public bool AppliesTo(InstructionEncoding first, InstructionEncoding second) { if ((first & ~Mask) != (second & ~Mask)) return false; return ((first & Mask) == A && (second & Mask) == B) || (first & Mask) == B && (second & Mask) == A; }
public Merge(InstructionEncoding mask, InstructionEncoding a, InstructionEncoding b, InstructionEncoding result) { this.Mask = mask; this.A = a & mask; this.B = b & mask; this.Result = result & mask; }
public static InstructionEntry GetInstruction(uint op) { InstructionEncoding encoding = InstructionEncoding.Imme; TableEntry instr = tableImmediate[op >> 26]; if (instr is InstructionEntry) { return(( InstructionEntry )instr); } while (instr is TableReference) { TableReference tref = ( TableReference )instr; TableEntry[] table = Tables[( int )encoding]; int mask = ((1 << encodingBits[( int )encoding, 1]) - 1); int shift = encodingBits[( int )encoding, 0]; int subop = ( int )(op >> shift) & mask; instr = table[subop]; if (encoding == InstructionEncoding.Rese) { return(null); //invalid instruction } if (instr == null) { return(null); } if (instr is InstructionEntry) { return(( InstructionEntry )instr); } encoding = tref.Reference; } return(null); }
private void AddInteger(string text) { ulong value = InstructionEncoding.ParseInteger(text); byte[] data = AsByteArray(value, Width, Endianness); Bytes.Add(data); TotalBytesCount += data.Length; }
public DataElement(PulsarAsmGrammarParser.Data_definition_statementContext ctx, Endianness currentEndianness) { Endianness = currentEndianness; Width = InstructionEncoding.GetDataAddressWidth(ctx.DATA_TYPE_SPECIFIER().GetText()); if (ctx.data_identifier().IDENTIFIER() != null) { SetId(ctx.data_identifier().GetText()); } Text = ctx.GetText(); }
public static void Parse(IEnumerable<NasmEncodingToken> tokens, VexOpcodeEncoding vexEncoding, out Opcode opcode, out InstructionEncoding encoding) { Contract.Requires(tokens != null); var parser = new EncodingParser(); parser.Parse(tokens, vexEncoding); opcode = parser.opcode; encoding = parser.encoding; }
public ExtendedInstructionInfo(InstructionEncoding encoding, long writeIndex, long writeSize, long eflagsIn, long eflagsOut, long dummy, long[] operandFlags, long instructionFlags, long secop) { Encoding = encoding; WriteIndex = writeIndex; WriteSize = writeSize; EflagsIn = eflagsIn; EflagsOut = eflagsOut; Reserved = dummy; OperandFlags = operandFlags; InstructionFlags = instructionFlags; SecondaryOpCode = secop; }
private static int GetOperandSizeMatchLevel(InstructionEncoding encoding, OperandSize size) { switch (encoding & InstructionEncoding.OperandSize_Mask) { case InstructionEncoding.OperandSize_Ignored: return 0; case InstructionEncoding.OperandSize_16Or32Or64: return 1; case InstructionEncoding.OperandSize_16Or32: return 2; case InstructionEncoding.OperandSize_32Or64: return 2; case InstructionEncoding.OperandSize_Fixed8: return 3; case InstructionEncoding.OperandSize_Fixed16: return size == OperandSize.Word ? 3 : -1; case InstructionEncoding.OperandSize_Fixed32: return size == OperandSize.Dword ? 3 : -1; case InstructionEncoding.OperandSize_Fixed64: return size == OperandSize.Qword ? 3 : -1; default: throw new ArgumentException(); } }
private void Parse(IEnumerable<NasmEncodingToken> tokens, VexOpcodeEncoding vexEncoding) { state = State.Prefixes; bool hasVex = false; NasmEncodingTokenType addressSize = 0; foreach (var token in tokens) { switch (token.Type) { case NasmEncodingTokenType.Vex: Contract.Assert(!hasVex); SetVex(vexEncoding); hasVex = true; break; case NasmEncodingTokenType.AddressSize_Fixed16: case NasmEncodingTokenType.AddressSize_Fixed32: case NasmEncodingTokenType.AddressSize_Fixed64: case NasmEncodingTokenType.AddressSize_NoOverride: Contract.Assert(state == State.Prefixes); Contract.Assert(addressSize == 0); addressSize = token.Type; break; case NasmEncodingTokenType.OperandSize_16: SetOperandSize(InstructionEncoding.OperandSize_Fixed16); break; case NasmEncodingTokenType.OperandSize_32: SetOperandSize(InstructionEncoding.OperandSize_Fixed32); break; case NasmEncodingTokenType.OperandSize_64: SetOperandSize(InstructionEncoding.OperandSize_Fixed64); break; case NasmEncodingTokenType.OperandSize_64WithoutW: { InstructionEncoding newOperandSize; switch (encoding & InstructionEncoding.OperandSize_Mask) { case 0: newOperandSize = InstructionEncoding.OperandSize_16Or32Or64; break; case InstructionEncoding.OperandSize_Fixed16: newOperandSize = InstructionEncoding.OperandSize_16Or32Or64; break; case InstructionEncoding.OperandSize_Fixed32: newOperandSize = InstructionEncoding.OperandSize_32Or64; break; default: throw new InvalidDataException(); } encoding &= ~InstructionEncoding.OperandSize_Mask; SetOperandSize(newOperandSize); } break; case NasmEncodingTokenType.OperandSize_NoOverride: // TODO: What does this mean for the instruction encoding? SetOperandSize(InstructionEncoding.OperandSize_16Or32); break; // Legacy prefixes case NasmEncodingTokenType.LegacyPrefix_F2: SetSimdPrefix(SimdPrefix._F2); continue; case NasmEncodingTokenType.LegacyPrefix_MustRep: case NasmEncodingTokenType.LegacyPrefix_F3: SetSimdPrefix(SimdPrefix._F3); continue; case NasmEncodingTokenType.LegacyPrefix_NoSimd: case NasmEncodingTokenType.LegacyPrefix_NoF3: case NasmEncodingTokenType.LegacyPrefix_HleAlways: case NasmEncodingTokenType.LegacyPrefix_HleWithLock: case NasmEncodingTokenType.LegacyPrefix_XReleaseAlways: case NasmEncodingTokenType.LegacyPrefix_DisassembleRepAsRepE: case NasmEncodingTokenType.LegacyPrefix_NoRep: break; // Rex case NasmEncodingTokenType.Rex_NoB: case NasmEncodingTokenType.Rex_NoW: // TODO: handle this? case NasmEncodingTokenType.Rex_LockAsRexR: // TODO: implies operand size 32 break; case NasmEncodingTokenType.Byte: if (state < State.PostSimdPrefix) { switch (token.Byte) { case 0x66: SetSimdPrefix(SimdPrefix._66); continue; case 0xF2: SetSimdPrefix(SimdPrefix._F2); continue; case 0xF3: SetSimdPrefix(SimdPrefix._F3); continue; } } if (state < State.PostOpcode) { if (!hasVex) { if ((opcode & Opcode.Map_Mask) == Opcode.Map_Default && token.Byte == 0x0F) { opcode = opcode.WithMap(OpcodeMap.Escape0F); AdvanceTo(State.Map0F); continue; } if ((opcode & Opcode.Map_Mask) == Opcode.Map_0F && (token.Byte == 0x38 || token.Byte == 0x3A)) { opcode = opcode.WithMap( token.Byte == 0x38 ? OpcodeMap.Escape0F38 : OpcodeMap.Escape0F3A); AdvanceTo(State.PostMap); continue; } } SetOpcode(InstructionEncoding.OpcodeFormat_FixedByte, token.Byte); continue; } if (state == State.PostOpcode) { SetModRM(InstructionEncoding.ModRM_Fixed, token.Byte); continue; } Contract.Assert(state == State.PostModRM); opcode = opcode.WithExtraByte(token.Byte); AddImmediate(ImmediateSize.Fixed8); // Opcode extension byte break; case NasmEncodingTokenType.Byte_PlusRegister: Contract.Assert((token.Byte & 7) == 0); if (state < State.PostOpcode) { SetOpcode(InstructionEncoding.OpcodeFormat_EmbeddedRegister, token.Byte); continue; } if (state < State.PostModRM) { SetModRM(InstructionEncoding.ModRM_FixedModReg, token.Byte); continue; } throw new FormatException(); case NasmEncodingTokenType.Byte_PlusConditionCode: // TODO: figure out what this means: [i: 71+c jlen e9 rel] Contract.Assert(state < State.PostOpcode); SetOpcode(InstructionEncoding.OpcodeFormat_EmbeddedConditionCode, (byte)(token.Byte & 0xF0)); continue; case NasmEncodingTokenType.ModRM: SetModRM(InstructionEncoding.ModRM_Any); break; case NasmEncodingTokenType.ModRM_FixedReg: SetModRM(InstructionEncoding.ModRM_FixedReg, (byte)(token.Byte << 3)); break; // Immediates case NasmEncodingTokenType.Immediate_Byte: case NasmEncodingTokenType.Immediate_Byte_Signed: case NasmEncodingTokenType.Immediate_Byte_Unsigned: case NasmEncodingTokenType.Immediate_RelativeOffset8: case NasmEncodingTokenType.Immediate_Is4: AddImmediate(ImmediateSize.Fixed8); break; case NasmEncodingTokenType.Immediate_Word: case NasmEncodingTokenType.Immediate_Segment: // TODO: Make sure this happens in the right order AddImmediate(ImmediateSize.Fixed16); break; case NasmEncodingTokenType.Immediate_Dword: case NasmEncodingTokenType.Immediate_Dword_Signed: AddImmediate(ImmediateSize.Fixed32); break; case NasmEncodingTokenType.Immediate_WordOrDword: AddImmediate(ImmediateSize.Operand16Or32); break; case NasmEncodingTokenType.Immediate_WordOrDwordOrQword: AddImmediate(ImmediateSize.Operand16Or32Or64); break; case NasmEncodingTokenType.Immediate_Qword: AddImmediate(ImmediateSize.Fixed64); break; case NasmEncodingTokenType.Immediate_RelativeOffset: switch (encoding & InstructionEncoding.OperandSize_Mask) { case InstructionEncoding.OperandSize_Ignored: AddImmediate(ImmediateSize.Operand16Or32); break; case InstructionEncoding.OperandSize_Fixed16: AddImmediate(ImmediateSize.Fixed16); break; case InstructionEncoding.OperandSize_Fixed32: AddImmediate(ImmediateSize.Fixed32); break; case InstructionEncoding.OperandSize_Fixed64: AddImmediate(ImmediateSize.Fixed64); break; case InstructionEncoding.OperandSize_16Or32: AddImmediate(ImmediateSize.Operand16Or32); break; case InstructionEncoding.OperandSize_16Or32Or64: AddImmediate(ImmediateSize.Operand16Or32Or64); break; default: throw new InvalidDataException(); } break; // Jump, it's not clear what additional info these provides so skip case NasmEncodingTokenType.Jump_8: case NasmEncodingTokenType.Jump_Conditional8: case NasmEncodingTokenType.Jump_Length: break; // Misc case NasmEncodingTokenType.VectorSib_XmmDwordIndices: case NasmEncodingTokenType.VectorSib_XmmQwordIndices: case NasmEncodingTokenType.VectorSib_YmmDwordIndices: case NasmEncodingTokenType.VectorSib_YmmQwordIndices: case NasmEncodingTokenType.VectorSib_ZmmDwordIndices: case NasmEncodingTokenType.VectorSib_ZmmQwordIndices: break; // doesn't impact encoding case NasmEncodingTokenType.Misc_NoHigh8Register: case NasmEncodingTokenType.Misc_AssembleWaitPrefix: // Implicit WAIT prefix when assembling instruction case NasmEncodingTokenType.Misc_Resb: break; default: throw new NotImplementedException("Handling NASM encoding tokens of type '{0}'".FormatInvariant(token.Type)); } } }
public static void ToOpcodeEncoding(this VexOpcodeEncoding vexEncoding, out Opcode opcode, out InstructionEncoding encoding) { opcode = default(Opcode); encoding = default(InstructionEncoding); var vexType = vexEncoding & VexOpcodeEncoding.Type_Mask; switch (vexType) { case VexOpcodeEncoding.Type_Vex: opcode |= Opcode.XexType_Vex; break; case VexOpcodeEncoding.Type_Xop: opcode |= Opcode.XexType_Xop; break; case VexOpcodeEncoding.Type_EVex: opcode |= Opcode.XexType_EVex; break; default: throw new ArgumentException(); } switch (vexEncoding & VexOpcodeEncoding.SimdPrefix_Mask) { case VexOpcodeEncoding.SimdPrefix_None: opcode |= Opcode.SimdPrefix_None; break; case VexOpcodeEncoding.SimdPrefix_66: opcode |= Opcode.SimdPrefix_66; break; case VexOpcodeEncoding.SimdPrefix_F2: opcode |= Opcode.SimdPrefix_F2; break; case VexOpcodeEncoding.SimdPrefix_F3: opcode |= Opcode.SimdPrefix_F3; break; default: throw new UnreachableException(); } switch (vexEncoding & VexOpcodeEncoding.VectorLength_Mask) { case VexOpcodeEncoding.VectorLength_0: encoding |= InstructionEncoding.VexL_Fixed; opcode |= Opcode.VexL_0; break; case VexOpcodeEncoding.VectorLength_1: encoding |= InstructionEncoding.VexL_Fixed; opcode |= Opcode.VexL_1; break; case VexOpcodeEncoding.VectorLength_2: encoding |= InstructionEncoding.VexL_Fixed; opcode |= Opcode.VexL_2; break; case VexOpcodeEncoding.VectorLength_Ignored: encoding |= InstructionEncoding.VexL_Ignored; break; } switch (vexEncoding & VexOpcodeEncoding.RexW_Mask) { case VexOpcodeEncoding.RexW_0: encoding |= InstructionEncoding.RexW_Fixed; break; case VexOpcodeEncoding.RexW_1: encoding |= InstructionEncoding.RexW_Fixed; opcode |= Opcode.RexW; break; case VexOpcodeEncoding.RexW_Ignored: encoding |= InstructionEncoding.RexW_Ignored; break; } if (vexType == VexOpcodeEncoding.Type_Xop) { switch (vexEncoding & VexOpcodeEncoding.Map_Mask) { case VexOpcodeEncoding.Map_Xop8: opcode |= Opcode.Map_Xop8; break; case VexOpcodeEncoding.Map_Xop9: opcode |= Opcode.Map_Xop9; break; case VexOpcodeEncoding.Map_Xop10: opcode |= Opcode.Map_Xop10; break; default: throw new ArgumentException(); } } else { switch (vexEncoding & VexOpcodeEncoding.Map_Mask) { case VexOpcodeEncoding.Map_0F: opcode |= Opcode.Map_0F; break; case VexOpcodeEncoding.Map_0F38: opcode |= Opcode.Map_0F38; break; case VexOpcodeEncoding.Map_0F3A: opcode |= Opcode.Map_0F3A; break; default: throw new ArgumentException(); } } opcode = opcode.WithMainByte(vexEncoding.GetMainByte()); encoding |= InstructionEncoding.OpcodeFormat_FixedByte; if ((vexEncoding & VexOpcodeEncoding.HasModRM) != 0) encoding |= InstructionEncoding.ModRM_Any; switch (vexEncoding & VexOpcodeEncoding.ImmediateType_Mask) { case VexOpcodeEncoding.ImmediateType_None: encoding = encoding.WithImmediateSizes(ImmediateSize.Zero); break; case VexOpcodeEncoding.ImmediateType_Byte: case VexOpcodeEncoding.ImmediateType_Is4: encoding = encoding.WithImmediateSizes(ImmediateSize.Fixed8); break; default: throw new ArgumentException(); } // TODO: Vvvv }
private void SetOperandSize(InstructionEncoding encoding) { Contract.Assert(state <= State.PostSimdPrefix); Contract.Assert((this.encoding & InstructionEncoding.OperandSize_Mask) == 0); this.encoding |= encoding; }
private void SetVex(VexOpcodeEncoding vexEncoding) { Contract.Requires((opcode & Opcode.XexType_Mask) == Opcode.XexType_LegacyOrRex); Contract.Requires((opcode & Opcode.SimdPrefix_Mask) == Opcode.SimdPrefix_None); Opcode opcodeFromVex; InstructionEncoding encodingFromVex; vexEncoding.ToOpcodeEncoding(out opcodeFromVex, out encodingFromVex); // TODO: Make sure these or's are safe opcode |= opcodeFromVex; encoding |= encodingFromVex; AdvanceTo(State.PostMap); }
public static string GetEncodingString(Opcode opcode, InstructionEncoding encoding) { var str = new StringBuilder(30); var xexType = opcode & Opcode.XexType_Mask; if (xexType == Opcode.XexType_LegacyOrRex) { // Legacy Xex: 66 REX.W 0F 38 switch (opcode & Opcode.SimdPrefix_Mask) { case Opcode.SimdPrefix_None: break; case Opcode.SimdPrefix_66: str.Append("66 "); break; case Opcode.SimdPrefix_F2: str.Append("F2 "); break; case Opcode.SimdPrefix_F3: str.Append("F3 "); break; default: throw new UnreachableException(); } if ((encoding & InstructionEncoding.RexW_Mask) != InstructionEncoding.RexW_Ignored && (opcode & Opcode.RexW) == Opcode.RexW) { str.Append("REX.W "); } switch (opcode & Opcode.Map_Mask) { case Opcode.Map_Default: break; case Opcode.Map_0F: str.Append("0F "); break; case Opcode.Map_0F38: str.Append("0F 38 "); break; case Opcode.Map_0F3A: str.Append("0F 3A "); break; default: throw new UnreachableException(); } } else { // Vex/Xop/EVex: VEX.NDS.LIG.66.0F3A.WIG switch (xexType) { case Opcode.XexType_Vex: str.Append("VEX"); break; case Opcode.XexType_Xop: str.Append("XOP"); break; case Opcode.XexType_EVex: str.Append("EVEX"); break; default: throw new UnreachableException(); } // TODO: Pretty print .NDS or similar switch (encoding & InstructionEncoding.VexL_Mask) { case InstructionEncoding.VexL_Fixed: switch (opcode & Opcode.VexL_Mask) { case Opcode.VexL_0: str.Append(".L0"); break; case Opcode.VexL_1: str.Append(".L1"); break; case Opcode.VexL_2: str.Append(".L2"); break; default: throw new UnreachableException(); } break; case InstructionEncoding.VexL_Ignored: str.Append(".LIG"); break; default: throw new NotImplementedException(); } switch (opcode & Opcode.SimdPrefix_Mask) { case Opcode.SimdPrefix_None: break; case Opcode.SimdPrefix_66: str.Append(".66"); break; case Opcode.SimdPrefix_F2: str.Append(".F2"); break; case Opcode.SimdPrefix_F3: str.Append(".F3"); break; default: throw new UnreachableException(); } if (xexType == Opcode.XexType_Xop) { switch (opcode & Opcode.Map_Mask) { case Opcode.Map_Xop8: str.Append(".M8"); break; case Opcode.Map_Xop9: str.Append(".M9"); break; case Opcode.Map_Xop10: str.Append(".M10"); break; default: throw new UnreachableException(); } } else { switch (opcode & Opcode.Map_Mask) { case Opcode.Map_0F: str.Append(".0F"); break; case Opcode.Map_0F38: str.Append(".0F38"); break; case Opcode.Map_0F3A: str.Append(".0F3A"); break; default: throw new UnreachableException(); } } switch (encoding & InstructionEncoding.RexW_Mask) { case InstructionEncoding.RexW_Fixed: str.Append((opcode & Opcode.RexW) == Opcode.RexW ? ".W1" : ".W0"); break; case InstructionEncoding.RexW_Ignored: str.Append(".WIG"); break; default: throw new NotImplementedException(); } str.Append(' '); } // String tail: opcode byte and what follows 0B /r ib // The opcode itself str.AppendFormat(CultureInfo.InvariantCulture, "{0:X2}", opcode.GetMainByte()); // Suffixes switch (encoding & InstructionEncoding.OpcodeFormat_Mask) { case InstructionEncoding.OpcodeFormat_FixedByte: break; case InstructionEncoding.OpcodeFormat_EmbeddedRegister: str.Append("+r"); break; case InstructionEncoding.OpcodeFormat_EmbeddedConditionCode: str.Append("+cc"); break; default: throw new UnreachableException(); } switch (encoding & InstructionEncoding.ModRM_Mask) { case InstructionEncoding.ModRM_Fixed: str.AppendFormat(CultureInfo.InvariantCulture, " {0:X2}", opcode.GetExtraByte()); break; case InstructionEncoding.ModRM_FixedModReg: str.AppendFormat(CultureInfo.InvariantCulture, " {0:X2}+r", opcode.GetExtraByte()); break; case InstructionEncoding.ModRM_FixedReg: str.Append(" /"); str.Append((char)('0' + (opcode.GetExtraByte() >> 3))); break; case InstructionEncoding.ModRM_Any: str.Append(" /r"); break; case InstructionEncoding.ModRM_None: break; default: throw new UnreachableException(); } AppendImmediate(str, encoding.GetFirstImmediateSize()); AppendImmediate(str, encoding.GetSecondImmediateSize()); return str.ToString(); }
private void SetOpcode(InstructionEncoding encoding, byte @byte) { Contract.Requires((encoding & ~InstructionEncoding.OpcodeFormat_Mask) == 0); Contract.Assert((this.encoding & InstructionEncoding.OpcodeFormat_Mask) == 0); this.encoding |= encoding; opcode = opcode.WithMainByte(@byte); AdvanceTo(State.PostOpcode); }
public static InstructionEncoding WithModRM(this InstructionEncoding encoding, InstructionEncoding format) { Contract.Requires((format & ~InstructionEncoding.ModRM_Mask) == 0); return (encoding & ~InstructionEncoding.ModRM_Mask) | format; }
public static InstructionEncoding WithOperandSize(this InstructionEncoding encoding, InstructionEncoding operandSize) { Contract.Requires((operandSize & ~InstructionEncoding.OperandSize_Mask) == 0); return (encoding & ~InstructionEncoding.OperandSize_Mask) | operandSize; }
private void SetModRM(InstructionEncoding encoding, byte @byte = 0) { Contract.Requires(state == State.PostOpcode); Contract.Requires((encoding & ~InstructionEncoding.ModRM_Mask) == 0); Contract.Requires((this.encoding & InstructionEncoding.ModRM_Mask) == InstructionEncoding.ModRM_None); this.encoding = this.encoding.WithModRM(encoding); if (encoding != InstructionEncoding.ModRM_None && encoding != InstructionEncoding.ModRM_Any) opcode = opcode.WithExtraByte(@byte); AdvanceTo(State.PostModRM); }
private void AddImmediate(ImmediateSize size) { Contract.Requires(state >= State.PostOpcode); int immediateCount = encoding.GetImmediateCount(); Contract.Requires(immediateCount < 2); encoding = (immediateCount == 0) ? encoding.WithFirstImmediateSize(size) : encoding.WithSecondImmediateSize(size); AdvanceTo(State.Immediates); }