private static void ParseFlags(NasmInsnsEntry.Builder entryBuilder, string str) { if (str == "ignore") return; foreach (var flagStr in str.Split(',')) { var enumerantName = char.IsDigit(flagStr[0]) ? '_' + flagStr : flagStr; var flag = (NasmInstructionFlag)Enum.Parse(typeof(NasmInstructionFlag), enumerantName, ignoreCase: true); entryBuilder.Flags.Add(flag); } }
private static void ParseVex(NasmInsnsEntry.Builder entryBuilder, string str) { var tokens = str.ToLowerInvariant().Split('.'); int tokenIndex = 0; VexOpcodeEncoding encoding = 0; switch (tokens[tokenIndex++]) { case "vex": encoding |= VexOpcodeEncoding.Type_Vex; break; case "xop": encoding |= VexOpcodeEncoding.Type_Xop; break; case "evex": encoding |= VexOpcodeEncoding.Type_EVex; break; default: throw new FormatException(); } if (tokens[tokenIndex][0] == 'm') { // AMD-Style // xop.m8.w0.nds.l0.p0 // vex.m3.w0.nds.l0.p1 ParseVex_Map(ref encoding, tokens, ref tokenIndex); ParseVex_RexW(ref encoding, tokens, ref tokenIndex); ParseVex_Vvvv(ref encoding, tokens, ref tokenIndex); ParseVex_VectorLength(ref encoding, tokens, ref tokenIndex); ParseVex_SimdPrefix_AmdStyle(ref encoding, tokens, ref tokenIndex); } else { // Intel-Style // vex.nds.256.66.0f3a.w0 // evex.nds.512.66.0f3a.w0 ParseVex_Vvvv(ref encoding, tokens, ref tokenIndex); ParseVex_VectorLength(ref encoding, tokens, ref tokenIndex); ParseVex_SimdPrefix_IntelStyle(ref encoding, tokens, ref tokenIndex); ParseVex_Map(ref encoding, tokens, ref tokenIndex); ParseVex_RexW(ref encoding, tokens, ref tokenIndex); } entryBuilder.EncodingTokens.Add(NasmEncodingTokenType.Vex); entryBuilder.VexEncoding = encoding; }
private static void ParseOperands(NasmInsnsEntry.Builder entryBuilder, string fieldsString, string valuesString) { if (valuesString == "void" || valuesString == "ignore") { Contract.Assert(fieldsString.Length == 0); return; } if (fieldsString.Length == 0) { // This only happens for pseudo-instructions return; } valuesString = valuesString.Replace("*", string.Empty); // '*' is for "relaxed", but it's not clear what this encodes var values = Regex.Split(valuesString, "[,:]"); if (fieldsString == "r+mi") { // Hack around the IMUL special case fieldsString = "rmi"; values = new[] { values[0], values[0].Replace("reg", "rm"), values[1] }; } Contract.Assert(values.Length == fieldsString.Length); for (int i = 0; i < values.Length; ++i) { var field = ParseOperandField(fieldsString[i]); var valueComponents = values[i].Split('|'); var typeString = valueComponents[0]; var type = (NasmOperandType)Enum.Parse(typeof(NasmOperandType), valueComponents[0], ignoreCase: true); entryBuilder.Operands.Add(new NasmOperand(field, type)); // TODO: Parse NASM operand flags (after the '|') // TODO: Support star'ed types like "xmmreg*" } }
private static void ParseCodeString(NasmInsnsEntry.Builder entryBuilder, string str) { var tokens = str.Split(' '); int tokenIndex = 0; bool hasVex = false; while (tokenIndex < tokens.Length) { var token = tokens[tokenIndex++]; var tokenType = NasmEncodingToken.TryParseType(token); if (tokenType != NasmEncodingTokenType.None) { entryBuilder.EncodingTokens.Add(tokenType); continue; } byte @byte; if (Regex.IsMatch(token, @"\A[0-9a-f]{2}(\+[rc])?\Z") && byte.TryParse(token.Substring(0, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out @byte)) { var type = NasmEncodingTokenType.Byte; if (token.Length == 4) { type = token[token.Length - 1] == 'r' ? NasmEncodingTokenType.Byte_PlusRegister : NasmEncodingTokenType.Byte_PlusConditionCode; } entryBuilder.EncodingTokens.Add(new NasmEncodingToken(type, @byte)); continue; } if (Regex.IsMatch(token, @"\A/[0-7]\Z")) { entryBuilder.EncodingTokens.Add(new NasmEncodingToken(NasmEncodingTokenType.ModRM_FixedReg, (byte)(token[1] - '0'))); continue; } if (Regex.IsMatch(token, @"\A(vex|xop|evex)\.")) { Contract.Assert(!hasVex); ParseVex(entryBuilder, token); hasVex = true; continue; } throw new FormatException("Unexpected NASM encoding token '{0}'".FormatInvariant(token)); } }