From 98e05ee4b7aa8a08088b1f0cd6c581bb50f11395 Mon Sep 17 00:00:00 2001 From: merry Date: Thu, 17 Feb 2022 22:39:45 +0000 Subject: ARMeilleure: Thumb support (All T16 instructions) (#3105) * Decoders: Add InITBlock argument * OpCodeTable: Minor cleanup * OpCodeTable: Remove existing thumb instruction implementations * OpCodeTable: Prepare for thumb instructions * OpCodeTables: Improve thumb fast lookup * Tests: Prepare for thumb tests * T16: Implement BX * T16: Implement LSL/LSR/ASR (imm) * T16: Implement ADDS, SUBS (reg) * T16: Implement ADDS, SUBS (3-bit immediate) * T16: Implement MOVS, CMP, ADDS, SUBS (8-bit immediate) * T16: Implement ANDS, EORS, LSLS, LSRS, ASRS, ADCS, SBCS, RORS, TST, NEGS, CMP, CMN, ORRS, MULS, BICS, MVNS (low registers) * T16: Implement ADD, CMP, MOV (high reg) * T16: Implement BLX (reg) * T16: Implement LDR (literal) * T16: Implement {LDR,STR}{,H,B,SB,SH} (register) * T16: Implement {LDR,STR}{,B,H} (immediate) * T16: Implement LDR/STR (SP) * T16: Implement ADR * T16: Implement Add to SP (immediate) * T16: Implement ADD/SUB (SP) * T16: Implement SXTH, SXTB, UXTH, UTXB * T16: Implement CBZ, CBNZ * T16: Implement PUSH, POP * T16: Implement REV, REV16, REVSH * T16: Implement NOP * T16: Implement LDM, STM * T16: Implement SVC * T16: Implement B (conditional) * T16: Implement B (unconditional) * T16: Implement IT * fixup! T16: Implement ADD/SUB (SP) * fixup! T16: Implement Add to SP (immediate) * fixup! T16: Implement IT * CpuTestThumb: Add randomized tests * Remove inITBlock argument * Address nits * Use index to handle IfThenBlockState * Reduce line noise * fixup * nit --- ARMeilleure/Decoders/OpCodeTable.cs | 134 +++++++++++++++++++++++++++--------- 1 file changed, 103 insertions(+), 31 deletions(-) (limited to 'ARMeilleure/Decoders/OpCodeTable.cs') 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 AllInstA32 = new List(); - private static List AllInstT32 = new List(); - private static List AllInstA64 = new List(); + private static List AllInstA32 = new(); + private static List AllInstT32 = new(); + private static List 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<>>>", InstName.It, InstEmit32.It, OpCodeT16IfThen.Create); + SetT16("11000xxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT16MemMult.Create); + SetT16("11001xxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT16MemMult.Create); + SetT16("1101<< allInsts) + private static void FillFastLookupTable(InstInfo[][] table, List allInsts, Func ToFastLookupIndex) { List[] temp = new List[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 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; + } } } -- cgit v1.2.3