diff --git a/Cpp2IL.Core/InstructionSets/X86InstructionSet.cs b/Cpp2IL.Core/InstructionSets/X86InstructionSet.cs index 11d20f59..1e42e8ab 100644 --- a/Cpp2IL.Core/InstructionSets/X86InstructionSet.cs +++ b/Cpp2IL.Core/InstructionSets/X86InstructionSet.cs @@ -503,9 +503,8 @@ ISIL.Instruction Add(ulong address, ISIL.OpCode opCode, params object[] operands AddCompareInstruction(instruction.IP, ConvertOperand(instruction, 0), 0); break; } - - //Fall through to cmp, as test is just a cmp that doesn't set flags - goto case Mnemonic.Cmp; + AddTestInstruction(instruction.IP, ConvertOperand(instruction, 0), ConvertOperand(instruction, 1)); + break; case Mnemonic.Cmp: case Mnemonic.Comiss: //comiss is just a floating point compare dest[31:0] == src[31:0] case Mnemonic.Ucomiss: // same, but unsigned @@ -791,6 +790,22 @@ void AddCompareInstruction(ulong ip, object op0, object op1) Add(ip, ISIL.OpCode.And, temp5, temp2, 1); // temp5 = tmp2 & 1 Add(ip, ISIL.OpCode.CheckEqual, new ISIL.Register(null, "PF"), temp5, 0); // PF = temp5 == 0 } + + void AddTestInstruction(ulong ip, object op0, object op1) + { + var temp = new ISIL.Register(null, "TEMP"); + var temp2 = new ISIL.Register(null, "TEMP2"); + var temp5 = new ISIL.Register(null, "TEMP5"); + + Add(ip, ISIL.OpCode.And, temp, op0, op1); // temp = op0 & op1 + Add(ip, ISIL.OpCode.CheckEqual, new ISIL.Register(null, "ZF"), temp, 0); // ZF = temp == 0 + Add(ip, ISIL.OpCode.CheckLess, new ISIL.Register(null, "SF"), temp, 0); // SF = temp < 0 + Add(ip, ISIL.OpCode.Move, new ISIL.Register(null, "CF"), 0); // CF = 0 + Add(ip, ISIL.OpCode.Move, new ISIL.Register(null, "OF"), 0); // OF = 0 + Add(ip, ISIL.OpCode.Xor, temp2, temp, 0); // temp2 = temp ^ 0 + Add(ip, ISIL.OpCode.And, temp5, temp2, 1); // temp5 = temp2 & 1 + Add(ip, ISIL.OpCode.CheckEqual, new ISIL.Register(null, "PF"), temp5, 0); // PF = temp5 == 0 + } }