Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 134d28b

Browse files
committed
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282430 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 786045e commit 134d28b

File tree

2 files changed

+109
-20
lines changed

2 files changed

+109
-20
lines changed

lib/Target/X86/AsmParser/X86AsmParser.cpp

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class X86AsmParser : public MCTargetAsmParser {
5959
const MCInstrInfo &MII;
6060
ParseInstructionInfo *InstInfo;
6161
std::unique_ptr<X86AsmInstrumentation> Instrumentation;
62+
bool Code16GCC;
6263

6364
private:
6465
SMLoc consumeToken() {
@@ -68,6 +69,19 @@ class X86AsmParser : public MCTargetAsmParser {
6869
return Result;
6970
}
7071

72+
unsigned MatchInstruction(const OperandVector &Operands, MCInst &Inst,
73+
uint64_t &ErrorInfo, bool matchingInlineAsm,
74+
unsigned VariantID = 0) {
75+
// In Code16GCC mode, match as 32-bit.
76+
if (Code16GCC)
77+
SwitchMode(X86::Mode32Bit);
78+
unsigned rv = MatchInstructionImpl(Operands, Inst, ErrorInfo,
79+
matchingInlineAsm, VariantID);
80+
if (Code16GCC)
81+
SwitchMode(X86::Mode16Bit);
82+
return rv;
83+
}
84+
7185
enum InfixCalculatorTok {
7286
IC_OR = 0,
7387
IC_XOR,
@@ -794,7 +808,8 @@ class X86AsmParser : public MCTargetAsmParser {
794808
public:
795809
X86AsmParser(const MCSubtargetInfo &sti, MCAsmParser &Parser,
796810
const MCInstrInfo &mii, const MCTargetOptions &Options)
797-
: MCTargetAsmParser(Options, sti), MII(mii), InstInfo(nullptr) {
811+
: MCTargetAsmParser(Options, sti), MII(mii), InstInfo(nullptr),
812+
Code16GCC(false) {
798813

799814
// Initialize the set of available features.
800815
setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
@@ -983,20 +998,20 @@ void X86AsmParser::SetFrameRegister(unsigned RegNo) {
983998
}
984999

9851000
std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
986-
unsigned basereg =
987-
is64BitMode() ? X86::RSI : (is32BitMode() ? X86::ESI : X86::SI);
1001+
bool Parse32 = is32BitMode() || Code16GCC;
1002+
unsigned Basereg = is64BitMode() ? X86::RSI : (Parse32 ? X86::ESI : X86::SI);
9881003
const MCExpr *Disp = MCConstantExpr::create(0, getContext());
9891004
return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
990-
/*BaseReg=*/basereg, /*IndexReg=*/0, /*Scale=*/1,
1005+
/*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,
9911006
Loc, Loc, 0);
9921007
}
9931008

9941009
std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(SMLoc Loc) {
995-
unsigned basereg =
996-
is64BitMode() ? X86::RDI : (is32BitMode() ? X86::EDI : X86::DI);
1010+
bool Parse32 = is32BitMode() || Code16GCC;
1011+
unsigned Basereg = is64BitMode() ? X86::RDI : (Parse32 ? X86::EDI : X86::DI);
9971012
const MCExpr *Disp = MCConstantExpr::create(0, getContext());
9981013
return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
999-
/*BaseReg=*/basereg, /*IndexReg=*/0, /*Scale=*/1,
1014+
/*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,
10001015
Loc, Loc, 0);
10011016
}
10021017

@@ -1672,8 +1687,9 @@ std::unique_ptr<X86Operand> X86AsmParser::ParseIntelOffsetOfOperator() {
16721687
// The offset operator will have an 'r' constraint, thus we need to create
16731688
// register operand to ensure proper matching. Just pick a GPR based on
16741689
// the size of a pointer.
1675-
unsigned RegNo =
1676-
is64BitMode() ? X86::RBX : (is32BitMode() ? X86::EBX : X86::BX);
1690+
bool Parse32 = is32BitMode() || Code16GCC;
1691+
unsigned RegNo = is64BitMode() ? X86::RBX : (Parse32 ? X86::EBX : X86::BX);
1692+
16771693
return X86Operand::CreateReg(RegNo, Start, End, /*GetAddress=*/true,
16781694
OffsetOfLoc, Identifier, Info.OpDecl);
16791695
}
@@ -2585,9 +2601,8 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
25852601
MCInst Inst;
25862602

25872603
// First, try a direct match.
2588-
switch (MatchInstructionImpl(Operands, Inst,
2589-
ErrorInfo, MatchingInlineAsm,
2590-
isParsingIntelSyntax())) {
2604+
switch (MatchInstruction(Operands, Inst, ErrorInfo, MatchingInlineAsm,
2605+
isParsingIntelSyntax())) {
25912606
default: llvm_unreachable("Unexpected match result!");
25922607
case Match_Success:
25932608
// Some instructions need post-processing to, for example, tweak which
@@ -2638,8 +2653,8 @@ bool X86AsmParser::MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode,
26382653

26392654
for (unsigned I = 0, E = array_lengthof(Match); I != E; ++I) {
26402655
Tmp.back() = Suffixes[I];
2641-
Match[I] = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore,
2642-
MatchingInlineAsm, isParsingIntelSyntax());
2656+
Match[I] = MatchInstruction(Operands, Inst, ErrorInfoIgnore,
2657+
MatchingInlineAsm, isParsingIntelSyntax());
26432658
// If this returned as a missing feature failure, remember that.
26442659
if (Match[I] == Match_MissingFeature)
26452660
ErrorInfoMissingFeature = ErrorInfoIgnore;
@@ -2785,9 +2800,8 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
27852800
UnsizedMemOp->Mem.Size = Size;
27862801
uint64_t ErrorInfoIgnore;
27872802
unsigned LastOpcode = Inst.getOpcode();
2788-
unsigned M =
2789-
MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore,
2790-
MatchingInlineAsm, isParsingIntelSyntax());
2803+
unsigned M = MatchInstruction(Operands, Inst, ErrorInfoIgnore,
2804+
MatchingInlineAsm, isParsingIntelSyntax());
27912805
if (Match.empty() || LastOpcode != Inst.getOpcode())
27922806
Match.push_back(M);
27932807

@@ -2805,9 +2819,8 @@ bool X86AsmParser::MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode,
28052819
// operation. There shouldn't be any ambiguity in our mnemonic table, so try
28062820
// matching with the unsized operand.
28072821
if (Match.empty()) {
2808-
Match.push_back(MatchInstructionImpl(Operands, Inst, ErrorInfo,
2809-
MatchingInlineAsm,
2810-
isParsingIntelSyntax()));
2822+
Match.push_back(MatchInstruction(
2823+
Operands, Inst, ErrorInfo, MatchingInlineAsm, isParsingIntelSyntax()));
28112824
// If this returned as a missing feature failure, remember that.
28122825
if (Match.back() == Match_MissingFeature)
28132826
ErrorInfoMissingFeature = ErrorInfo;
@@ -2967,12 +2980,21 @@ bool X86AsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
29672980
/// ::= .code16 | .code32 | .code64
29682981
bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) {
29692982
MCAsmParser &Parser = getParser();
2983+
Code16GCC = false;
29702984
if (IDVal == ".code16") {
29712985
Parser.Lex();
29722986
if (!is16BitMode()) {
29732987
SwitchMode(X86::Mode16Bit);
29742988
getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
29752989
}
2990+
} else if (IDVal == ".code16gcc") {
2991+
// .code16gcc parses as if in 32-bit mode, but emits code in 16-bit mode.
2992+
Parser.Lex();
2993+
Code16GCC = true;
2994+
if (!is16BitMode()) {
2995+
SwitchMode(X86::Mode16Bit);
2996+
getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
2997+
}
29762998
} else if (IDVal == ".code32") {
29772999
Parser.Lex();
29783000
if (!is32BitMode()) {

test/MC/X86/code16gcc.s

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// RUN: llvm-mc -triple i386-unknown-unknown-unknown --show-encoding %s | FileCheck %s
2+
3+
.code16gcc
4+
//CHECK: .code16
5+
nop
6+
//CHECK: nop # encoding: [0x90]
7+
lodsb
8+
//CHECK: lodsb (%esi), %al # encoding: [0x67,0xac]
9+
lodsb (%si), %al
10+
//CHECK: lodsb (%si), %al # encoding: [0xac]
11+
lodsb (%esi), %al
12+
//CHECK: lodsb (%esi), %al # encoding: [0x67,0xac]
13+
lodsl %gs:(%esi)
14+
//CHECK: lodsl %gs:(%esi), %eax # encoding: [0x66,0x65,0x67,0xad]
15+
lods (%esi), %ax
16+
//CHECK: lodsw (%esi), %ax # encoding: [0x67,0xad]
17+
stosw
18+
//CHECK: stosw %ax, %es:(%edi) # encoding: [0x67,0xab]
19+
stos %eax, (%edi)
20+
//CHECK: stosl %eax, %es:(%edi) # encoding: [0x66,0x67,0xab]
21+
stosb %al, %es:(%edi)
22+
//CHECK: stosb %al, %es:(%edi) # encoding: [0x67,0xaa]
23+
scas %es:(%edi), %al
24+
//CHECK: scasb %es:(%edi), %al # encoding: [0x67,0xae]
25+
scas %es:(%di), %ax
26+
//CHECK: scasw %es:(%di), %ax # encoding: [0xaf]
27+
cmpsb
28+
//CHECK: cmpsb %es:(%edi), (%esi) # encoding: [0x67,0xa6]
29+
cmpsw (%edi), (%esi)
30+
//CHECK: cmpsw %es:(%edi), (%esi) # encoding: [0x67,0xa7]
31+
cmpsl %es:(%edi), %ss:(%esi)
32+
//CHECK: cmpsl %es:(%edi), %ss:(%esi) # encoding: [0x66,0x36,0x67,0xa7]
33+
movsb (%esi), (%edi)
34+
//CHECK: movsb (%esi), %es:(%edi) # encoding: [0x67,0xa4]
35+
movsl %gs:(%esi), (%edi)
36+
//CHECK: movsl %gs:(%esi), %es:(%edi) # encoding: [0x66,0x65,0x67,0xa5]
37+
outsb
38+
//CHECK: outsb (%esi), %dx # encoding: [0x67,0x6e]
39+
outsw %fs:(%esi), %dx
40+
//CHECK: outsw %fs:(%esi), %dx # encoding: [0x64,0x67,0x6f]
41+
insw %dx, (%di)
42+
//CHECK: insw %dx, %es:(%di) # encoding: [0x6d]
43+
call $0x7ace,$0x7ace
44+
//CHECK: lcalll $31438, $31438 # encoding: [0x66,0x9a,0xce,0x7a,0x00,0x00,0xce,0x7a]
45+
ret
46+
//CHECK: retl # encoding: [0x66,0xc3]
47+
pop %ss
48+
//CHECK: popl %ss # encoding: [0x66,0x17]
49+
enter $0x7ace,$0x7f
50+
//CHECK: enter $31438, $127 # encoding: [0xc8,0xce,0x7a,0x7f]
51+
leave
52+
//CHECK: leave # encoding: [0xc9]
53+
push %ss
54+
//CHECK: pushl %ss # encoding: [0x66,0x16]
55+
pop %ss
56+
//CHECK: popl %ss # encoding: [0x66,0x17]
57+
popa
58+
//CHECK: popal # encoding: [0x66,0x61]
59+
pushf
60+
//CHECK: pushfl # encoding: [0x66,0x9c]
61+
popf
62+
//CHECK: popfl # encoding: [0x66,0x9d]
63+
pushw 4
64+
//CHECK: pushw 4 # encoding: [0xff,0x36,0x04,0x00]
65+
66+
67+

0 commit comments

Comments
 (0)