diff options
Diffstat (limited to 'ARMeilleure')
54 files changed, 885 insertions, 99 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; + } } } diff --git a/ARMeilleure/Instructions/InstEmitAlu32.cs b/ARMeilleure/Instructions/InstEmitAlu32.cs index 66b8a8a7..1cbc0765 100644 --- a/ARMeilleure/Instructions/InstEmitAlu32.cs +++ b/ARMeilleure/Instructions/InstEmitAlu32.cs @@ -20,7 +20,7 @@ namespace ARMeilleure.Instructions Operand res = context.Add(n, m); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); @@ -44,7 +44,7 @@ namespace ARMeilleure.Instructions res = context.Add(res, carry); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); @@ -64,7 +64,7 @@ namespace ARMeilleure.Instructions Operand res = context.BitwiseAnd(n, m); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); } @@ -110,7 +110,7 @@ namespace ARMeilleure.Instructions Operand res = context.BitwiseAnd(n, context.BitwiseNot(m)); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); } @@ -161,7 +161,7 @@ namespace ARMeilleure.Instructions Operand res = context.BitwiseExclusiveOr(n, m); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); } @@ -175,7 +175,7 @@ namespace ARMeilleure.Instructions Operand m = GetAluM(context); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, m); } @@ -204,7 +204,7 @@ namespace ARMeilleure.Instructions Operand res = context.Multiply(n, m); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); } @@ -219,7 +219,7 @@ namespace ARMeilleure.Instructions Operand res = context.BitwiseNot(m); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); } @@ -236,7 +236,7 @@ namespace ARMeilleure.Instructions Operand res = context.BitwiseOr(n, m); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); } @@ -315,7 +315,7 @@ namespace ARMeilleure.Instructions res = context.Subtract(res, borrow); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); @@ -335,7 +335,7 @@ namespace ARMeilleure.Instructions Operand res = context.Subtract(m, n); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); @@ -359,7 +359,7 @@ namespace ARMeilleure.Instructions res = context.Subtract(res, borrow); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); @@ -420,7 +420,7 @@ namespace ARMeilleure.Instructions Operand res = context.Subtract(n, m); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); @@ -836,7 +836,7 @@ namespace ARMeilleure.Instructions { IOpCode32Alu op = (IOpCode32Alu)context.CurrOp; - EmitGenericAluStoreA32(context, op.Rd, op.SetFlags, value); + EmitGenericAluStoreA32(context, op.Rd, ShouldSetFlags(context), value); } } } diff --git a/ARMeilleure/Instructions/InstEmitAluHelper.cs b/ARMeilleure/Instructions/InstEmitAluHelper.cs index 32440283..fe555767 100644 --- a/ARMeilleure/Instructions/InstEmitAluHelper.cs +++ b/ARMeilleure/Instructions/InstEmitAluHelper.cs @@ -12,6 +12,18 @@ namespace ARMeilleure.Instructions { static class InstEmitAluHelper { + public static bool ShouldSetFlags(ArmEmitterContext context) + { + IOpCode32Alu op = (IOpCode32Alu)context.CurrOp; + + if (op.SetFlags == null) + { + return !context.IsInIfThenBlock; + } + + return op.SetFlags.Value; + } + public static void EmitNZFlagsCheck(ArmEmitterContext context, Operand d) { SetFlag(context, PState.NFlag, context.ICompareLess (d, Const(d.Type, 0))); @@ -183,9 +195,9 @@ namespace ARMeilleure.Instructions switch (context.CurrOp) { // ARM32. - case OpCode32AluImm op: + case IOpCode32AluImm op: { - if (op.SetFlags && op.IsRotated) + if (ShouldSetFlags(context) && op.IsRotated) { SetFlag(context, PState.CFlag, Const((uint)op.Immediate >> 31)); } @@ -195,10 +207,8 @@ namespace ARMeilleure.Instructions case OpCode32AluImm16 op: return Const(op.Immediate); - case OpCode32AluRsImm op: return GetMShiftedByImmediate(context, op, setCarry); - case OpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry); - - case OpCodeT16AluImm8 op: return Const(op.Immediate); + case IOpCode32AluRsImm op: return GetMShiftedByImmediate(context, op, setCarry); + case IOpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry); case IOpCode32AluReg op: return GetIntA32(context, op.Rm); @@ -249,7 +259,7 @@ namespace ARMeilleure.Instructions } // ARM32 helpers. - public static Operand GetMShiftedByImmediate(ArmEmitterContext context, OpCode32AluRsImm op, bool setCarry) + public static Operand GetMShiftedByImmediate(ArmEmitterContext context, IOpCode32AluRsImm op, bool setCarry) { Operand m = GetIntA32(context, op.Rm); @@ -267,7 +277,7 @@ namespace ARMeilleure.Instructions if (shift != 0) { - setCarry &= op.SetFlags; + setCarry &= ShouldSetFlags(context); switch (op.ShiftType) { @@ -305,7 +315,7 @@ namespace ARMeilleure.Instructions return shift; } - public static Operand GetMShiftedByReg(ArmEmitterContext context, OpCode32AluRsReg op, bool setCarry) + public static Operand GetMShiftedByReg(ArmEmitterContext context, IOpCode32AluRsReg op, bool setCarry) { Operand m = GetIntA32(context, op.Rm); Operand s = context.ZeroExtend8(OperandType.I32, GetIntA32(context, op.Rs)); @@ -314,7 +324,7 @@ namespace ARMeilleure.Instructions Operand zeroResult = m; Operand shiftResult = m; - setCarry &= op.SetFlags; + setCarry &= ShouldSetFlags(context); switch (op.ShiftType) { diff --git a/ARMeilleure/Instructions/InstEmitException32.cs b/ARMeilleure/Instructions/InstEmitException32.cs index 76dbbf74..0b3d28d9 100644 --- a/ARMeilleure/Instructions/InstEmitException32.cs +++ b/ARMeilleure/Instructions/InstEmitException32.cs @@ -20,11 +20,11 @@ namespace ARMeilleure.Instructions private static void EmitExceptionCall(ArmEmitterContext context, string name) { - OpCode32Exception op = (OpCode32Exception)context.CurrOp; + IOpCode32Exception op = (IOpCode32Exception)context.CurrOp; context.StoreToContext(); - context.Call(typeof(NativeInterface).GetMethod(name), Const(op.Address), Const(op.Id)); + context.Call(typeof(NativeInterface).GetMethod(name), Const(((IOpCode)op).Address), Const(op.Id)); context.LoadFromContext(); diff --git a/ARMeilleure/Instructions/InstEmitFlow32.cs b/ARMeilleure/Instructions/InstEmitFlow32.cs index 6665ca51..add66a42 100644 --- a/ARMeilleure/Instructions/InstEmitFlow32.cs +++ b/ARMeilleure/Instructions/InstEmitFlow32.cs @@ -64,7 +64,7 @@ namespace ARMeilleure.Instructions bool isThumb = IsThumb(context.CurrOp); uint currentPc = isThumb - ? pc | 1 + ? (pc - 2) | 1 : pc - 4; SetIntA32(context, GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr), Const(currentPc)); @@ -80,5 +80,32 @@ namespace ARMeilleure.Instructions EmitBxWritePc(context, GetIntA32(context, op.Rm), op.Rm); } + + public static void Cbnz(ArmEmitterContext context) => EmitCb(context, onNotZero: true); + public static void Cbz(ArmEmitterContext context) => EmitCb(context, onNotZero: false); + + private static void EmitCb(ArmEmitterContext context, bool onNotZero) + { + OpCodeT16BImmCmp op = (OpCodeT16BImmCmp)context.CurrOp; + + Operand value = GetIntOrZR(context, op.Rn); + Operand lblTarget = context.GetLabel((ulong)op.Immediate); + + if (onNotZero) + { + context.BranchIfTrue(lblTarget, value); + } + else + { + context.BranchIfFalse(lblTarget, value); + } + } + + public static void It(ArmEmitterContext context) + { + OpCodeT16IfThen op = (OpCodeT16IfThen)context.CurrOp; + + context.SetIfThenBlockState(op.IfThenBlockConds); + } } }
\ No newline at end of file diff --git a/ARMeilleure/Instructions/InstEmitMemory32.cs b/ARMeilleure/Instructions/InstEmitMemory32.cs index af9eaf1a..e15f6a5b 100644 --- a/ARMeilleure/Instructions/InstEmitMemory32.cs +++ b/ARMeilleure/Instructions/InstEmitMemory32.cs @@ -32,7 +32,7 @@ namespace ARMeilleure.Instructions public static void Ldm(ArmEmitterContext context) { - OpCode32MemMult op = (OpCode32MemMult)context.CurrOp; + IOpCode32MemMult op = (IOpCode32MemMult)context.CurrOp; Operand n = GetIntA32(context, op.Rn); @@ -95,7 +95,7 @@ namespace ARMeilleure.Instructions public static void Stm(ArmEmitterContext context) { - OpCode32MemMult op = (OpCode32MemMult)context.CurrOp; + IOpCode32MemMult op = (IOpCode32MemMult)context.CurrOp; Operand n = context.Copy(GetIntA32(context, op.Rn)); @@ -151,7 +151,7 @@ namespace ARMeilleure.Instructions private static void EmitLoadOrStore(ArmEmitterContext context, int size, AccessType accType) { - OpCode32Mem op = (OpCode32Mem)context.CurrOp; + IOpCode32Mem op = (IOpCode32Mem)context.CurrOp; Operand n = context.Copy(GetIntA32AlignedPC(context, op.Rn)); Operand m = GetMemM(context, setCarry: false); @@ -255,5 +255,11 @@ namespace ARMeilleure.Instructions } } } + + public static void Adr(ArmEmitterContext context) + { + IOpCode32Adr op = (IOpCode32Adr)context.CurrOp; + SetIntA32(context, op.Rd, Const(op.Immediate)); + } } }
\ No newline at end of file diff --git a/ARMeilleure/Instructions/InstEmitMemoryHelper.cs b/ARMeilleure/Instructions/InstEmitMemoryHelper.cs index 570fb02a..ecb644a2 100644 --- a/ARMeilleure/Instructions/InstEmitMemoryHelper.cs +++ b/ARMeilleure/Instructions/InstEmitMemoryHelper.cs @@ -549,9 +549,9 @@ namespace ARMeilleure.Instructions { case OpCode32MemRsImm op: return GetMShiftedByImmediate(context, op, setCarry); - case OpCode32MemReg op: return GetIntA32(context, op.Rm); + case IOpCode32MemReg op: return GetIntA32(context, op.Rm); - case OpCode32Mem op: return Const(op.Immediate); + case IOpCode32Mem op: return Const(op.Immediate); case OpCode32SimdMemImm op: return Const(op.Immediate); diff --git a/ARMeilleure/Instructions/InstEmitMul32.cs b/ARMeilleure/Instructions/InstEmitMul32.cs index 92ed4772..868a1f42 100644 --- a/ARMeilleure/Instructions/InstEmitMul32.cs +++ b/ARMeilleure/Instructions/InstEmitMul32.cs @@ -33,7 +33,7 @@ namespace ARMeilleure.Instructions Operand res = context.Add(a, context.Multiply(n, m)); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); } @@ -250,13 +250,13 @@ namespace ARMeilleure.Instructions Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32))); Operand lo = context.ConvertI64ToI32(res); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); } - EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi); - EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo); + EmitGenericAluStoreA32(context, op.RdHi, ShouldSetFlags(context), hi); + EmitGenericAluStoreA32(context, op.RdLo, ShouldSetFlags(context), lo); } public static void Smulw_(ArmEmitterContext context) @@ -320,13 +320,13 @@ namespace ARMeilleure.Instructions Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32))); Operand lo = context.ConvertI64ToI32(res); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); } - EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi); - EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo); + EmitGenericAluStoreA32(context, op.RdHi, ShouldSetFlags(context), hi); + EmitGenericAluStoreA32(context, op.RdLo, ShouldSetFlags(context), lo); } private static void EmitMlal(ArmEmitterContext context, bool signed) @@ -356,13 +356,13 @@ namespace ARMeilleure.Instructions Operand hi = context.ConvertI64ToI32(context.ShiftRightUI(res, Const(32))); Operand lo = context.ConvertI64ToI32(res); - if (op.SetFlags) + if (ShouldSetFlags(context)) { EmitNZFlagsCheck(context, res); } - EmitGenericAluStoreA32(context, op.RdHi, op.SetFlags, hi); - EmitGenericAluStoreA32(context, op.RdLo, op.SetFlags, lo); + EmitGenericAluStoreA32(context, op.RdHi, ShouldSetFlags(context), hi); + EmitGenericAluStoreA32(context, op.RdLo, ShouldSetFlags(context), lo); } private static void UpdateQFlag(ArmEmitterContext context, Operand q) diff --git a/ARMeilleure/Instructions/InstName.cs b/ARMeilleure/Instructions/InstName.cs index 3e016495..c667ba5f 100644 --- a/ARMeilleure/Instructions/InstName.cs +++ b/ARMeilleure/Instructions/InstName.cs @@ -48,6 +48,7 @@ namespace ARMeilleure.Instructions Extr, Hint, Isb, + It, Ldar, Ldaxp, Ldaxr, @@ -512,6 +513,8 @@ namespace ARMeilleure.Instructions Mvn, Pkh, Pld, + Pop, + Push, Rev, Revsh, Rsb, diff --git a/ARMeilleure/Translation/ArmEmitterContext.cs b/ARMeilleure/Translation/ArmEmitterContext.cs index 6d02728c..33355dae 100644 --- a/ARMeilleure/Translation/ArmEmitterContext.cs +++ b/ARMeilleure/Translation/ArmEmitterContext.cs @@ -54,6 +54,11 @@ namespace ARMeilleure.Translation public bool HighCq { get; } public Aarch32Mode Mode { get; } + private int _ifThenBlockStateIndex = 0; + private Condition[] _ifThenBlockState = { }; + public bool IsInIfThenBlock => _ifThenBlockStateIndex < _ifThenBlockState.Length; + public Condition CurrentIfThenBlockCond => _ifThenBlockState[_ifThenBlockStateIndex]; + public ArmEmitterContext( IMemoryManager memory, EntryTable<uint> countTable, @@ -196,5 +201,19 @@ namespace ARMeilleure.Translation return default; } + + public void SetIfThenBlockState(Condition[] state) + { + _ifThenBlockState = state; + _ifThenBlockStateIndex = 0; + } + + public void AdvanceIfThenBlockState() + { + if (IsInIfThenBlock) + { + _ifThenBlockStateIndex++; + } + } } }
\ No newline at end of file diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs index 9974fb2d..4962a846 100644 --- a/ARMeilleure/Translation/Translator.cs +++ b/ARMeilleure/Translation/Translator.cs @@ -380,6 +380,13 @@ namespace ARMeilleure.Translation Operand lblPredicateSkip = default; + if (context.IsInIfThenBlock && context.CurrentIfThenBlockCond != Condition.Al) + { + lblPredicateSkip = Label(); + + InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, context.CurrentIfThenBlockCond.Invert()); + } + if (opCode is OpCode32 op && op.Cond < Condition.Al) { lblPredicateSkip = Label(); @@ -400,6 +407,11 @@ namespace ARMeilleure.Translation { context.MarkLabel(lblPredicateSkip); } + + if (context.IsInIfThenBlock && opCode.Instruction.Name != InstName.It) + { + context.AdvanceIfThenBlockState(); + } } } } |