From f468db76028086a6645856383fecdf8180b04dd1 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 10 Sep 2022 22:51:00 -0300 Subject: [PATCH] Implement Thumb (32-bit) memory (ordered), multiply, extension and bitfield instructions (#3687) * Implement Thumb (32-bit) memory (ordered), multiply and bitfield instructions * Remove public from interface * Fix T32 BL immediate and implement signed and unsigned extend instructions --- ARMeilleure/Decoders/IOpCode32AluBf.cs | 3 + ARMeilleure/Decoders/IOpCode32AluImm16.cs | 7 ++ ARMeilleure/Decoders/IOpCode32AluMla.cs | 11 +++ ARMeilleure/Decoders/IOpCode32AluUmull.cs | 13 ++++ ARMeilleure/Decoders/OpCode32AluBf.cs | 4 - ARMeilleure/Decoders/OpCode32AluImm16.cs | 2 +- ARMeilleure/Decoders/OpCode32AluMla.cs | 2 +- ARMeilleure/Decoders/OpCode32AluUmull.cs | 4 +- ARMeilleure/Decoders/OpCodeT32AluBf.cs | 22 ++++++ ARMeilleure/Decoders/OpCodeT32AluMla.cs | 29 +++++++ ARMeilleure/Decoders/OpCodeT32AluUmull.cs | 28 +++++++ ARMeilleure/Decoders/OpCodeT32AluUx.cs | 18 +++++ ARMeilleure/Decoders/OpCodeT32BImm24.cs | 2 +- ARMeilleure/Decoders/OpCodeT32MemLdEx.cs | 2 + ARMeilleure/Decoders/OpCodeT32MemStEx.cs | 2 + ARMeilleure/Decoders/OpCodeT32MovImm16.cs | 5 +- ARMeilleure/Decoders/OpCodeTable.cs | 75 +++++++++++++++---- ARMeilleure/Instructions/InstEmitAlu32.cs | 10 +-- ARMeilleure/Instructions/InstEmitAluHelper.cs | 2 +- .../Instructions/InstEmitMemoryEx32.cs | 6 +- ARMeilleure/Instructions/InstEmitMul32.cs | 24 +++--- 21 files changed, 221 insertions(+), 50 deletions(-) create mode 100644 ARMeilleure/Decoders/IOpCode32AluImm16.cs create mode 100644 ARMeilleure/Decoders/IOpCode32AluMla.cs create mode 100644 ARMeilleure/Decoders/IOpCode32AluUmull.cs create mode 100644 ARMeilleure/Decoders/OpCodeT32AluBf.cs create mode 100644 ARMeilleure/Decoders/OpCodeT32AluMla.cs create mode 100644 ARMeilleure/Decoders/OpCodeT32AluUmull.cs create mode 100644 ARMeilleure/Decoders/OpCodeT32AluUx.cs diff --git a/ARMeilleure/Decoders/IOpCode32AluBf.cs b/ARMeilleure/Decoders/IOpCode32AluBf.cs index 18de3eb6..206c2965 100644 --- a/ARMeilleure/Decoders/IOpCode32AluBf.cs +++ b/ARMeilleure/Decoders/IOpCode32AluBf.cs @@ -7,5 +7,8 @@ int Msb { get; } int Lsb { get; } + + int SourceMask => (int)(0xFFFFFFFF >> (31 - Msb)); + int DestMask => SourceMask & (int)(0xFFFFFFFF << Lsb); } } diff --git a/ARMeilleure/Decoders/IOpCode32AluImm16.cs b/ARMeilleure/Decoders/IOpCode32AluImm16.cs new file mode 100644 index 00000000..cd128f65 --- /dev/null +++ b/ARMeilleure/Decoders/IOpCode32AluImm16.cs @@ -0,0 +1,7 @@ +namespace ARMeilleure.Decoders +{ + interface IOpCode32AluImm16 : IOpCode32Alu + { + int Immediate { get; } + } +} \ No newline at end of file diff --git a/ARMeilleure/Decoders/IOpCode32AluMla.cs b/ARMeilleure/Decoders/IOpCode32AluMla.cs new file mode 100644 index 00000000..79b16425 --- /dev/null +++ b/ARMeilleure/Decoders/IOpCode32AluMla.cs @@ -0,0 +1,11 @@ +namespace ARMeilleure.Decoders +{ + interface IOpCode32AluMla : IOpCode32AluReg + { + int Ra { get; } + + bool NHigh { get; } + bool MHigh { get; } + bool R { get; } + } +} diff --git a/ARMeilleure/Decoders/IOpCode32AluUmull.cs b/ARMeilleure/Decoders/IOpCode32AluUmull.cs new file mode 100644 index 00000000..79d2bb9b --- /dev/null +++ b/ARMeilleure/Decoders/IOpCode32AluUmull.cs @@ -0,0 +1,13 @@ +namespace ARMeilleure.Decoders +{ + interface IOpCode32AluUmull : IOpCode32, IOpCode32HasSetFlags + { + int RdLo { get; } + int RdHi { get; } + int Rn { get; } + int Rm { get; } + + bool NHigh { get; } + bool MHigh { get; } + } +} diff --git a/ARMeilleure/Decoders/OpCode32AluBf.cs b/ARMeilleure/Decoders/OpCode32AluBf.cs index f8dc6db0..0cee34e6 100644 --- a/ARMeilleure/Decoders/OpCode32AluBf.cs +++ b/ARMeilleure/Decoders/OpCode32AluBf.cs @@ -6,12 +6,8 @@ public int Rn { get; } public int Msb { get; } - public int Lsb { get; } - public int SourceMask => (int)(0xFFFFFFFF >> (31 - Msb)); - public int DestMask => SourceMask & (int)(0xFFFFFFFF << Lsb); - public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluBf(inst, address, opCode); public OpCode32AluBf(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) diff --git a/ARMeilleure/Decoders/OpCode32AluImm16.cs b/ARMeilleure/Decoders/OpCode32AluImm16.cs index 66248271..e24edeb4 100644 --- a/ARMeilleure/Decoders/OpCode32AluImm16.cs +++ b/ARMeilleure/Decoders/OpCode32AluImm16.cs @@ -1,6 +1,6 @@ namespace ARMeilleure.Decoders { - class OpCode32AluImm16 : OpCode32Alu + class OpCode32AluImm16 : OpCode32Alu, IOpCode32AluImm16 { public int Immediate { get; } diff --git a/ARMeilleure/Decoders/OpCode32AluMla.cs b/ARMeilleure/Decoders/OpCode32AluMla.cs index 74894667..2cd2b9dc 100644 --- a/ARMeilleure/Decoders/OpCode32AluMla.cs +++ b/ARMeilleure/Decoders/OpCode32AluMla.cs @@ -1,6 +1,6 @@ namespace ARMeilleure.Decoders { - class OpCode32AluMla : OpCode32, IOpCode32AluReg + class OpCode32AluMla : OpCode32, IOpCode32AluMla { public int Rn { get; } public int Rm { get; } diff --git a/ARMeilleure/Decoders/OpCode32AluUmull.cs b/ARMeilleure/Decoders/OpCode32AluUmull.cs index 1b31239b..bf80df3f 100644 --- a/ARMeilleure/Decoders/OpCode32AluUmull.cs +++ b/ARMeilleure/Decoders/OpCode32AluUmull.cs @@ -1,6 +1,6 @@ namespace ARMeilleure.Decoders { - class OpCode32AluUmull : OpCode32, IOpCode32HasSetFlags + class OpCode32AluUmull : OpCode32, IOpCode32AluUmull { public int RdLo { get; } public int RdHi { get; } @@ -11,7 +11,6 @@ public bool MHigh { 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); @@ -26,7 +25,6 @@ MHigh = ((opCode >> 6) & 0x1) == 1; SetFlags = ((opCode >> 20) & 0x1) != 0; - DataOp = DataOp.Arithmetic; } } } diff --git a/ARMeilleure/Decoders/OpCodeT32AluBf.cs b/ARMeilleure/Decoders/OpCodeT32AluBf.cs new file mode 100644 index 00000000..57ad422f --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT32AluBf.cs @@ -0,0 +1,22 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT32AluBf : OpCodeT32, IOpCode32AluBf + { + public int Rd { get; } + public int Rn { get; } + + public int Msb { get; } + public int Lsb { get; } + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluBf(inst, address, opCode); + + public OpCodeT32AluBf(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rd = (opCode >> 8) & 0xf; + Rn = (opCode >> 16) & 0xf; + + Msb = (opCode >> 0) & 0x1f; + Lsb = ((opCode >> 6) & 0x3) | ((opCode >> 10) & 0x1c); + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT32AluMla.cs b/ARMeilleure/Decoders/OpCodeT32AluMla.cs new file mode 100644 index 00000000..6cb604da --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT32AluMla.cs @@ -0,0 +1,29 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT32AluMla : OpCodeT32, IOpCode32AluMla + { + public int Rn { get; } + public int Rm { get; } + public int Ra { get; } + public int Rd { get; } + + public bool NHigh { get; } + public bool MHigh { get; } + public bool R { get; } + public bool? SetFlags => false; + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluMla(inst, address, opCode); + + public OpCodeT32AluMla(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rm = (opCode >> 0) & 0xf; + Rd = (opCode >> 8) & 0xf; + Ra = (opCode >> 12) & 0xf; + Rn = (opCode >> 16) & 0xf; + R = (opCode & (1 << 4)) != 0; + + MHigh = ((opCode >> 4) & 0x1) == 1; + NHigh = ((opCode >> 5) & 0x1) == 1; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT32AluUmull.cs b/ARMeilleure/Decoders/OpCodeT32AluUmull.cs new file mode 100644 index 00000000..a1b2e612 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT32AluUmull.cs @@ -0,0 +1,28 @@ +namespace ARMeilleure.Decoders +{ + class OpCodeT32AluUmull : OpCodeT32, IOpCode32AluUmull + { + public int RdLo { get; } + public int RdHi { get; } + public int Rn { get; } + public int Rm { get; } + + public bool NHigh { get; } + public bool MHigh { get; } + + public bool? SetFlags => false; + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluUmull(inst, address, opCode); + + public OpCodeT32AluUmull(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rm = (opCode >> 0) & 0xf; + RdHi = (opCode >> 8) & 0xf; + RdLo = (opCode >> 12) & 0xf; + Rn = (opCode >> 16) & 0xf; + + MHigh = ((opCode >> 4) & 0x1) == 1; + NHigh = ((opCode >> 5) & 0x1) == 1; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT32AluUx.cs b/ARMeilleure/Decoders/OpCodeT32AluUx.cs new file mode 100644 index 00000000..861dc904 --- /dev/null +++ b/ARMeilleure/Decoders/OpCodeT32AluUx.cs @@ -0,0 +1,18 @@ +using ARMeilleure.State; + +namespace ARMeilleure.Decoders +{ + class OpCodeT32AluUx : OpCodeT32AluReg, IOpCode32AluUx + { + public int Rotate { get; } + public int RotateBits => Rotate * 8; + public bool Add => Rn != RegisterAlias.Aarch32Pc; + + public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluUx(inst, address, opCode); + + public OpCodeT32AluUx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) + { + Rotate = (opCode >> 4) & 0x3; + } + } +} diff --git a/ARMeilleure/Decoders/OpCodeT32BImm24.cs b/ARMeilleure/Decoders/OpCodeT32BImm24.cs index 4381be47..774ec3a6 100644 --- a/ARMeilleure/Decoders/OpCodeT32BImm24.cs +++ b/ARMeilleure/Decoders/OpCodeT32BImm24.cs @@ -27,7 +27,7 @@ namespace ARMeilleure.Decoders int i2 = j2 ^ s ^ 1; int imm32 = imm11 | (imm10 << 11) | (i2 << 21) | (i1 << 22) | (s << 23); - imm32 = (imm32 << 9) >> 8; + imm32 = (imm32 << 8) >> 7; Immediate = pc + imm32; } diff --git a/ARMeilleure/Decoders/OpCodeT32MemLdEx.cs b/ARMeilleure/Decoders/OpCodeT32MemLdEx.cs index da565f61..c8eb36b3 100644 --- a/ARMeilleure/Decoders/OpCodeT32MemLdEx.cs +++ b/ARMeilleure/Decoders/OpCodeT32MemLdEx.cs @@ -4,6 +4,7 @@ namespace ARMeilleure.Decoders { public int Rd => 0; public int Rt { get; } + public int Rt2 { get; } public int Rn { get; } public bool WBack => false; @@ -17,6 +18,7 @@ namespace ARMeilleure.Decoders public OpCodeT32MemLdEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { + Rt2 = (opCode >> 8) & 0xf; Rt = (opCode >> 12) & 0xf; Rn = (opCode >> 16) & 0xf; } diff --git a/ARMeilleure/Decoders/OpCodeT32MemStEx.cs b/ARMeilleure/Decoders/OpCodeT32MemStEx.cs index 8fe1950e..6a0a6bb1 100644 --- a/ARMeilleure/Decoders/OpCodeT32MemStEx.cs +++ b/ARMeilleure/Decoders/OpCodeT32MemStEx.cs @@ -4,6 +4,7 @@ namespace ARMeilleure.Decoders { public int Rd { get; } public int Rt { get; } + public int Rt2 { get; } public int Rn { get; } public bool WBack => false; @@ -18,6 +19,7 @@ namespace ARMeilleure.Decoders public OpCodeT32MemStEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { Rd = (opCode >> 0) & 0xf; + Rt2 = (opCode >> 8) & 0xf; Rt = (opCode >> 12) & 0xf; Rn = (opCode >> 16) & 0xf; } diff --git a/ARMeilleure/Decoders/OpCodeT32MovImm16.cs b/ARMeilleure/Decoders/OpCodeT32MovImm16.cs index 55db012c..5161892b 100644 --- a/ARMeilleure/Decoders/OpCodeT32MovImm16.cs +++ b/ARMeilleure/Decoders/OpCodeT32MovImm16.cs @@ -1,9 +1,6 @@ -using ARMeilleure.Common; -using System.Runtime.Intrinsics; - namespace ARMeilleure.Decoders { - class OpCodeT32MovImm16 : OpCodeT32Alu, IOpCode32AluImm + class OpCodeT32MovImm16 : OpCodeT32Alu, IOpCode32AluImm16 { public int Immediate { get; } diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index a7793681..034707b9 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -1074,6 +1074,8 @@ namespace ARMeilleure.Decoders SetT32("11110x00000xxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm8.Create); @@ -1135,18 +1167,31 @@ namespace ARMeilleure.Decoders SetT32("111110000100<<<xxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm8.Create); SetT32("111110001000xxxxxxxxxxxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm12.Create); + SetT32("111110000000<<<xxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm8.Create); SetT32("111110001010xxxxxxxxxxxxxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm12.Create); + SetT32("111110000010<<<