const MCInstrInfo &MII;
ParseInstructionInfo *InstInfo;
std::unique_ptr<X86AsmInstrumentation> Instrumentation;
+ bool Code16GCC;
private:
SMLoc consumeToken() {
return Result;
}
+ unsigned MatchInstruction(const OperandVector &Operands, MCInst &Inst,
+ uint64_t &ErrorInfo, bool matchingInlineAsm,
+ unsigned VariantID = 0) {
+ // In Code16GCC mode, match as 32-bit.
+ if (Code16GCC)
+ SwitchMode(X86::Mode32Bit);
+ unsigned rv = MatchInstructionImpl(Operands, Inst, ErrorInfo,
+ matchingInlineAsm, VariantID);
+ if (Code16GCC)
+ SwitchMode(X86::Mode16Bit);
+ return rv;
+ }
+
enum InfixCalculatorTok {
IC_OR = 0,
IC_XOR,
public:
X86AsmParser(const MCSubtargetInfo &sti, MCAsmParser &Parser,
const MCInstrInfo &mii, const MCTargetOptions &Options)
- : MCTargetAsmParser(Options, sti), MII(mii), InstInfo(nullptr) {
+ : MCTargetAsmParser(Options, sti), MII(mii), InstInfo(nullptr),
+ Code16GCC(false) {
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
}
std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
- unsigned basereg =
- is64BitMode() ? X86::RSI : (is32BitMode() ? X86::ESI : X86::SI);
+ bool Parse32 = is32BitMode() || Code16GCC;
+ unsigned Basereg = is64BitMode() ? X86::RSI : (Parse32 ? X86::ESI : X86::SI);
const MCExpr *Disp = MCConstantExpr::create(0, getContext());
return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
- /*BaseReg=*/basereg, /*IndexReg=*/0, /*Scale=*/1,
+ /*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,
Loc, Loc, 0);
}
std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(SMLoc Loc) {
- unsigned basereg =
- is64BitMode() ? X86::RDI : (is32BitMode() ? X86::EDI : X86::DI);
+ bool Parse32 = is32BitMode() || Code16GCC;
+ unsigned Basereg = is64BitMode() ? X86::RDI : (Parse32 ? X86::EDI : X86::DI);
const MCExpr *Disp = MCConstantExpr::create(0, getContext());
return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
- /*BaseReg=*/basereg, /*IndexReg=*/0, /*Scale=*/1,
+ /*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,
Loc, Loc, 0);
}
// The offset operator will have an 'r' constraint, thus we need to create
// register operand to ensure proper matching. Just pick a GPR based on
// the size of a pointer.
- unsigned RegNo =
- is64BitMode() ? X86::RBX : (is32BitMode() ? X86::EBX : X86::BX);
+ bool Parse32 = is32BitMode() || Code16GCC;
+ unsigned RegNo = is64BitMode() ? X86::RBX : (Parse32 ? X86::EBX : X86::BX);
+
return X86Operand::CreateReg(RegNo, Start, End, /*GetAddress=*/true,
OffsetOfLoc, Identifier, Info.OpDecl);
}
MCInst Inst;
// First, try a direct match.
- switch (MatchInstructionImpl(Operands, Inst,
- ErrorInfo, MatchingInlineAsm,
- isParsingIntelSyntax())) {
+ switch (MatchInstruction(Operands, Inst, ErrorInfo, MatchingInlineAsm,
+ isParsingIntelSyntax())) {
default: llvm_unreachable("Unexpected match result!");
case Match_Success:
// Some instructions need post-processing to, for example, tweak which
for (unsigned I = 0, E = array_lengthof(Match); I != E; ++I) {
Tmp.back() = Suffixes[I];
- Match[I] = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore,
- MatchingInlineAsm, isParsingIntelSyntax());
+ Match[I] = MatchInstruction(Operands, Inst, ErrorInfoIgnore,
+ MatchingInlineAsm, isParsingIntelSyntax());
// If this returned as a missing feature failure, remember that.
if (Match[I] == Match_MissingFeature)
ErrorInfoMissingFeature = ErrorInfoIgnore;
UnsizedMemOp->Mem.Size = Size;
uint64_t ErrorInfoIgnore;
unsigned LastOpcode = Inst.getOpcode();
- unsigned M =
- MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore,
- MatchingInlineAsm, isParsingIntelSyntax());
+ unsigned M = MatchInstruction(Operands, Inst, ErrorInfoIgnore,
+ MatchingInlineAsm, isParsingIntelSyntax());
if (Match.empty() || LastOpcode != Inst.getOpcode())
Match.push_back(M);
// operation. There shouldn't be any ambiguity in our mnemonic table, so try
// matching with the unsized operand.
if (Match.empty()) {
- Match.push_back(MatchInstructionImpl(Operands, Inst, ErrorInfo,
- MatchingInlineAsm,
- isParsingIntelSyntax()));
+ Match.push_back(MatchInstruction(
+ Operands, Inst, ErrorInfo, MatchingInlineAsm, isParsingIntelSyntax()));
// If this returned as a missing feature failure, remember that.
if (Match.back() == Match_MissingFeature)
ErrorInfoMissingFeature = ErrorInfo;
/// ::= .code16 | .code32 | .code64
bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) {
MCAsmParser &Parser = getParser();
+ Code16GCC = false;
if (IDVal == ".code16") {
Parser.Lex();
if (!is16BitMode()) {
SwitchMode(X86::Mode16Bit);
getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
}
+ } else if (IDVal == ".code16gcc") {
+ // .code16gcc parses as if in 32-bit mode, but emits code in 16-bit mode.
+ Parser.Lex();
+ Code16GCC = true;
+ if (!is16BitMode()) {
+ SwitchMode(X86::Mode16Bit);
+ getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
+ }
} else if (IDVal == ".code32") {
Parser.Lex();
if (!is32BitMode()) {
--- /dev/null
+// RUN: llvm-mc -triple i386-unknown-unknown-unknown --show-encoding %s | FileCheck %s
+
+ .code16gcc
+ //CHECK: .code16
+ nop
+ //CHECK: nop # encoding: [0x90]
+ lodsb
+ //CHECK: lodsb (%esi), %al # encoding: [0x67,0xac]
+ lodsb (%si), %al
+ //CHECK: lodsb (%si), %al # encoding: [0xac]
+ lodsb (%esi), %al
+ //CHECK: lodsb (%esi), %al # encoding: [0x67,0xac]
+ lodsl %gs:(%esi)
+ //CHECK: lodsl %gs:(%esi), %eax # encoding: [0x66,0x65,0x67,0xad]
+ lods (%esi), %ax
+ //CHECK: lodsw (%esi), %ax # encoding: [0x67,0xad]
+ stosw
+ //CHECK: stosw %ax, %es:(%edi) # encoding: [0x67,0xab]
+ stos %eax, (%edi)
+ //CHECK: stosl %eax, %es:(%edi) # encoding: [0x66,0x67,0xab]
+ stosb %al, %es:(%edi)
+ //CHECK: stosb %al, %es:(%edi) # encoding: [0x67,0xaa]
+ scas %es:(%edi), %al
+ //CHECK: scasb %es:(%edi), %al # encoding: [0x67,0xae]
+ scas %es:(%di), %ax
+ //CHECK: scasw %es:(%di), %ax # encoding: [0xaf]
+ cmpsb
+ //CHECK: cmpsb %es:(%edi), (%esi) # encoding: [0x67,0xa6]
+ cmpsw (%edi), (%esi)
+ //CHECK: cmpsw %es:(%edi), (%esi) # encoding: [0x67,0xa7]
+ cmpsl %es:(%edi), %ss:(%esi)
+ //CHECK: cmpsl %es:(%edi), %ss:(%esi) # encoding: [0x66,0x36,0x67,0xa7]
+ movsb (%esi), (%edi)
+ //CHECK: movsb (%esi), %es:(%edi) # encoding: [0x67,0xa4]
+ movsl %gs:(%esi), (%edi)
+ //CHECK: movsl %gs:(%esi), %es:(%edi) # encoding: [0x66,0x65,0x67,0xa5]
+ outsb
+ //CHECK: outsb (%esi), %dx # encoding: [0x67,0x6e]
+ outsw %fs:(%esi), %dx
+ //CHECK: outsw %fs:(%esi), %dx # encoding: [0x64,0x67,0x6f]
+ insw %dx, (%di)
+ //CHECK: insw %dx, %es:(%di) # encoding: [0x6d]
+ call $0x7ace,$0x7ace
+ //CHECK: lcalll $31438, $31438 # encoding: [0x66,0x9a,0xce,0x7a,0x00,0x00,0xce,0x7a]
+ ret
+ //CHECK: retl # encoding: [0x66,0xc3]
+ pop %ss
+ //CHECK: popl %ss # encoding: [0x66,0x17]
+ enter $0x7ace,$0x7f
+ //CHECK: enter $31438, $127 # encoding: [0xc8,0xce,0x7a,0x7f]
+ leave
+ //CHECK: leave # encoding: [0xc9]
+ push %ss
+ //CHECK: pushl %ss # encoding: [0x66,0x16]
+ pop %ss
+ //CHECK: popl %ss # encoding: [0x66,0x17]
+ popa
+ //CHECK: popal # encoding: [0x66,0x61]
+ pushf
+ //CHECK: pushfl # encoding: [0x66,0x9c]
+ popf
+ //CHECK: popfl # encoding: [0x66,0x9d]
+ pushw 4
+ //CHECK: pushw 4 # encoding: [0xff,0x36,0x04,0x00]
+
+
+