diff options
| author | emmauss <emmausssss@gmail.com> | 2018-02-20 22:09:23 +0200 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-02-20 17:09:23 -0300 |
| commit | 62b827f474f0aa2152dd339fcc7cf31084e16a0b (patch) | |
| tree | 0e5c55b341aee4db0ccb841a084f253ec5e05657 /ChocolArm64/Decoder | |
| parent | cb665bb715834526d73c9469d16114b287faaecd (diff) | |
Split main project into core,graphics and chocolarm4 subproject (#29)
Diffstat (limited to 'ChocolArm64/Decoder')
58 files changed, 1641 insertions, 0 deletions
diff --git a/ChocolArm64/Decoder/ABlock.cs b/ChocolArm64/Decoder/ABlock.cs new file mode 100644 index 00000000..32974c1a --- /dev/null +++ b/ChocolArm64/Decoder/ABlock.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; + +namespace ChocolArm64.Decoder +{ + class ABlock + { + public long Position { get; set; } + public long EndPosition { get; set; } + + public ABlock Next { get; set; } + public ABlock Branch { get; set; } + + public List<AOpCode> OpCodes { get; private set; } + + public ABlock() + { + OpCodes = new List<AOpCode>(); + } + + public ABlock(long Position) : this() + { + this.Position = Position; + } + + public AOpCode GetLastOp() + { + if (OpCodes.Count > 0) + { + return OpCodes[OpCodes.Count - 1]; + } + + return null; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/ACond.cs b/ChocolArm64/Decoder/ACond.cs new file mode 100644 index 00000000..f2da8bd2 --- /dev/null +++ b/ChocolArm64/Decoder/ACond.cs @@ -0,0 +1,22 @@ +namespace ChocolArm64.Decoder +{ + enum ACond + { + Eq = 0, + Ne = 1, + Ge_Un = 2, + Lt_Un = 3, + Mi = 4, + Pl = 5, + Vs = 6, + Vc = 7, + Gt_Un = 8, + Le_Un = 9, + Ge = 10, + Lt = 11, + Gt = 12, + Le = 13, + Al = 14, + Nv = 15 + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/ADataOp.cs b/ChocolArm64/Decoder/ADataOp.cs new file mode 100644 index 00000000..a5601a3a --- /dev/null +++ b/ChocolArm64/Decoder/ADataOp.cs @@ -0,0 +1,10 @@ +namespace ChocolArm64.Decoder +{ + enum ADataOp + { + Adr = 0, + Arithmetic = 1, + Logical = 2, + BitField = 3 + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/ADecoder.cs b/ChocolArm64/Decoder/ADecoder.cs new file mode 100644 index 00000000..06a535c1 --- /dev/null +++ b/ChocolArm64/Decoder/ADecoder.cs @@ -0,0 +1,207 @@ +using ChocolArm64.Instruction; +using ChocolArm64.Memory; +using System; +using System.Collections.Generic; +using System.Reflection.Emit; + +namespace ChocolArm64.Decoder +{ + static class ADecoder + { + public static (ABlock[] Graph, ABlock Root) DecodeSubroutine(ATranslator Translator, long Start) + { + Dictionary<long, ABlock> Visited = new Dictionary<long, ABlock>(); + Dictionary<long, ABlock> VisitedEnd = new Dictionary<long, ABlock>(); + + Queue<ABlock> Blocks = new Queue<ABlock>(); + + ABlock Enqueue(long Position) + { + if (!Visited.TryGetValue(Position, out ABlock Output)) + { + Output = new ABlock(Position); + + Blocks.Enqueue(Output); + + Visited.Add(Position, Output); + } + + return Output; + } + + ABlock Root = Enqueue(Start); + + while (Blocks.Count > 0) + { + ABlock Current = Blocks.Dequeue(); + + FillBlock(Translator.Thread.Memory, Current); + + //Set child blocks. "Branch" is the block the branch instruction + //points to (when taken), "Next" is the block at the next address, + //executed when the branch is not taken. For Unconditional Branches + //(except BL/BLR that are sub calls) or end of executable, Next is null. + if (Current.OpCodes.Count > 0) + { + bool HasCachedSub = false; + + AOpCode LastOp = Current.GetLastOp(); + + if (LastOp is AOpCodeBImm Op) + { + if (Op.Emitter == AInstEmit.Bl) + { + HasCachedSub = Translator.HasCachedSub(Op.Imm); + } + else + { + Current.Branch = Enqueue(Op.Imm); + } + } + + if ((!(LastOp is AOpCodeBImmAl) && + !(LastOp is AOpCodeBReg)) || HasCachedSub) + { + Current.Next = Enqueue(Current.EndPosition); + } + } + + //If we have on the tree two blocks with the same end position, + //then we need to split the bigger block and have two small blocks, + //the end position of the bigger "Current" block should then be == to + //the position of the "Smaller" block. + while (VisitedEnd.TryGetValue(Current.EndPosition, out ABlock Smaller)) + { + if (Current.Position > Smaller.Position) + { + ABlock Temp = Smaller; + + Smaller = Current; + Current = Temp; + } + + Current.EndPosition = Smaller.Position; + Current.Next = Smaller; + Current.Branch = null; + + Current.OpCodes.RemoveRange( + Current.OpCodes.Count - Smaller.OpCodes.Count, + Smaller.OpCodes.Count); + + VisitedEnd[Smaller.EndPosition] = Smaller; + } + + VisitedEnd.Add(Current.EndPosition, Current); + } + + //Make and sort Graph blocks array by position. + ABlock[] Graph = new ABlock[Visited.Count]; + + while (Visited.Count > 0) + { + ulong FirstPos = ulong.MaxValue; + + foreach (ABlock Block in Visited.Values) + { + if (FirstPos > (ulong)Block.Position) + FirstPos = (ulong)Block.Position; + } + + ABlock Current = Visited[(long)FirstPos]; + + do + { + Graph[Graph.Length - Visited.Count] = Current; + + Visited.Remove(Current.Position); + + Current = Current.Next; + } + while (Current != null); + } + + return (Graph, Root); + } + + private static void FillBlock(AMemory Memory, ABlock Block) + { + long Position = Block.Position; + + AOpCode OpCode; + + do + { + OpCode = DecodeOpCode(Memory, Position); + + Block.OpCodes.Add(OpCode); + + Position += 4; + } + while (!(IsBranch(OpCode) || IsException(OpCode))); + + Block.EndPosition = Position; + } + + private static bool IsBranch(AOpCode OpCode) + { + return OpCode is AOpCodeBImm || + OpCode is AOpCodeBReg; + } + + private static bool IsException(AOpCode OpCode) + { + return OpCode.Emitter == AInstEmit.Brk || + OpCode.Emitter == AInstEmit.Svc || + OpCode.Emitter == AInstEmit.Und; + } + + public static AOpCode DecodeOpCode(AMemory Memory, long Position) + { + int OpCode = Memory.ReadInt32(Position); + + AInst Inst = AOpCodeTable.GetInst(OpCode); + + AOpCode DecodedOpCode = new AOpCode(AInst.Undefined, Position, OpCode); + + if (Inst.Type != null) + { + DecodedOpCode = CreateOpCode(Inst.Type, Inst, Position, OpCode); + } + + return DecodedOpCode; + } + + private delegate object OpActivator(AInst Inst, long Position, int OpCode); + + private static Dictionary<Type, OpActivator> Activators = new Dictionary<Type, OpActivator>(); + + private static AOpCode CreateOpCode(Type Type, AInst Inst, long Position, int OpCode) + { + if (Type == null) + { + throw new ArgumentNullException(nameof(Type)); + } + + if (!Activators.TryGetValue(Type, out OpActivator CreateInstance)) + { + Type[] ArgTypes = new Type[] { typeof(AInst), typeof(long), typeof(int) }; + + DynamicMethod Mthd = new DynamicMethod($"{Type.Name}_Create", Type, ArgTypes); + + ILGenerator Generator = Mthd.GetILGenerator(); + + Generator.Emit(OpCodes.Ldarg_0); + Generator.Emit(OpCodes.Ldarg_1); + Generator.Emit(OpCodes.Ldarg_2); + Generator.Emit(OpCodes.Newobj, Type.GetConstructor(ArgTypes)); + Generator.Emit(OpCodes.Ret); + + CreateInstance = (OpActivator)Mthd.CreateDelegate(typeof(OpActivator)); + + Activators.Add(Type, CreateInstance); + } + + return (AOpCode)CreateInstance(Inst, Position, OpCode); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/ADecoderHelper.cs b/ChocolArm64/Decoder/ADecoderHelper.cs new file mode 100644 index 00000000..a2179f49 --- /dev/null +++ b/ChocolArm64/Decoder/ADecoderHelper.cs @@ -0,0 +1,107 @@ +using System; + +namespace ChocolArm64.Decoder +{ + static class ADecoderHelper + { + public struct BitMask + { + public long WMask; + public long TMask; + public int Pos; + public int Shift; + public bool IsUndefined; + + public static BitMask Invalid => new BitMask { IsUndefined = true }; + } + + public static BitMask DecodeBitMask(int OpCode, bool Immediate) + { + int ImmS = (OpCode >> 10) & 0x3f; + int ImmR = (OpCode >> 16) & 0x3f; + + int N = (OpCode >> 22) & 1; + int SF = (OpCode >> 31) & 1; + + int Length = ABitUtils.HighestBitSet32((~ImmS & 0x3f) | (N << 6)); + + if (Length < 1 || (SF == 0 && N != 0)) + { + return BitMask.Invalid; + } + + int Size = 1 << Length; + + int Levels = Size - 1; + + int S = ImmS & Levels; + int R = ImmR & Levels; + + if (Immediate && S == Levels) + { + return BitMask.Invalid; + } + + long WMask = ABitUtils.FillWithOnes(S + 1); + long TMask = ABitUtils.FillWithOnes(((S - R) & Levels) + 1); + + if (R > 0) + { + WMask = ABitUtils.RotateRight(WMask, R, Size); + WMask &= ABitUtils.FillWithOnes(Size); + } + + return new BitMask() + { + WMask = ABitUtils.Replicate(WMask, Size), + TMask = ABitUtils.Replicate(TMask, Size), + + Pos = ImmS, + Shift = ImmR + }; + } + + public static long DecodeImm8Float(long Imm, int Size) + { + int E = 0, F = 0; + + switch (Size) + { + case 0: E = 8; F = 23; break; + case 1: E = 11; F = 52; break; + + default: throw new ArgumentOutOfRangeException(nameof(Size)); + } + + long Value = (Imm & 0x3f) << F - 4; + + long EBit = (Imm >> 6) & 1; + long SBit = (Imm >> 7) & 1; + + if (EBit != 0) + { + Value |= (1L << E - 3) - 1 << F + 2; + } + + Value |= (EBit ^ 1) << F + E - 1; + Value |= SBit << F + E; + + return Value; + } + + public static long DecodeImm26_2(int OpCode) + { + return ((long)OpCode << 38) >> 36; + } + + public static long DecodeImmS19_2(int OpCode) + { + return (((long)OpCode << 40) >> 43) & ~3; + } + + public static long DecodeImmS14_2(int OpCode) + { + return (((long)OpCode << 45) >> 48) & ~3; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AIntType.cs b/ChocolArm64/Decoder/AIntType.cs new file mode 100644 index 00000000..242fdada --- /dev/null +++ b/ChocolArm64/Decoder/AIntType.cs @@ -0,0 +1,14 @@ +namespace ChocolArm64.Decoder +{ + enum AIntType + { + UInt8 = 0, + UInt16 = 1, + UInt32 = 2, + UInt64 = 3, + Int8 = 4, + Int16 = 5, + Int32 = 6, + Int64 = 7 + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCode.cs b/ChocolArm64/Decoder/AOpCode.cs new file mode 100644 index 00000000..5d127593 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCode.cs @@ -0,0 +1,38 @@ +using ChocolArm64.Instruction; +using ChocolArm64.State; +using System; + +namespace ChocolArm64.Decoder +{ + class AOpCode : IAOpCode + { + public long Position { get; private set; } + public int RawOpCode { get; private set; } + + public AInstEmitter Emitter { get; protected set; } + public ARegisterSize RegisterSize { get; protected set; } + + public AOpCode(AInst Inst, long Position, int OpCode) + { + this.Position = Position; + this.RawOpCode = OpCode; + + RegisterSize = ARegisterSize.Int64; + + Emitter = Inst.Emitter; + } + + public int GetBitsCount() + { + switch (RegisterSize) + { + case ARegisterSize.Int32: return 32; + case ARegisterSize.Int64: return 64; + case ARegisterSize.SIMD64: return 64; + case ARegisterSize.SIMD128: return 128; + } + + throw new InvalidOperationException(); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeAdr.cs b/ChocolArm64/Decoder/AOpCodeAdr.cs new file mode 100644 index 00000000..3396281f --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeAdr.cs @@ -0,0 +1,18 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeAdr : AOpCode + { + public int Rd { get; private set; } + public long Imm { get; private set; } + + public AOpCodeAdr(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rd = OpCode & 0x1f; + + Imm = ADecoderHelper.DecodeImmS19_2(OpCode); + Imm |= ((long)OpCode >> 29) & 3; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeAlu.cs b/ChocolArm64/Decoder/AOpCodeAlu.cs new file mode 100644 index 00000000..e1a44f04 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeAlu.cs @@ -0,0 +1,24 @@ +using ChocolArm64.Instruction; +using ChocolArm64.State; + +namespace ChocolArm64.Decoder +{ + class AOpCodeAlu : AOpCode, IAOpCodeAlu + { + public int Rd { get; protected set; } + public int Rn { get; private set; } + + public ADataOp DataOp { get; private set; } + + public AOpCodeAlu(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rd = (OpCode >> 0) & 0x1f; + Rn = (OpCode >> 5) & 0x1f; + DataOp = (ADataOp)((OpCode >> 24) & 0x3); + + RegisterSize = (OpCode >> 31) != 0 + ? ARegisterSize.Int64 + : ARegisterSize.Int32; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeAluImm.cs b/ChocolArm64/Decoder/AOpCodeAluImm.cs new file mode 100644 index 00000000..e913475a --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeAluImm.cs @@ -0,0 +1,39 @@ +using ChocolArm64.Instruction; +using System; + +namespace ChocolArm64.Decoder +{ + class AOpCodeAluImm : AOpCodeAlu, IAOpCodeAluImm + { + public long Imm { get; private set; } + + public AOpCodeAluImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + if (DataOp == ADataOp.Arithmetic) + { + Imm = (OpCode >> 10) & 0xfff; + + int Shift = (OpCode >> 22) & 3; + + Imm <<= Shift * 12; + } + else if (DataOp == ADataOp.Logical) + { + var BM = ADecoderHelper.DecodeBitMask(OpCode, true); + + if (BM.IsUndefined) + { + Emitter = AInstEmit.Und; + + return; + } + + Imm = BM.WMask; + } + else + { + throw new ArgumentException(nameof(OpCode)); + } + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeAluRs.cs b/ChocolArm64/Decoder/AOpCodeAluRs.cs new file mode 100644 index 00000000..9c215be3 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeAluRs.cs @@ -0,0 +1,29 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeAluRs : AOpCodeAlu, IAOpCodeAluRs + { + public int Shift { get; private set; } + public int Rm { get; private set; } + + public AShiftType ShiftType { get; private set; } + + public AOpCodeAluRs(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + int Shift = (OpCode >> 10) & 0x3f; + + if (Shift >= GetBitsCount()) + { + Emitter = AInstEmit.Und; + + return; + } + + this.Shift = Shift; + + Rm = (OpCode >> 16) & 0x1f; + ShiftType = (AShiftType)((OpCode >> 22) & 0x3); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeAluRx.cs b/ChocolArm64/Decoder/AOpCodeAluRx.cs new file mode 100644 index 00000000..7dd72a68 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeAluRx.cs @@ -0,0 +1,19 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeAluRx : AOpCodeAlu, IAOpCodeAluRx + { + public int Shift { get; private set; } + public int Rm { get; private set; } + + public AIntType IntType { get; private set; } + + public AOpCodeAluRx(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Shift = (OpCode >> 10) & 0x7; + IntType = (AIntType)((OpCode >> 13) & 0x7); + Rm = (OpCode >> 16) & 0x1f; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeBImm.cs b/ChocolArm64/Decoder/AOpCodeBImm.cs new file mode 100644 index 00000000..6519d281 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeBImm.cs @@ -0,0 +1,11 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeBImm : AOpCode + { + public long Imm { get; protected set; } + + public AOpCodeBImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeBImmAl.cs b/ChocolArm64/Decoder/AOpCodeBImmAl.cs new file mode 100644 index 00000000..a4ff686d --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeBImmAl.cs @@ -0,0 +1,12 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeBImmAl : AOpCodeBImm + { + public AOpCodeBImmAl(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Imm = Position + ADecoderHelper.DecodeImm26_2(OpCode); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeBImmCmp.cs b/ChocolArm64/Decoder/AOpCodeBImmCmp.cs new file mode 100644 index 00000000..1b6185da --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeBImmCmp.cs @@ -0,0 +1,16 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeBImmCmp : AOpCodeBImm + { + public int Rt { get; private set; } + + public AOpCodeBImmCmp(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rt = OpCode & 0x1f; + + Imm = Position + ADecoderHelper.DecodeImmS19_2(OpCode); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeBImmCond.cs b/ChocolArm64/Decoder/AOpCodeBImmCond.cs new file mode 100644 index 00000000..1310feb8 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeBImmCond.cs @@ -0,0 +1,25 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeBImmCond : AOpCodeBImm, IAOpCodeCond + { + public ACond Cond { get; private set; } + + public AOpCodeBImmCond(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + int O0 = (OpCode >> 4) & 1; + + if (O0 != 0) + { + Emitter = AInstEmit.Und; + + return; + } + + Cond = (ACond)(OpCode & 0xf); + + Imm = Position + ADecoderHelper.DecodeImmS19_2(OpCode); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeBImmTest.cs b/ChocolArm64/Decoder/AOpCodeBImmTest.cs new file mode 100644 index 00000000..73e57b7a --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeBImmTest.cs @@ -0,0 +1,20 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeBImmTest : AOpCodeBImm + { + public int Rt { get; private set; } + public int Pos { get; private set; } + + public AOpCodeBImmTest(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rt = OpCode & 0x1f; + + Imm = Position + ADecoderHelper.DecodeImmS14_2(OpCode); + + Pos = (OpCode >> 19) & 0x1f; + Pos |= (OpCode >> 26) & 0x20; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeBReg.cs b/ChocolArm64/Decoder/AOpCodeBReg.cs new file mode 100644 index 00000000..c9c600af --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeBReg.cs @@ -0,0 +1,24 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeBReg : AOpCode + { + public int Rn { get; private set; } + + public AOpCodeBReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + int Op4 = (OpCode >> 0) & 0x1f; + int Op2 = (OpCode >> 16) & 0x1f; + + if (Op2 != 0b11111 || Op4 != 0b00000) + { + Emitter = AInstEmit.Und; + + return; + } + + Rn = (OpCode >> 5) & 0x1f; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeBfm.cs b/ChocolArm64/Decoder/AOpCodeBfm.cs new file mode 100644 index 00000000..6498d8ec --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeBfm.cs @@ -0,0 +1,29 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeBfm : AOpCodeAlu + { + public long WMask { get; private set; } + public long TMask { get; private set; } + public int Pos { get; private set; } + public int Shift { get; private set; } + + public AOpCodeBfm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + var BM = ADecoderHelper.DecodeBitMask(OpCode, false); + + if (BM.IsUndefined) + { + Emitter = AInstEmit.Und; + + return; + } + + WMask = BM.WMask; + TMask = BM.TMask; + Pos = BM.Pos; + Shift = BM.Shift; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeCcmp.cs b/ChocolArm64/Decoder/AOpCodeCcmp.cs new file mode 100644 index 00000000..d0c7f779 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeCcmp.cs @@ -0,0 +1,31 @@ +using ChocolArm64.Instruction; +using ChocolArm64.State; + +namespace ChocolArm64.Decoder +{ + class AOpCodeCcmp : AOpCodeAlu, IAOpCodeCond + { + public int NZCV { get; private set; } + protected int RmImm; + + public ACond Cond { get; private set; } + + public AOpCodeCcmp(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + int O3 = (OpCode >> 4) & 1; + + if (O3 != 0) + { + Emitter = AInstEmit.Und; + + return; + } + + NZCV = (OpCode >> 0) & 0xf; + Cond = (ACond)((OpCode >> 12) & 0xf); + RmImm = (OpCode >> 16) & 0x1f; + + Rd = AThreadState.ZRIndex; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeCcmpImm.cs b/ChocolArm64/Decoder/AOpCodeCcmpImm.cs new file mode 100644 index 00000000..803eefc2 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeCcmpImm.cs @@ -0,0 +1,11 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeCcmpImm : AOpCodeCcmp, IAOpCodeAluImm + { + public long Imm => RmImm; + + public AOpCodeCcmpImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeCcmpReg.cs b/ChocolArm64/Decoder/AOpCodeCcmpReg.cs new file mode 100644 index 00000000..c364ae68 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeCcmpReg.cs @@ -0,0 +1,15 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeCcmpReg : AOpCodeCcmp, IAOpCodeAluRs + { + public int Rm => RmImm; + + public int Shift => 0; + + public AShiftType ShiftType => AShiftType.Lsl; + + public AOpCodeCcmpReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) { } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeCsel.cs b/ChocolArm64/Decoder/AOpCodeCsel.cs new file mode 100644 index 00000000..cdef3e74 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeCsel.cs @@ -0,0 +1,17 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeCsel : AOpCodeAlu, IAOpCodeCond + { + public int Rm { get; private set; } + + public ACond Cond { get; private set; } + + public AOpCodeCsel(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rm = (OpCode >> 16) & 0x1f; + Cond = (ACond)((OpCode >> 12) & 0xf); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeException.cs b/ChocolArm64/Decoder/AOpCodeException.cs new file mode 100644 index 00000000..4579c1a7 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeException.cs @@ -0,0 +1,14 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeException : AOpCode + { + public int Id { get; private set; } + + public AOpCodeException(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Id = (OpCode >> 5) & 0xffff; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeMem.cs b/ChocolArm64/Decoder/AOpCodeMem.cs new file mode 100644 index 00000000..be5367cf --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeMem.cs @@ -0,0 +1,19 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeMem : AOpCode + { + public int Rt { get; protected set; } + public int Rn { get; protected set; } + public int Size { get; protected set; } + public bool Extend64 { get; protected set; } + + public AOpCodeMem(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rt = (OpCode >> 0) & 0x1f; + Rn = (OpCode >> 5) & 0x1f; + Size = (OpCode >> 30) & 0x3; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeMemEx.cs b/ChocolArm64/Decoder/AOpCodeMemEx.cs new file mode 100644 index 00000000..3a28cfd7 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeMemEx.cs @@ -0,0 +1,16 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeMemEx : AOpCodeMem + { + public int Rt2 { get; private set; } + public int Rs { get; private set; } + + public AOpCodeMemEx(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rt2 = (OpCode >> 10) & 0x1f; + Rs = (OpCode >> 16) & 0x1f; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeMemImm.cs b/ChocolArm64/Decoder/AOpCodeMemImm.cs new file mode 100644 index 00000000..14edc514 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeMemImm.cs @@ -0,0 +1,53 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeMemImm : AOpCodeMem + { + public long Imm { get; protected set; } + public bool WBack { get; protected set; } + public bool PostIdx { get; protected set; } + protected bool Unscaled { get; private set; } + + private enum MemOp + { + Unscaled = 0, + PostIndexed = 1, + Unprivileged = 2, + PreIndexed = 3, + Unsigned + } + + public AOpCodeMemImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Extend64 = ((OpCode >> 22) & 3) == 2; + WBack = ((OpCode >> 24) & 1) == 0; + + //The type is not valid for the Unsigned Immediate 12-bits encoding, + //because the bits 11:10 are used for the larger Immediate offset. + MemOp Type = WBack ? (MemOp)((OpCode >> 10) & 3) : MemOp.Unsigned; + + PostIdx = Type == MemOp.PostIndexed; + Unscaled = Type == MemOp.Unscaled || + Type == MemOp.Unprivileged; + + //Unscaled and Unprivileged doesn't write back, + //but they do use the 9-bits Signed Immediate. + if (Unscaled) + { + WBack = false; + } + + if (WBack || Unscaled) + { + //9-bits Signed Immediate. + Imm = (OpCode << 43) >> 55; + } + else + { + //12-bits Unsigned Immediate. + Imm = ((OpCode >> 10) & 0xfff) << Size; + } + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeMemLit.cs b/ChocolArm64/Decoder/AOpCodeMemLit.cs new file mode 100644 index 00000000..ad719a19 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeMemLit.cs @@ -0,0 +1,28 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeMemLit : AOpCode, IAOpCodeLit + { + public int Rt { get; private set; } + public long Imm { get; private set; } + public int Size { get; private set; } + public bool Signed { get; private set; } + public bool Prefetch { get; private set; } + + public AOpCodeMemLit(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rt = OpCode & 0x1f; + + Imm = Position + ADecoderHelper.DecodeImmS19_2(OpCode); + + switch ((OpCode >> 30) & 3) + { + case 0: Size = 2; Signed = false; Prefetch = false; break; + case 1: Size = 3; Signed = false; Prefetch = false; break; + case 2: Size = 2; Signed = true; Prefetch = false; break; + case 3: Size = 0; Signed = false; Prefetch = true; break; + } + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeMemPair.cs b/ChocolArm64/Decoder/AOpCodeMemPair.cs new file mode 100644 index 00000000..ec866c84 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeMemPair.cs @@ -0,0 +1,25 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeMemPair : AOpCodeMemImm + { + public int Rt2 { get; private set; } + + public AOpCodeMemPair(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rt2 = (OpCode >> 10) & 0x1f; + WBack = ((OpCode >> 23) & 0x1) != 0; + PostIdx = ((OpCode >> 23) & 0x3) == 1; + Extend64 = ((OpCode >> 30) & 0x3) == 1; + Size = ((OpCode >> 31) & 0x1) | 2; + + DecodeImm(OpCode); + } + + protected void DecodeImm(int OpCode) + { + Imm = ((long)(OpCode >> 15) << 57) >> (57 - Size); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeMemReg.cs b/ChocolArm64/Decoder/AOpCodeMemReg.cs new file mode 100644 index 00000000..98927128 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeMemReg.cs @@ -0,0 +1,20 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeMemReg : AOpCodeMem + { + public bool Shift { get; private set; } + public int Rm { get; private set; } + + public AIntType IntType { get; private set; } + + public AOpCodeMemReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Shift = ((OpCode >> 12) & 0x1) != 0; + IntType = (AIntType)((OpCode >> 13) & 0x7); + Rm = (OpCode >> 16) & 0x1f; + Extend64 = ((OpCode >> 22) & 0x3) == 2; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeMov.cs b/ChocolArm64/Decoder/AOpCodeMov.cs new file mode 100644 index 00000000..d5398646 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeMov.cs @@ -0,0 +1,36 @@ +using ChocolArm64.Instruction; +using ChocolArm64.State; + +namespace ChocolArm64.Decoder +{ + class AOpCodeMov : AOpCode + { + public int Rd { get; private set; } + public long Imm { get; private set; } + public int Pos { get; private set; } + + public AOpCodeMov(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + int P1 = (OpCode >> 22) & 1; + int SF = (OpCode >> 31) & 1; + + if (SF == 0 && P1 != 0) + { + Emitter = AInstEmit.Und; + + return; + } + + Rd = (OpCode >> 0) & 0x1f; + Imm = (OpCode >> 5) & 0xffff; + Pos = (OpCode >> 21) & 0x3; + + Pos <<= 4; + Imm <<= Pos; + + RegisterSize = (OpCode >> 31) != 0 + ? ARegisterSize.Int64 + : ARegisterSize.Int32; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeMul.cs b/ChocolArm64/Decoder/AOpCodeMul.cs new file mode 100644 index 00000000..ca2b0cdb --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeMul.cs @@ -0,0 +1,16 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeMul : AOpCodeAlu + { + public int Rm { get; private set; } + public int Ra { get; private set; } + + public AOpCodeMul(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Ra = (OpCode >> 10) & 0x1f; + Rm = (OpCode >> 16) & 0x1f; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimd.cs b/ChocolArm64/Decoder/AOpCodeSimd.cs new file mode 100644 index 00000000..5f940b22 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimd.cs @@ -0,0 +1,27 @@ +using ChocolArm64.Instruction; +using ChocolArm64.State; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimd : AOpCode, IAOpCodeSimd + { + public int Rd { get; private set; } + public int Rn { get; private set; } + public int Opc { get; private set; } + public int Size { get; protected set; } + + public int SizeF => Size & 1; + + public AOpCodeSimd(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rd = (OpCode >> 0) & 0x1f; + Rn = (OpCode >> 5) & 0x1f; + Opc = (OpCode >> 15) & 0x3; + Size = (OpCode >> 22) & 0x3; + + RegisterSize = ((OpCode >> 30) & 1) != 0 + ? ARegisterSize.SIMD128 + : ARegisterSize.SIMD64; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdCvt.cs b/ChocolArm64/Decoder/AOpCodeSimdCvt.cs new file mode 100644 index 00000000..41f4d3b1 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdCvt.cs @@ -0,0 +1,31 @@ +using ChocolArm64.Instruction; +using ChocolArm64.State; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdCvt : AOpCodeSimd + { + public int FBits { get; private set; } + + public AOpCodeSimdCvt(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + //TODO: + //Und of Fixed Point variants. + int Scale = (OpCode >> 10) & 0x3f; + int SF = (OpCode >> 31) & 0x1; + + /*if (Type != SF && !(Type == 2 && SF == 1)) + { + Emitter = AInstEmit.Und; + + return; + }*/ + + FBits = 64 - Scale; + + RegisterSize = SF != 0 + ? ARegisterSize.Int64 + : ARegisterSize.Int32; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdFcond.cs b/ChocolArm64/Decoder/AOpCodeSimdFcond.cs new file mode 100644 index 00000000..e38e7424 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdFcond.cs @@ -0,0 +1,17 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdFcond : AOpCodeSimdReg, IAOpCodeCond + { + public int NZCV { get; private set; } + + public ACond Cond { get; private set; } + + public AOpCodeSimdFcond(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + NZCV = (OpCode >> 0) & 0xf; + Cond = (ACond)((OpCode >> 12) & 0xf); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdFmov.cs b/ChocolArm64/Decoder/AOpCodeSimdFmov.cs new file mode 100644 index 00000000..3f888959 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdFmov.cs @@ -0,0 +1,33 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdFmov : AOpCode, IAOpCodeSimd + { + public int Rd { get; private set; } + public long Imm { get; private set; } + public int Size { get; private set; } + + public AOpCodeSimdFmov(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + int Imm5 = (OpCode >> 5) & 0x1f; + int Type = (OpCode >> 22) & 0x3; + + if (Imm5 != 0b00000 || Type > 1) + { + Emitter = AInstEmit.Und; + + return; + } + + Size = Type; + + long Imm; + + Rd = (OpCode >> 0) & 0x1f; + Imm = (OpCode >> 13) & 0xff; + + this.Imm = ADecoderHelper.DecodeImm8Float(Imm, Type); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdImm.cs b/ChocolArm64/Decoder/AOpCodeSimdImm.cs new file mode 100644 index 00000000..2959aee6 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdImm.cs @@ -0,0 +1,94 @@ +using ChocolArm64.Instruction; +using ChocolArm64.State; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdImm : AOpCode, IAOpCodeSimd + { + public int Rd { get; private set; } + public long Imm { get; private set; } + public int Size { get; private set; } + + public AOpCodeSimdImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rd = OpCode & 0x1f; + + int CMode = (OpCode >> 12) & 0xf; + int Op = (OpCode >> 29) & 0x1; + + int ModeLow = CMode & 1; + int ModeHigh = CMode >> 1; + + long Imm; + + Imm = ((uint)OpCode >> 5) & 0x1f; + Imm |= ((uint)OpCode >> 11) & 0xe0; + + if (ModeHigh == 0b111) + { + Size = ModeLow != 0 ? Op : 3; + + switch (Op | (ModeLow << 1)) + { + case 0: + //64-bits Immediate. + //Transform abcd efgh into abcd efgh abcd efgh ... + Imm = (long)((ulong)Imm * 0x0101010101010101); + break; + + case 1: + //64-bits Immediate. + //Transform abcd efgh into aaaa aaaa bbbb bbbb ... + Imm = (Imm & 0xf0) >> 4 | (Imm & 0x0f) << 4; + Imm = (Imm & 0xcc) >> 2 | (Imm & 0x33) << 2; + Imm = (Imm & 0xaa) >> 1 | (Imm & 0x55) << 1; + + Imm = (long)((ulong)Imm * 0x8040201008040201); + Imm = (long)((ulong)Imm & 0x8080808080808080); + + Imm |= Imm >> 4; + Imm |= Imm >> 2; + Imm |= Imm >> 1; + break; + + case 2: + case 3: + //Floating point Immediate. + Imm = ADecoderHelper.DecodeImm8Float(Imm, Size); + break; + } + } + else if ((ModeHigh & 0b110) == 0b100) + { + //16-bits shifted Immediate. + Size = 1; Imm <<= (ModeHigh & 1) << 3; + } + else if ((ModeHigh & 0b100) == 0b000) + { + //32-bits shifted Immediate. + Size = 2; Imm <<= ModeHigh << 3; + } + else if ((ModeHigh & 0b111) == 0b110) + { + //32-bits shifted Immediate (fill with ones). + Size = 2; Imm = ShlOnes(Imm, 8 << ModeLow); + } + else + { + //8 bits without shift. + Size = 0; + } + + this.Imm = Imm; + + RegisterSize = ((OpCode >> 30) & 1) != 0 + ? ARegisterSize.SIMD128 + : ARegisterSize.SIMD64; + } + + private static long ShlOnes(long Value, int Shift) + { + return Value << Shift | (long)(ulong.MaxValue >> (64 - Shift)); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdIns.cs b/ChocolArm64/Decoder/AOpCodeSimdIns.cs new file mode 100644 index 00000000..0b60bbe8 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdIns.cs @@ -0,0 +1,36 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdIns : AOpCodeSimd + { + public int SrcIndex { get; private set; } + public int DstIndex { get; private set; } + + public AOpCodeSimdIns(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + int Imm4 = (OpCode >> 11) & 0xf; + int Imm5 = (OpCode >> 16) & 0x1f; + + if (Imm5 == 0b10000) + { + Emitter = AInstEmit.Und; + + return; + } + + Size = Imm5 & -Imm5; + + switch (Size) + { + case 1: Size = 0; break; + case 2: Size = 1; break; + case 4: Size = 2; break; + case 8: Size = 3; break; + } + + SrcIndex = Imm4 >> Size; + DstIndex = Imm5 >> (Size + 1); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdMemImm.cs b/ChocolArm64/Decoder/AOpCodeSimdMemImm.cs new file mode 100644 index 00000000..1ef19a5d --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdMemImm.cs @@ -0,0 +1,19 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdMemImm : AOpCodeMemImm, IAOpCodeSimd + { + public AOpCodeSimdMemImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Size |= (OpCode >> 21) & 4; + + if (!WBack && !Unscaled && Size >= 4) + { + Imm <<= 4; + } + + Extend64 = false; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdMemLit.cs b/ChocolArm64/Decoder/AOpCodeSimdMemLit.cs new file mode 100644 index 00000000..ea6fe00b --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdMemLit.cs @@ -0,0 +1,31 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdMemLit : AOpCode, IAOpCodeSimd, IAOpCodeLit + { + public int Rt { get; private set; } + public long Imm { get; private set; } + public int Size { get; private set; } + public bool Signed => false; + public bool Prefetch => false; + + public AOpCodeSimdMemLit(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + int Opc = (OpCode >> 30) & 3; + + if (Opc == 3) + { + Emitter = AInstEmit.Und; + + return; + } + + Rt = OpCode & 0x1f; + + Imm = Position + ADecoderHelper.DecodeImmS19_2(OpCode); + + Size = Opc + 2; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdMemMs.cs b/ChocolArm64/Decoder/AOpCodeSimdMemMs.cs new file mode 100644 index 00000000..9ea979ba --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdMemMs.cs @@ -0,0 +1,49 @@ +using ChocolArm64.Instruction; +using ChocolArm64.State; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdMemMs : AOpCodeMemReg, IAOpCodeSimd + { + public int Reps { get; private set; } + public int SElems { get; private set; } + public int Elems { get; private set; } + public bool WBack { get; private set; } + + public AOpCodeSimdMemMs(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + switch ((OpCode >> 12) & 0xf) + { + case 0b0000: Reps = 1; SElems = 4; break; + case 0b0010: Reps = 4; SElems = 1; break; + case 0b0100: Reps = 1; SElems = 3; break; + case 0b0110: Reps = 3; SElems = 1; break; + case 0b0111: Reps = 1; SElems = 1; break; + case 0b1000: Reps = 1; SElems = 2; break; + case 0b1010: Reps = 2; SElems = 1; break; + + default: Inst = AInst.Undefined; return; + } + + Size = (OpCode >> 10) & 0x3; + WBack = ((OpCode >> 23) & 0x1) != 0; + + bool Q = ((OpCode >> 30) & 1) != 0; + + if (!Q && Size == 3 && SElems != 1) + { + Inst = AInst.Undefined; + + return; + } + + Extend64 = false; + + RegisterSize = Q + ? ARegisterSize.SIMD128 + : ARegisterSize.SIMD64; + + Elems = (GetBitsCount() >> 3) >> Size; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdMemPair.cs b/ChocolArm64/Decoder/AOpCodeSimdMemPair.cs new file mode 100644 index 00000000..db99e3d4 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdMemPair.cs @@ -0,0 +1,16 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdMemPair : AOpCodeMemPair, IAOpCodeSimd + { + public AOpCodeSimdMemPair(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Size = ((OpCode >> 30) & 3) + 2; + + Extend64 = false; + + DecodeImm(OpCode); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdMemReg.cs b/ChocolArm64/Decoder/AOpCodeSimdMemReg.cs new file mode 100644 index 00000000..aabf4846 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdMemReg.cs @@ -0,0 +1,14 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdMemReg : AOpCodeMemReg, IAOpCodeSimd + { + public AOpCodeSimdMemReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Size |= (OpCode >> 21) & 4; + + Extend64 = false; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdMemSs.cs b/ChocolArm64/Decoder/AOpCodeSimdMemSs.cs new file mode 100644 index 00000000..be4a8cd9 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdMemSs.cs @@ -0,0 +1,97 @@ +using ChocolArm64.Instruction; +using ChocolArm64.State; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdMemSs : AOpCodeMemReg, IAOpCodeSimd + { + public int SElems { get; private set; } + public int Index { get; private set; } + public bool Replicate { get; private set; } + public bool WBack { get; private set; } + + public AOpCodeSimdMemSs(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + int Size = (OpCode >> 10) & 3; + int S = (OpCode >> 12) & 1; + int SElems = (OpCode >> 12) & 2; + int Scale = (OpCode >> 14) & 3; + int L = (OpCode >> 22) & 1; + int Q = (OpCode >> 30) & 1; + + SElems |= (OpCode >> 21) & 1; + + SElems++; + + int Index = (Q << 3) | (S << 2) | Size; + + switch (Scale) + { + case 1: + { + if ((Size & 1) != 0) + { + Inst = AInst.Undefined; + + return; + } + + Index >>= 1; + + break; + } + + case 2: + { + if ((Size & 2) != 0 || + ((Size & 1) != 0 && S != 0)) + { + Inst = AInst.Undefined; + + return; + } + + if ((Size & 1) != 0) + { + Index >>= 3; + + Scale = 3; + } + else + { + Index >>= 2; + } + + break; + } + + case 3: + { + if (L == 0 || S != 0) + { + Inst = AInst.Undefined; + + return; + } + + Scale = Size; + + Replicate = true; + + break; + } + } + + this.SElems = SElems; + this.Size = Scale; + + Extend64 = false; + + WBack = ((OpCode >> 23) & 0x1) != 0; + + RegisterSize = Q != 0 + ? ARegisterSize.SIMD128 + : ARegisterSize.SIMD64; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdReg.cs b/ChocolArm64/Decoder/AOpCodeSimdReg.cs new file mode 100644 index 00000000..10a4aff8 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdReg.cs @@ -0,0 +1,18 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdReg : AOpCodeSimd + { + public bool Bit3 { get; private set; } + public int Ra { get; private set; } + public int Rm { get; private set; } + + public AOpCodeSimdReg(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Bit3 = ((OpCode >> 3) & 0x1) != 0; + Ra = (OpCode >> 10) & 0x1f; + Rm = (OpCode >> 16) & 0x1f; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdRegElem.cs b/ChocolArm64/Decoder/AOpCodeSimdRegElem.cs new file mode 100644 index 00000000..d878b12e --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdRegElem.cs @@ -0,0 +1,22 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdRegElem : AOpCodeSimdReg + { + public int Index { get; private set; } + + public AOpCodeSimdRegElem(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + if ((Size & 1) != 0) + { + Index = (OpCode >> 11) & 1; + } + else + { + Index = (OpCode >> 21) & 1 | + (OpCode >> 10) & 2; + } + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdShImm.cs b/ChocolArm64/Decoder/AOpCodeSimdShImm.cs new file mode 100644 index 00000000..6c839881 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdShImm.cs @@ -0,0 +1,16 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdShImm : AOpCodeSimd + { + public int Imm { get; private set; } + + public AOpCodeSimdShImm(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Imm = (OpCode >> 16) & 0x7f; + + Size = ABitUtils.HighestBitSet32(Imm >> 3); + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSimdTbl.cs b/ChocolArm64/Decoder/AOpCodeSimdTbl.cs new file mode 100644 index 00000000..c8ae5bac --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSimdTbl.cs @@ -0,0 +1,12 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSimdTbl : AOpCodeSimdReg + { + public AOpCodeSimdTbl(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Size = ((OpCode >> 13) & 3) + 1; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AOpCodeSystem.cs b/ChocolArm64/Decoder/AOpCodeSystem.cs new file mode 100644 index 00000000..3d81a5d4 --- /dev/null +++ b/ChocolArm64/Decoder/AOpCodeSystem.cs @@ -0,0 +1,24 @@ +using ChocolArm64.Instruction; + +namespace ChocolArm64.Decoder +{ + class AOpCodeSystem : AOpCode + { + public int Rt { get; private set; } + public int Op2 { get; private set; } + public int CRm { get; private set; } + public int CRn { get; private set; } + public int Op1 { get; private set; } + public int Op0 { get; private set; } + + public AOpCodeSystem(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) + { + Rt = (OpCode >> 0) & 0x1f; + Op2 = (OpCode >> 5) & 0x7; + CRm = (OpCode >> 8) & 0xf; + CRn = (OpCode >> 12) & 0xf; + Op1 = (OpCode >> 16) & 0x7; + Op0 = ((OpCode >> 19) & 0x1) | 2; + } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/AShiftType.cs b/ChocolArm64/Decoder/AShiftType.cs new file mode 100644 index 00000000..34ceea20 --- /dev/null +++ b/ChocolArm64/Decoder/AShiftType.cs @@ -0,0 +1,10 @@ +namespace ChocolArm64.Decoder +{ + enum AShiftType + { + Lsl, + Lsr, + Asr, + Ror + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/IAOpCode.cs b/ChocolArm64/Decoder/IAOpCode.cs new file mode 100644 index 00000000..44bf9cb2 --- /dev/null +++ b/ChocolArm64/Decoder/IAOpCode.cs @@ -0,0 +1,13 @@ +using ChocolArm64.Instruction; +using ChocolArm64.State; + +namespace ChocolArm64.Decoder +{ + interface IAOpCode + { + long Position { get; } + + AInstEmitter Emitter { get; } + ARegisterSize RegisterSize { get; } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/IAOpCodeAlu.cs b/ChocolArm64/Decoder/IAOpCodeAlu.cs new file mode 100644 index 00000000..22af4c82 --- /dev/null +++ b/ChocolArm64/Decoder/IAOpCodeAlu.cs @@ -0,0 +1,10 @@ +namespace ChocolArm64.Decoder +{ + interface IAOpCodeAlu : IAOpCode + { + int Rd { get; } + int Rn { get; } + + ADataOp DataOp { get; } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/IAOpCodeAluImm.cs b/ChocolArm64/Decoder/IAOpCodeAluImm.cs new file mode 100644 index 00000000..04b5c5f7 --- /dev/null +++ b/ChocolArm64/Decoder/IAOpCodeAluImm.cs @@ -0,0 +1,7 @@ +namespace ChocolArm64.Decoder +{ + interface IAOpCodeAluImm : IAOpCodeAlu + { + long Imm { get; } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/IAOpCodeAluRs.cs b/ChocolArm64/Decoder/IAOpCodeAluRs.cs new file mode 100644 index 00000000..5ca9de40 --- /dev/null +++ b/ChocolArm64/Decoder/IAOpCodeAluRs.cs @@ -0,0 +1,10 @@ +namespace ChocolArm64.Decoder +{ + interface IAOpCodeAluRs : IAOpCodeAlu + { + int Shift { get; } + int Rm { get; } + + AShiftType ShiftType { get; } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/IAOpCodeAluRx.cs b/ChocolArm64/Decoder/IAOpCodeAluRx.cs new file mode 100644 index 00000000..b49d5325 --- /dev/null +++ b/ChocolArm64/Decoder/IAOpCodeAluRx.cs @@ -0,0 +1,10 @@ +namespace ChocolArm64.Decoder +{ + interface IAOpCodeAluRx : IAOpCodeAlu + { + int Shift { get; } + int Rm { get; } + + AIntType IntType { get; } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/IAOpCodeCond.cs b/ChocolArm64/Decoder/IAOpCodeCond.cs new file mode 100644 index 00000000..1655abaa --- /dev/null +++ b/ChocolArm64/Decoder/IAOpCodeCond.cs @@ -0,0 +1,7 @@ +namespace ChocolArm64.Decoder +{ + interface IAOpCodeCond : IAOpCode + { + ACond Cond { get; } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/IAOpCodeLit.cs b/ChocolArm64/Decoder/IAOpCodeLit.cs new file mode 100644 index 00000000..0f5092d0 --- /dev/null +++ b/ChocolArm64/Decoder/IAOpCodeLit.cs @@ -0,0 +1,11 @@ +namespace ChocolArm64.Decoder +{ + interface IAOpCodeLit : IAOpCode + { + int Rt { get; } + long Imm { get; } + int Size { get; } + bool Signed { get; } + bool Prefetch { get; } + } +}
\ No newline at end of file diff --git a/ChocolArm64/Decoder/IAOpCodeSimd.cs b/ChocolArm64/Decoder/IAOpCodeSimd.cs new file mode 100644 index 00000000..19032ad9 --- /dev/null +++ b/ChocolArm64/Decoder/IAOpCodeSimd.cs @@ -0,0 +1,7 @@ +namespace ChocolArm64.Decoder +{ + interface IAOpCodeSimd : IAOpCode + { + int Size { get; } + } +}
\ No newline at end of file |
