diff options
Diffstat (limited to 'ARMeilleure/Decoders')
44 files changed, 766 insertions, 57 deletions
diff --git a/ARMeilleure/Decoders/Decoder.cs b/ARMeilleure/Decoders/Decoder.cs index eb085999..46774f41 100644 --- a/ARMeilleure/Decoders/Decoder.cs +++ b/ARMeilleure/Decoders/Decoder.cs @@ -195,12 +195,13 @@ namespace ARMeilleure.Decoders ulong limitAddress) { ulong address = block.Address; + int itBlockSize = 0; OpCode opCode; do { - if (address >= limitAddress) + if (address >= limitAddress && itBlockSize == 0) { break; } @@ -210,6 +211,15 @@ namespace ARMeilleure.Decoders block.OpCodes.Add(opCode); address += (ulong)opCode.OpCodeSizeInBytes; + + if (opCode is OpCodeT16IfThen it) + { + itBlockSize = it.IfThenBlockSize; + } + else if (itBlockSize > 0) + { + itBlockSize--; + } } while (!(IsBranch(opCode) || IsException(opCode))); @@ -345,7 +355,14 @@ namespace ARMeilleure.Decoders } else { - return new OpCode(inst, address, opCode); + if (mode == ExecutionMode.Aarch32Thumb) + { + return new OpCodeT16(inst, address, opCode); + } + else + { + return new OpCode(inst, address, opCode); + } } } } diff --git a/ARMeilleure/Decoders/IOpCode32Adr.cs b/ARMeilleure/Decoders/IOpCode32Adr.cs new file mode 100644 index 00000000..40a4f526 --- /dev/null +++ b/ARMeilleure/Decoders/IOpCode32Adr.cs @@ -0,0 +1,9 @@ +namespace ARMeilleure.Decoders +{ + interface IOpCode32Adr + { + int Rd { get; } + + int Immediate { get; } + } +} diff --git a/ARMeilleure/Decoders/IOpCode32Alu.cs b/ARMeilleure/Decoders/IOpCode32Alu.cs index 72aea30e..9876f107 100644 --- a/ARMeilleure/Decoders/IOpCode32Alu.cs +++ b/ARMeilleure/Decoders/IOpCode32Alu.cs @@ -5,6 +5,6 @@ namespace ARMeilleure.Decoders int Rd { get; } int Rn { get; } - bool SetFlags { get; } + bool? SetFlags { get; } } }
\ No newline at end of file diff --git a/ARMeilleure/Decoders/IOpCode32AluImm.cs b/ARMeilleure/Decoders/IOpCode32AluImm.cs new file mode 100644 index 00000000..342fb8f6 --- /dev/null +++ b/ARMeilleure/Decoders/IOpCode32AluImm.cs @@ -0,0 +1,9 @@ +namespace ARMeilleure.Decoders +{ + interface IOpCode32AluImm : IOpCode32Alu + { + int Immediate { get; } + + bool IsRotated { get; } + } +}
\ No newline at end of file diff --git a/ARMeilleure/Decoders/IOpCode32AluRsImm.cs b/ARMeilleure/Decoders/IOpCode32AluRsImm.cs new file mode 100644 index 00000000..e899a659 --- /dev/null +++ b/ARMeilleure/Decoders/IOpCode32AluRsImm.cs @@ -0,0 +1,10 @@ +namespace ARMeilleure.Decoders +{ + interface IOpCode32AluRsImm : IOpCode32Alu + { + int Rm { get; } + int Immediate { get; } + + ShiftType ShiftType { get; } + } +}
\ No newline at end of file diff --git a/ARMeilleure/Decoders/IOpCode32AluRsReg.cs b/ARMeilleure/Decoders/IOpCode32AluRsReg.cs new file mode 100644 index 00000000..879db059 --- /dev/null +++ b/ARMeilleure/Decoders/IOpCode32AluRsReg.cs @@ -0,0 +1,10 @@ +namespace ARMeilleure.Decoders +{ + interface IOpCode32AluRsReg : IOpCode32Alu + { + int Rm { get; } + int Rs { get; } + + ShiftType ShiftType { get; } + } +}
\ No newline at end of file diff --git a/ARMeilleure/Decoders/IOpCode32Exception.cs b/ARMeilleure/Decoders/IOpCode32Exception.cs new file mode 100644 index 00000000..82819bdd --- /dev/null +++ b/ARMeilleure/Decoders/IOpCode32Exception.cs @@ -0,0 +1,6 @@ +namespace ARMeilleure.Decoders; + +interface IOpCode32Exception +{ + int Id { get; } +}
\ No newline at end of file diff --git a/ARMeilleure/Decoders/IOpCode32Mem.cs b/ARMeilleure/Decoders/IOpCode32Mem.cs index 8fdc9dad..145bc618 100644 --- a/ARMeilleure/Decoders/IOpCode32Mem.cs +++ b/ARMeilleure/Decoders/IOpCode32Mem.cs @@ -7,5 +7,9 @@ namespace ARMeilleure.Decoders bool WBack { get; } bool IsLoad { get; } + bool Index { get; } + bool Add { get; } + + int Immediate { get; } } }
\ No newline at end of file diff --git a/ARMeilleure/Decoders/IOpCode32MemMult.cs b/ARMeilleure/Decoders/IOpCode32MemMult.cs index 18fd3f6b..4b891bc1 100644 --- a/ARMeilleure/Decoders/IOpCode32MemMult.cs +++ b/ARMeilleure/Decoders/IOpCode32MemMult.cs @@ -9,5 +9,7 @@ namespace ARMeilleure.Decoders int PostOffset { get; } bool IsLoad { get; } + + int Offset { get; } } }
\ No newline at end of file diff --git a/ARMeilleure/Decoders/IOpCode32MemReg.cs b/ARMeilleure/Decoders/IOpCode32MemReg.cs new file mode 100644 index 00000000..7fe1b022 --- /dev/null +++ b/ARMeilleure/Decoders/IOpCode32MemReg.cs @@ -0,0 +1,7 @@ +namespace ARMeilleure.Decoders +{ + interface IOpCode32MemReg : IOpCode32Mem + { + int Rm { get; } + } +}
\ No newline at end of file diff --git a/ARMeilleure/Decoders/OpCode.cs b/ARMeilleure/Decoders/OpCode.cs index e0b14e66..f9aed792 100644 --- a/ARMeilleure/Decoders/OpCode.cs +++ b/ARMeilleure/Decoders/OpCode.cs @@ -18,10 +18,9 @@ namespace ARMeilleure.Decoders public OpCode(InstDescriptor inst, ulong address, int opCode) { - Address = address; - RawOpCode = opCode; - Instruction = inst; + Address = address; + RawOpCode = opCode; RegisterSize = RegisterSize.Int64; } diff --git a/ARMeilleure/Decoders/OpCode32Alu.cs b/ARMeilleure/Decoders/OpCode32Alu.cs index 6c7723bb..1625aee0 100644 --- a/ARMeilleure/Decoders/OpCode32Alu.cs +++ b/ARMeilleure/Decoders/OpCode32Alu.cs @@ -5,7 +5,7 @@ namespace ARMeilleure.Decoders public int Rd { get; } public int Rn { get; } - public bool SetFlags { get; } + public bool? SetFlags { get; } public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32Alu(inst, address, opCode); diff --git a/ARMeilleure/Decoders/OpCode32AluImm.cs b/ARMeilleure/Decoders/OpCode32AluImm.cs index 9d82db4b..b5435aaf 100644 --- a/ARMeilleure/Decoders/OpCode32AluImm.cs +++ b/ARMeilleure/Decoders/OpCode32AluImm.cs @@ -2,7 +2,7 @@ using ARMeilleure.Common; namespace ARMeilleure.Decoders { - class OpCode32AluImm : OpCode32Alu + class OpCode32AluImm : OpCode32Alu, IOpCode32AluImm { public int Immediate { get; } diff --git a/ARMeilleure/Decoders/OpCode32AluMla.cs b/ARMeilleure/Decoders/OpCode32AluMla.cs index 4e9b25e3..74894667 100644 --- a/ARMeilleure/Decoders/OpCode32AluMla.cs +++ b/ARMeilleure/Decoders/OpCode32AluMla.cs @@ -10,7 +10,7 @@ public bool NHigh { get; } public bool MHigh { get; } public bool R { get; } - public bool SetFlags { get; } + public bool? SetFlags { get; } public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluMla(inst, address, opCode); diff --git a/ARMeilleure/Decoders/OpCode32AluRsImm.cs b/ARMeilleure/Decoders/OpCode32AluRsImm.cs index f24e7757..c2dee6c9 100644 --- a/ARMeilleure/Decoders/OpCode32AluRsImm.cs +++ b/ARMeilleure/Decoders/OpCode32AluRsImm.cs @@ -1,6 +1,6 @@ namespace ARMeilleure.Decoders { - class OpCode32AluRsImm : OpCode32Alu + class OpCode32AluRsImm : OpCode32Alu, IOpCode32AluRsImm { public int Rm { get; } public int Immediate { get; } diff --git a/ARMeilleure/Decoders/OpCode32AluRsReg.cs b/ARMeilleure/Decoders/OpCode32AluRsReg.cs index 574588f8..04740d08 100644 --- a/ARMeilleure/Decoders/OpCode32AluRsReg.cs +++ b/ARMeilleure/Decoders/OpCode32AluRsReg.cs @@ -1,6 +1,6 @@ namespace ARMeilleure.Decoders { - class OpCode32AluRsReg : OpCode32Alu + class OpCode32AluRsReg : OpCode32Alu, IOpCode32AluRsReg { public int Rm { get; } public int Rs { get; } diff --git a/ARMeilleure/Decoders/OpCode32AluUmull.cs b/ARMeilleure/Decoders/OpCode32AluUmull.cs index e4f0895b..bbdaaeae 100644 --- a/ARMeilleure/Decoders/OpCode32AluUmull.cs +++ b/ARMeilleure/Decoders/OpCode32AluUmull.cs @@ -10,7 +10,7 @@ public bool NHigh { get; } public bool MHigh { get; } - public bool SetFlags { get; } + public bool? SetFlags { get; } public DataOp DataOp { get; } public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluUmull(inst, address, opCode); diff --git a/ARMeilleure/Decoders/OpCode32Exception.cs b/ARMeilleure/Decoders/OpCode32Exception.cs index e963be64..b4edcc10 100644 --- a/ARMeilleure/Decoders/OpCode32Exception.cs +++ b/ARMeilleure/Decoders/OpCode32Exception.cs @@ -1,6 +1,6 @@ namespace ARMeilleure.Decoders { - class OpCode32Exception : OpCode32 + class OpCode32Exception : OpCode32, IOpCode32Exception { public int Id { get; } diff --git a/ARMeilleure/Decoders/OpCode32MemReg.cs b/ARMeilleure/Decoders/OpCode32MemReg.cs index c9434399..786f37fa 100644 --- a/ARMeilleure/Decoders/OpCode32MemReg.cs +++ b/ARMeilleure/Decoders/OpCode32MemReg.cs @@ -1,6 +1,6 @@ namespace ARMeilleure.Decoders { - class OpCode32MemReg : OpCode32Mem + class OpCode32MemReg : OpCode32Mem, IOpCode32MemReg { public int Rm { get; } diff --git a/ARMeilleure/Decoders/OpCodeT16AddSubImm3.cs b/ARMeilleure/Decoders/OpCodeT16AddSubImm3.cs new file mode 100644 index 00000000..95f18054 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16AddSubImm3.cs @@ -0,0 +1,24 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16AddSubImm3: OpCodeT16, IOpCode32AluImm + { + public int Rd { get; } + public int Rn { get; } + + public bool? SetFlags => null; + + public int Immediate { get; } + + public bool IsRotated { get; } + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AddSubImm3(inst, address, opCode); + + public OpCodeT16AddSubImm3(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rd = (opCode >> 0) & 0x7; + Rn = (opCode >> 3) & 0x7; + Immediate = (opCode >> 6) & 0x7; + IsRotated = false; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16AddSubReg.cs b/ARMeilleure/Decoders/OpCodeT16AddSubReg.cs new file mode 100644 index 00000000..2a407b2d --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16AddSubReg.cs @@ -0,0 +1,20 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16AddSubReg : OpCodeT16, IOpCode32AluReg + { + public int Rm { get; } + public int Rd { get; } + public int Rn { get; } + + public bool? SetFlags => null; + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AddSubReg(inst, address, opCode); + + public OpCodeT16AddSubReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rd = (opCode >> 0) & 0x7; + Rn = (opCode >> 3) & 0x7; + Rm = (opCode >> 6) & 0x7; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16AddSubSp.cs b/ARMeilleure/Decoders/OpCodeT16AddSubSp.cs new file mode 100644 index 00000000..b66fe0cd --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16AddSubSp.cs @@ -0,0 +1,23 @@ +using ARMeilleure.State; + +namespace ARMeilleure.Decoders +{ + class OpCodeT16AddSubSp : OpCodeT16, IOpCode32AluImm + { + public int Rd => RegisterAlias.Aarch32Sp; + public int Rn => RegisterAlias.Aarch32Sp; + + public bool? SetFlags => false; + + public int Immediate { get; } + + public bool IsRotated => false; + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AddSubSp(inst, address, opCode); + + public OpCodeT16AddSubSp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Immediate = ((opCode >> 0) & 0x7f) << 2; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16Adr.cs b/ARMeilleure/Decoders/OpCodeT16Adr.cs new file mode 100644 index 00000000..ef14791d --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16Adr.cs @@ -0,0 +1,20 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16Adr : OpCodeT16, IOpCode32Adr + { + public int Rd { get; } + + public bool Add => true; + public int Immediate { get; } + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16Adr(inst, address, opCode); + + public OpCodeT16Adr(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rd = (opCode >> 8) & 7; + + int imm = (opCode & 0xff) << 2; + Immediate = (int)(GetPc() & 0xfffffffc) + imm; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16AluImm8.cs b/ARMeilleure/Decoders/OpCodeT16AluImm8.cs index d31f37a2..673a4604 100644 --- a/ARMeilleure/Decoders/OpCodeT16AluImm8.cs +++ b/ARMeilleure/Decoders/OpCodeT16AluImm8.cs @@ -1,22 +1,24 @@ -namespace ARMeilleure.Decoders +namespace ARMeilleure.Decoders { - class OpCodeT16AluImm8 : OpCodeT16, IOpCode32Alu + class OpCodeT16AluImm8 : OpCodeT16, IOpCode32AluImm { - private int _rdn; + public int Rd { get; } + public int Rn { get; } - public int Rd => _rdn; - public int Rn => _rdn; - - public bool SetFlags => false; + public bool? SetFlags => null; public int Immediate { get; } - public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AluImm8(inst, address, opCode); + public bool IsRotated { get; } + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AluImm8(inst, address, opCode); public OpCodeT16AluImm8(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { + Rd = (opCode >> 8) & 0x7; + Rn = (opCode >> 8) & 0x7; Immediate = (opCode >> 0) & 0xff; - _rdn = (opCode >> 8) & 0x7; + IsRotated = false; } } -}
\ No newline at end of file +} diff --git a/ARMeilleure/Decoders/OpCodeT16AluImmZero.cs b/ARMeilleure/Decoders/OpCodeT16AluImmZero.cs new file mode 100644 index 00000000..b23f8fe0 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16AluImmZero.cs @@ -0,0 +1,24 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16AluImmZero : OpCodeT16, IOpCode32AluImm + { + public int Rd { get; } + public int Rn { get; } + + public bool? SetFlags => null; + + public int Immediate { get; } + + public bool IsRotated { get; } + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AluImmZero(inst, address, opCode); + + public OpCodeT16AluImmZero(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rd = (opCode >> 0) & 0x7; + Rn = (opCode >> 3) & 0x7; + Immediate = 0; + IsRotated = false; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16AluRegHigh.cs b/ARMeilleure/Decoders/OpCodeT16AluRegHigh.cs new file mode 100644 index 00000000..6d5ac8fd --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16AluRegHigh.cs @@ -0,0 +1,20 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16AluRegHigh : OpCodeT16, IOpCode32AluReg + { + public int Rm { get; } + public int Rd { get; } + public int Rn { get; } + + public bool? SetFlags => false; + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AluRegHigh(inst, address, opCode); + + public OpCodeT16AluRegHigh(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rd = ((opCode >> 0) & 0x7) | ((opCode >> 4) & 0x8); + Rn = ((opCode >> 0) & 0x7) | ((opCode >> 4) & 0x8); + Rm = (opCode >> 3) & 0xf; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16AluRegLow.cs b/ARMeilleure/Decoders/OpCodeT16AluRegLow.cs new file mode 100644 index 00000000..b37b4f66 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16AluRegLow.cs @@ -0,0 +1,20 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16AluRegLow : OpCodeT16, IOpCode32AluReg + { + public int Rm { get; } + public int Rd { get; } + public int Rn { get; } + + public bool? SetFlags => null; + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AluRegLow(inst, address, opCode); + + public OpCodeT16AluRegLow(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rd = (opCode >> 0) & 0x7; + Rn = (opCode >> 0) & 0x7; + Rm = (opCode >> 3) & 0x7; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16AluUx.cs b/ARMeilleure/Decoders/OpCodeT16AluUx.cs new file mode 100644 index 00000000..11d3a8fe --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16AluUx.cs @@ -0,0 +1,22 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16AluUx : OpCodeT16, IOpCode32AluUx + { + public int Rm { get; } + public int Rd { get; } + public int Rn { get; } + + public bool? SetFlags => false; + + public int RotateBits => 0; + public bool Add => false; + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16AluUx(inst, address, opCode); + + public OpCodeT16AluUx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rd = (opCode >> 0) & 0x7; + Rm = (opCode >> 3) & 0x7; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16BImm11.cs b/ARMeilleure/Decoders/OpCodeT16BImm11.cs new file mode 100644 index 00000000..42ebec4f --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16BImm11.cs @@ -0,0 +1,15 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16BImm11 : OpCode32, IOpCode32BImm + { + public long Immediate { get; } + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16BImm11(inst, address, opCode); + + public OpCodeT16BImm11(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + int imm = (opCode << 21) >> 20; + Immediate = GetPc() + imm; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16BImm8.cs b/ARMeilleure/Decoders/OpCodeT16BImm8.cs new file mode 100644 index 00000000..9b3a4ad1 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16BImm8.cs @@ -0,0 +1,17 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16BImm8 : OpCode32, IOpCode32BImm + { + public long Immediate { get; } + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16BImm8(inst, address, opCode); + + public OpCodeT16BImm8(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Cond = (Condition)((opCode >> 8) & 0xf); + + int imm = (opCode << 24) >> 23; + Immediate = GetPc() + imm; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16BImmCmp.cs b/ARMeilleure/Decoders/OpCodeT16BImmCmp.cs new file mode 100644 index 00000000..ab7ae13f --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16BImmCmp.cs @@ -0,0 +1,19 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16BImmCmp : OpCodeT16 + { + public int Rn { get; } + + public int Immediate { get; } + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16BImmCmp(inst, address, opCode); + + public OpCodeT16BImmCmp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rn = (opCode >> 0) & 0x7; + + int imm = ((opCode >> 2) & 0x3e) | ((opCode >> 3) & 0x40); + Immediate = (int)GetPc() + imm; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16BReg.cs b/ARMeilleure/Decoders/OpCodeT16BReg.cs index 38c07480..3122cd07 100644 --- a/ARMeilleure/Decoders/OpCodeT16BReg.cs +++ b/ARMeilleure/Decoders/OpCodeT16BReg.cs @@ -1,4 +1,4 @@ -namespace ARMeilleure.Decoders +namespace ARMeilleure.Decoders { class OpCodeT16BReg : OpCodeT16, IOpCode32BReg { @@ -11,4 +11,4 @@ namespace ARMeilleure.Decoders Rm = (opCode >> 3) & 0xf; } } -}
\ No newline at end of file +} diff --git a/ARMeilleure/Decoders/OpCodeT16Exception.cs b/ARMeilleure/Decoders/OpCodeT16Exception.cs new file mode 100644 index 00000000..bb005083 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16Exception.cs @@ -0,0 +1,14 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16Exception : OpCodeT16, IOpCode32Exception + { + public int Id { get; } + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16Exception(inst, address, opCode); + + public OpCodeT16Exception(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Id = opCode & 0xFF; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16IfThen.cs b/ARMeilleure/Decoders/OpCodeT16IfThen.cs new file mode 100644 index 00000000..bf84d1d3 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16IfThen.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Reflection.Emit; + +namespace ARMeilleure.Decoders +{ + class OpCodeT16IfThen : OpCodeT16 + { + public Condition[] IfThenBlockConds { get; } + + public int IfThenBlockSize { get { return IfThenBlockConds.Length; } } + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16IfThen(inst, address, opCode); + + public OpCodeT16IfThen(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + List<Condition> conds = new(); + + int cond = (opCode >> 4) & 0xf; + int mask = opCode & 0xf; + + conds.Add((Condition)cond); + + while ((mask & 7) != 0) + { + int newLsb = (mask >> 3) & 1; + cond = (cond & 0xe) | newLsb; + mask <<= 1; + conds.Add((Condition)cond); + } + + IfThenBlockConds = conds.ToArray(); + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16MemImm5.cs b/ARMeilleure/Decoders/OpCodeT16MemImm5.cs new file mode 100644 index 00000000..20ef31e2 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16MemImm5.cs @@ -0,0 +1,58 @@ +using ARMeilleure.Instructions; +using System; + +namespace ARMeilleure.Decoders +{ + class OpCodeT16MemImm5 : OpCodeT16, IOpCode32Mem + { + public int Rt { get; } + public int Rn { get; } + + public bool WBack => false; + public bool IsLoad { get; } + public bool Index => true; + public bool Add => true; + + public int Immediate { get; } + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16MemImm5(inst, address, opCode); + + public OpCodeT16MemImm5(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rt = (opCode >> 0) & 7; + Rn = (opCode >> 3) & 7; + + switch (inst.Name) + { + case InstName.Ldr: + case InstName.Ldrb: + case InstName.Ldrh: + IsLoad = true; + break; + case InstName.Str: + case InstName.Strb: + case InstName.Strh: + IsLoad = false; + break; + } + + switch (inst.Name) + { + case InstName.Str: + case InstName.Ldr: + Immediate = ((opCode >> 6) & 0x1f) << 2; + break; + case InstName.Strb: + case InstName.Ldrb: + Immediate = ((opCode >> 6) & 0x1f); + break; + case InstName.Strh: + case InstName.Ldrh: + Immediate = ((opCode >> 6) & 0x1f) << 1; + break; + default: + throw new InvalidOperationException(); + } + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16MemLit.cs b/ARMeilleure/Decoders/OpCodeT16MemLit.cs new file mode 100644 index 00000000..f8c16e29 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16MemLit.cs @@ -0,0 +1,26 @@ +using ARMeilleure.State; + +namespace ARMeilleure.Decoders +{ + class OpCodeT16MemLit : OpCodeT16, IOpCode32Mem + { + public int Rt { get; } + public int Rn => RegisterAlias.Aarch32Pc; + + public bool WBack => false; + public bool IsLoad => true; + public bool Index => true; + public bool Add => true; + + public int Immediate { get; } + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16MemLit(inst, address, opCode); + + public OpCodeT16MemLit(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rt = (opCode >> 8) & 7; + + Immediate = (opCode & 0xff) << 2; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16MemMult.cs b/ARMeilleure/Decoders/OpCodeT16MemMult.cs new file mode 100644 index 00000000..f4185cfc --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16MemMult.cs @@ -0,0 +1,34 @@ +using ARMeilleure.Instructions; +using System; +using System.Numerics; + +namespace ARMeilleure.Decoders +{ + class OpCodeT16MemMult : OpCodeT16, IOpCode32MemMult + { + public int Rn { get; } + public int RegisterMask { get; } + public int PostOffset { get; } + public bool IsLoad { get; } + public int Offset { get; } + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16MemMult(inst, address, opCode); + + public OpCodeT16MemMult(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + RegisterMask = opCode & 0xff; + Rn = (opCode >> 8) & 7; + + int regCount = BitOperations.PopCount((uint)RegisterMask); + + Offset = 0; + PostOffset = 4 * regCount; + IsLoad = inst.Name switch + { + InstName.Ldm => true, + InstName.Stm => false, + _ => throw new InvalidOperationException() + }; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16MemReg.cs b/ARMeilleure/Decoders/OpCodeT16MemReg.cs new file mode 100644 index 00000000..71100112 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16MemReg.cs @@ -0,0 +1,27 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16MemReg : OpCodeT16, IOpCode32MemReg + { + public int Rm { get; } + public int Rt { get; } + public int Rn { get; } + + public bool WBack => false; + public bool IsLoad { get; } + public bool Index => true; + public bool Add => true; + + public int Immediate => throw new System.InvalidOperationException(); + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16MemReg(inst, address, opCode); + + public OpCodeT16MemReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rt = (opCode >> 0) & 7; + Rn = (opCode >> 3) & 7; + Rm = (opCode >> 6) & 7; + + IsLoad = ((opCode >> 9) & 7) >= 3; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16MemSp.cs b/ARMeilleure/Decoders/OpCodeT16MemSp.cs new file mode 100644 index 00000000..a038b915 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16MemSp.cs @@ -0,0 +1,28 @@ +using ARMeilleure.State; + +namespace ARMeilleure.Decoders +{ + class OpCodeT16MemSp : OpCodeT16, IOpCode32Mem + { + public int Rt { get; } + public int Rn => RegisterAlias.Aarch32Sp; + + public bool WBack => false; + public bool IsLoad { get; } + public bool Index => true; + public bool Add => true; + + public int Immediate { get; } + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16MemSp(inst, address, opCode); + + public OpCodeT16MemSp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rt = (opCode >> 8) & 7; + + IsLoad = ((opCode >> 11) & 1) != 0; + + Immediate = ((opCode >> 0) & 0xff) << 2; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16MemStack.cs b/ARMeilleure/Decoders/OpCodeT16MemStack.cs new file mode 100644 index 00000000..9d7b0d20 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16MemStack.cs @@ -0,0 +1,42 @@ +using ARMeilleure.Instructions; +using ARMeilleure.State; +using System; +using System.Numerics; + +namespace ARMeilleure.Decoders +{ + class OpCodeT16MemStack : OpCodeT16, IOpCode32MemMult + { + public int Rn => RegisterAlias.Aarch32Sp; + public int RegisterMask { get; } + public int PostOffset { get; } + public bool IsLoad { get; } + public int Offset { get; } + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16MemStack(inst, address, opCode); + + public OpCodeT16MemStack(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + int extra = (opCode >> 8) & 1; + int regCount = BitOperations.PopCount((uint)opCode & 0x1ff); + + switch (inst.Name) + { + case InstName.Push: + RegisterMask = (opCode & 0xff) | (extra << 14); + IsLoad = false; + Offset = -4 * regCount; + PostOffset = -4 * regCount; + break; + case InstName.Pop: + RegisterMask = (opCode & 0xff) | (extra << 15); + IsLoad = true; + Offset = 0; + PostOffset = 4 * regCount; + break; + default: + throw new InvalidOperationException(); + } + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16ShiftImm.cs b/ARMeilleure/Decoders/OpCodeT16ShiftImm.cs new file mode 100644 index 00000000..a540026e --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16ShiftImm.cs @@ -0,0 +1,24 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16ShiftImm : OpCodeT16, IOpCode32AluRsImm + { + public int Rd { get; } + public int Rn { get; } + public int Rm { get; } + + public int Immediate { get; } + public ShiftType ShiftType { get; } + + public bool? SetFlags => null; + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16ShiftImm(inst, address, opCode); + + public OpCodeT16ShiftImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rd = (opCode >> 0) & 0x7; + Rm = (opCode >> 3) & 0x7; + Immediate = (opCode >> 6) & 0x1F; + ShiftType = (ShiftType)((opCode >> 11) & 3); + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16ShiftReg.cs b/ARMeilleure/Decoders/OpCodeT16ShiftReg.cs new file mode 100644 index 00000000..9f898281 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16ShiftReg.cs @@ -0,0 +1,27 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT16ShiftReg : OpCodeT16, IOpCode32AluRsReg + { + public int Rm { get; } + public int Rs { get; } + public int Rd { get; } + + public int Rn { get; } + + public ShiftType ShiftType { get; } + + public bool? SetFlags => null; + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16ShiftReg(inst, address, opCode); + + public OpCodeT16ShiftReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rd = (opCode >> 0) & 7; + Rm = (opCode >> 0) & 7; + Rn = (opCode >> 3) & 7; + Rs = (opCode >> 3) & 7; + + ShiftType = (ShiftType)(((opCode >> 6) & 1) | ((opCode >> 7) & 2)); + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT16SpRel.cs b/ARMeilleure/Decoders/OpCodeT16SpRel.cs new file mode 100644 index 00000000..d737f5bd --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT16SpRel.cs @@ -0,0 +1,24 @@ +using ARMeilleure.State; + +namespace ARMeilleure.Decoders +{ + class OpCodeT16SpRel : OpCodeT16, IOpCode32AluImm + { + public int Rd { get; } + public int Rn => RegisterAlias.Aarch32Sp; + + public bool? SetFlags => false; + + public int Immediate { get; } + + public bool IsRotated => false; + + public static new OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16SpRel(inst, address, opCode); + + public OpCodeT16SpRel(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rd = (opCode >> 8) & 0x7; + Immediate = ((opCode >> 0) & 0xff) << 2; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index 53328a73..1ea8885b 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -1,5 +1,4 @@ using ARMeilleure.Instructions; -using ARMeilleure.State; using System; using System.Collections.Generic; @@ -29,9 +28,9 @@ namespace ARMeilleure.Decoders } } - private static List<InstInfo> AllInstA32 = new List<InstInfo>(); - private static List<InstInfo> AllInstT32 = new List<InstInfo>(); - private static List<InstInfo> AllInstA64 = new List<InstInfo>(); + private static List<InstInfo> AllInstA32 = new(); + private static List<InstInfo> AllInstT32 = new(); + private static List<InstInfo> AllInstA64 = new(); private static InstInfo[][] InstA32FastLookup = new InstInfo[FastLookupSize][]; private static InstInfo[][] InstT32FastLookup = new InstInfo[FastLookupSize][]; @@ -628,7 +627,7 @@ namespace ARMeilleure.Decoders SetA64("0>001110<<0xxxxx011110xxxxxxxxxx", InstName.Zip2_V, InstEmit.Zip2_V, OpCodeSimdReg.Create); #endregion -#region "OpCode Table (AArch32)" +#region "OpCode Table (AArch32, A32)" // Base SetA32("<<<<0010101xxxxxxxxxxxxxxxxxxxxx", InstName.Adc, InstEmit32.Adc, OpCode32AluImm.Create); SetA32("<<<<0000101xxxxxxxxxxxxxxxx0xxxx", InstName.Adc, InstEmit32.Adc, OpCode32AluRsImm.Create); @@ -649,7 +648,6 @@ namespace ARMeilleure.Decoders SetA32("1111101xxxxxxxxxxxxxxxxxxxxxxxxx", InstName.Blx, InstEmit32.Blx, OpCode32BImm.Create); SetA32("<<<<000100101111111111110011xxxx", InstName.Blx, InstEmit32.Blxr, OpCode32BReg.Create); SetA32("<<<<000100101111111111110001xxxx", InstName.Bx, InstEmit32.Bx, OpCode32BReg.Create); - SetT32("xxxxxxxxxxxxxxxx010001110xxxx000", InstName.Bx, InstEmit32.Bx, OpCodeT16BReg.Create); SetA32("11110101011111111111000000011111", InstName.Clrex, InstEmit32.Clrex, OpCode32.Create); SetA32("<<<<000101101111xxxx11110001xxxx", InstName.Clz, InstEmit32.Clz, OpCode32AluReg.Create); SetA32("<<<<00110111xxxx0000xxxxxxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCode32AluImm.Create); @@ -702,7 +700,6 @@ namespace ARMeilleure.Decoders SetA32("<<<<0001101x0000xxxxxxxxxxx0xxxx", InstName.Mov, InstEmit32.Mov, OpCode32AluRsImm.Create); SetA32("<<<<0001101x0000xxxxxxxx0xx1xxxx", InstName.Mov, InstEmit32.Mov, OpCode32AluRsReg.Create); SetA32("<<<<00110000xxxxxxxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCode32AluImm16.Create); - SetT32("xxxxxxxxxxxxxxxx00100xxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16AluImm8.Create); SetA32("<<<<00110100xxxxxxxxxxxxxxxxxxxx", InstName.Movt, InstEmit32.Movt, OpCode32AluImm16.Create); SetA32("<<<<1110xxx1xxxxxxxx111xxxx1xxxx", InstName.Mrc, InstEmit32.Mrc, OpCode32System.Create); SetA32("<<<<11000101xxxxxxxx111xxxxxxxxx", InstName.Mrrc, InstEmit32.Mrrc, OpCode32System.Create); @@ -975,12 +972,85 @@ namespace ARMeilleure.Decoders SetA32("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create); #endregion - FillFastLookupTable(InstA32FastLookup, AllInstA32); - FillFastLookupTable(InstT32FastLookup, AllInstT32); - FillFastLookupTable(InstA64FastLookup, AllInstA64); +#region "OpCode Table (AArch32, T16/T32)" + // T16 + SetT16("000<<xxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16ShiftImm.Create); + SetT16("0001100xxxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AddSubReg.Create); + SetT16("0001101xxxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT16AddSubReg.Create); + SetT16("0001110xxxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AddSubImm3.Create); + SetT16("0001111xxxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT16AddSubImm3.Create); + SetT16("00100xxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16AluImm8.Create); + SetT16("00101xxxxxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT16AluImm8.Create); + SetT16("00110xxxxxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AluImm8.Create); + SetT16("00111xxxxxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT16AluImm8.Create); + SetT16("0100000000xxxxxx", InstName.And, InstEmit32.And, OpCodeT16AluRegLow.Create); + SetT16("0100000001xxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT16AluRegLow.Create); + SetT16("0100000010xxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16ShiftReg.Create); + SetT16("0100000011xxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16ShiftReg.Create); + SetT16("0100000100xxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16ShiftReg.Create); + SetT16("0100000101xxxxxx", InstName.Adc, InstEmit32.Adc, OpCodeT16AluRegLow.Create); + SetT16("0100000110xxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT16AluRegLow.Create); + SetT16("0100000111xxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16ShiftReg.Create); + SetT16("0100001000xxxxxx", InstName.Tst, InstEmit32.Tst, OpCodeT16AluRegLow.Create); + SetT16("0100001001xxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT16AluImmZero.Create); + SetT16("0100001010xxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT16AluRegLow.Create); + SetT16("0100001011xxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCodeT16AluRegLow.Create); + SetT16("0100001100xxxxxx", InstName.Orr, InstEmit32.Orr, OpCodeT16AluRegLow.Create); + SetT16("0100001101xxxxxx", InstName.Mul, InstEmit32.Mul, OpCodeT16AluRegLow.Create); + SetT16("0100001110xxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT16AluRegLow.Create); + SetT16("0100001111xxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT16AluRegLow.Create); + SetT16("01000100xxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AluRegHigh.Create); + SetT16("01000101xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT16AluRegHigh.Create); + SetT16("01000110xxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16AluRegHigh.Create); + SetT16("010001110xxxx000", InstName.Bx, InstEmit32.Bx, OpCodeT16BReg.Create); + SetT16("010001111xxxx000", InstName.Blx, InstEmit32.Blx, OpCodeT16BReg.Create); + SetT16("01001xxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT16MemLit.Create); + SetT16("0101000xxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT16MemReg.Create); + SetT16("0101001xxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT16MemReg.Create); + SetT16("0101010xxxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT16MemReg.Create); + SetT16("0101011xxxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT16MemReg.Create); + SetT16("0101100xxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT16MemReg.Create); + SetT16("0101101xxxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT16MemReg.Create); + SetT16("0101110xxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT16MemReg.Create); + SetT16("0101111xxxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT16MemReg.Create); + SetT16("01100xxxxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT16MemImm5.Create); + SetT16("01101xxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT16MemImm5.Create); + SetT16("01110xxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT16MemImm5.Create); + SetT16("01111xxxxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT16MemImm5.Create); + SetT16("10000xxxxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT16MemImm5.Create); + SetT16("10001xxxxxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT16MemImm5.Create); + SetT16("10010xxxxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT16MemSp.Create); + SetT16("10011xxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT16MemSp.Create); + SetT16("10100xxxxxxxxxxx", InstName.Adr, InstEmit32.Adr, OpCodeT16Adr.Create); + SetT16("10101xxxxxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16SpRel.Create); + SetT16("101100000xxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AddSubSp.Create); + SetT16("101100001xxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT16AddSubSp.Create); + SetT16("1011001000xxxxxx", InstName.Sxth, InstEmit32.Sxth, OpCodeT16AluUx.Create); + SetT16("1011001001xxxxxx", InstName.Sxtb, InstEmit32.Sxtb, OpCodeT16AluUx.Create); + SetT16("1011001010xxxxxx", InstName.Uxth, InstEmit32.Uxth, OpCodeT16AluUx.Create); + SetT16("1011001011xxxxxx", InstName.Uxtb, InstEmit32.Uxtb, OpCodeT16AluUx.Create); + SetT16("101100x1xxxxxxxx", InstName.Cbz, InstEmit32.Cbz, OpCodeT16BImmCmp.Create); + SetT16("1011010xxxxxxxxx", InstName.Push, InstEmit32.Stm, OpCodeT16MemStack.Create); + SetT16("1011101000xxxxxx", InstName.Rev, InstEmit32.Rev, OpCodeT16AluRegLow.Create); + SetT16("1011101001xxxxxx", InstName.Rev16, InstEmit32.Rev16, OpCodeT16AluRegLow.Create); + SetT16("1011101011xxxxxx", InstName.Revsh, InstEmit32.Revsh, OpCodeT16AluRegLow.Create); + SetT16("101110x1xxxxxxxx", InstName.Cbnz, InstEmit32.Cbnz, OpCodeT16BImmCmp.Create); + SetT16("1011110xxxxxxxxx", InstName.Pop, InstEmit32.Ldm, OpCodeT16MemStack.Create); + SetT16("10111111xxxx0000", InstName.Nop, InstEmit32.Nop, OpCodeT16.Create); + SetT16("10111111xxxx>>>>", InstName.It, InstEmit32.It, OpCodeT16IfThen.Create); + SetT16("11000xxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT16MemMult.Create); + SetT16("11001xxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT16MemMult.Create); + SetT16("1101<<<xxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm8.Create); + SetT16("11011111xxxxxxxx", InstName.Svc, InstEmit32.Svc, OpCodeT16Exception.Create); + SetT16("11100xxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm11.Create); +#endregion + + FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA); + FillFastLookupTable(InstT32FastLookup, AllInstT32, ToFastLookupIndexT); + FillFastLookupTable(InstA64FastLookup, AllInstA64, ToFastLookupIndexA); } - private static void FillFastLookupTable(InstInfo[][] table, List<InstInfo> allInsts) + private static void FillFastLookupTable(InstInfo[][] table, List<InstInfo> allInsts, Func<int, int> ToFastLookupIndex) { List<InstInfo>[] temp = new List<InstInfo>[FastLookupSize]; @@ -1011,20 +1081,27 @@ namespace ARMeilleure.Decoders private static void SetA32(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp) { - Set(encoding, ExecutionMode.Aarch32Arm, new InstDescriptor(name, emitter), makeOp); + Set(encoding, AllInstA32, new InstDescriptor(name, emitter), makeOp); + } + + private static void SetT16(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp) + { + encoding = "xxxxxxxxxxxxxxxx" + encoding; + Set(encoding, AllInstT32, new InstDescriptor(name, emitter), makeOp); } private static void SetT32(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp) { - Set(encoding, ExecutionMode.Aarch32Thumb, new InstDescriptor(name, emitter), makeOp); + encoding = encoding.Substring(16) + encoding.Substring(0, 16); + Set(encoding, AllInstT32, new InstDescriptor(name, emitter), makeOp); } private static void SetA64(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp) { - Set(encoding, ExecutionMode.Aarch64, new InstDescriptor(name, emitter), makeOp); + Set(encoding, AllInstA64, new InstDescriptor(name, emitter), makeOp); } - private static void Set(string encoding, ExecutionMode mode, InstDescriptor inst, MakeOp makeOp) + private static void Set(string encoding, List<InstInfo> list, InstDescriptor inst, MakeOp makeOp) { int bit = encoding.Length - 1; int value = 0; @@ -1073,7 +1150,7 @@ namespace ARMeilleure.Decoders if (xBits == 0) { - InsertInst(new InstInfo(xMask, value, inst, makeOp), mode); + list.Add(new InstInfo(xMask, value, inst, makeOp)); return; } @@ -1089,34 +1166,24 @@ namespace ARMeilleure.Decoders if (mask != blacklisted) { - InsertInst(new InstInfo(xMask, value | mask, inst, makeOp), mode); + list.Add(new InstInfo(xMask, value | mask, inst, makeOp)); } } } - private static void InsertInst(InstInfo info, ExecutionMode mode) - { - switch (mode) - { - case ExecutionMode.Aarch32Arm: AllInstA32.Add(info); break; - case ExecutionMode.Aarch32Thumb: AllInstT32.Add(info); break; - case ExecutionMode.Aarch64: AllInstA64.Add(info); break; - } - } - public static (InstDescriptor inst, MakeOp makeOp) GetInstA32(int opCode) { - return GetInstFromList(InstA32FastLookup[ToFastLookupIndex(opCode)], opCode); + return GetInstFromList(InstA32FastLookup[ToFastLookupIndexA(opCode)], opCode); } public static (InstDescriptor inst, MakeOp makeOp) GetInstT32(int opCode) { - return GetInstFromList(InstT32FastLookup[ToFastLookupIndex(opCode)], opCode); + return GetInstFromList(InstT32FastLookup[ToFastLookupIndexT(opCode)], opCode); } public static (InstDescriptor inst, MakeOp makeOp) GetInstA64(int opCode) { - return GetInstFromList(InstA64FastLookup[ToFastLookupIndex(opCode)], opCode); + return GetInstFromList(InstA64FastLookup[ToFastLookupIndexA(opCode)], opCode); } private static (InstDescriptor inst, MakeOp makeOp) GetInstFromList(InstInfo[] insts, int opCode) @@ -1132,9 +1199,14 @@ namespace ARMeilleure.Decoders return (new InstDescriptor(InstName.Und, InstEmit.Und), null); } - private static int ToFastLookupIndex(int value) + private static int ToFastLookupIndexA(int value) { return ((value >> 10) & 0x00F) | ((value >> 18) & 0xFF0); } + + private static int ToFastLookupIndexT(int value) + { + return (value >> 4) & 0xFFF; + } } } |