mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-20 19:42:54 +02:00
Add support for Code16GCC
[X86] The .code16gcc directive parses X86 assembly input in 32-bit mode and outputs in 16-bit mode. Teach parser to switch modes appropriately. Reviewers: dwmw2, craig.topper Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D20109 llvm-svn: 282430
This commit is contained in:
parent
fce59ef3ff
commit
2a4049ccf6
@ -59,6 +59,7 @@ class X86AsmParser : public MCTargetAsmParser {
|
||||
const MCInstrInfo &MII;
|
||||
ParseInstructionInfo *InstInfo;
|
||||
std::unique_ptr<X86AsmInstrumentation> Instrumentation;
|
||||
bool Code16GCC;
|
||||
|
||||
private:
|
||||
SMLoc consumeToken() {
|
||||
@ -68,6 +69,19 @@ private:
|
||||
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,
|
||||
@ -794,7 +808,8 @@ private:
|
||||
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()));
|
||||
@ -983,20 +998,20 @@ void X86AsmParser::SetFrameRegister(unsigned RegNo) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1672,8 +1687,9 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOffsetOfOperator() {
|
||||
// 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);
|
||||
}
|
||||
@ -2585,9 +2601,8 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
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
|
||||
@ -2638,8 +2653,8 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
|
||||
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;
|
||||
@ -2785,9 +2800,8 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
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);
|
||||
|
||||
@ -2805,9 +2819,8 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
|
||||
// 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;
|
||||
@ -2967,12 +2980,21 @@ bool X86AsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
|
||||
/// ::= .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()) {
|
||||
|
67
test/MC/X86/code16gcc.s
Normal file
67
test/MC/X86/code16gcc.s
Normal file
@ -0,0 +1,67 @@
|
||||
// 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]
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user