summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp44
-rw-r--r--llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp12
-rw-r--r--llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp4
-rw-r--r--llvm/lib/Target/X86/X86.td4
-rw-r--r--llvm/lib/Target/X86/X86InstrInfo.td6
-rw-r--r--llvm/lib/Target/X86/X86Subtarget.cpp10
-rw-r--r--llvm/lib/Target/X86/X86Subtarget.h16
7 files changed, 79 insertions, 17 deletions
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 0f8e9f7b4ad..86ba1858190 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -544,9 +544,21 @@ private:
// FIXME: Can tablegen auto-generate this?
return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
}
- void SwitchMode() {
- unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(X86::Mode64Bit));
+ bool is32BitMode() const {
+ // FIXME: Can tablegen auto-generate this?
+ return (STI.getFeatureBits() & X86::Mode32Bit) != 0;
+ }
+ bool is16BitMode() const {
+ // FIXME: Can tablegen auto-generate this?
+ return (STI.getFeatureBits() & X86::Mode16Bit) != 0;
+ }
+ void SwitchMode(uint64_t mode) {
+ uint64_t oldMode = STI.getFeatureBits() &
+ (X86::Mode64Bit | X86::Mode32Bit | X86::Mode16Bit);
+ unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(oldMode | mode));
setAvailableFeatures(FB);
+ assert(mode == (STI.getFeatureBits() &
+ (X86::Mode64Bit | X86::Mode32Bit | X86::Mode16Bit)));
}
bool isParsingIntelSyntax() {
@@ -1033,7 +1045,8 @@ struct X86Operand : public MCParsedAsmOperand {
} // end anonymous namespace.
bool X86AsmParser::isSrcOp(X86Operand &Op) {
- unsigned basereg = is64BitMode() ? X86::RSI : X86::ESI;
+ unsigned basereg =
+ is64BitMode() ? X86::RSI : (is32BitMode() ? X86::ESI : X86::SI);
return (Op.isMem() &&
(Op.Mem.SegReg == 0 || Op.Mem.SegReg == X86::DS) &&
@@ -1043,7 +1056,8 @@ bool X86AsmParser::isSrcOp(X86Operand &Op) {
}
bool X86AsmParser::isDstOp(X86Operand &Op) {
- unsigned basereg = is64BitMode() ? X86::RDI : X86::EDI;
+ unsigned basereg =
+ is64BitMode() ? X86::RDI : (is32BitMode() ? X86::EDI : X86::DI);
return Op.isMem() &&
(Op.Mem.SegReg == 0 || Op.Mem.SegReg == X86::ES) &&
@@ -1193,7 +1207,8 @@ X86AsmParser::CreateMemForInlineAsm(unsigned SegReg, const MCExpr *Disp,
// operand to ensure proper matching. Just pick a GPR based on the size of
// a pointer.
if (!Info.IsVarDecl) {
- unsigned RegNo = is64BitMode() ? X86::RBX : X86::EBX;
+ unsigned RegNo =
+ is64BitMode() ? X86::RBX : (is32BitMode() ? X86::EBX : X86::BX);
return X86Operand::CreateReg(RegNo, Start, End, /*AddressOf=*/true,
SMLoc(), Identifier, Info.OpDecl);
}
@@ -1612,7 +1627,8 @@ 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 : X86::EBX;
+ unsigned RegNo =
+ is64BitMode() ? X86::RBX : (is32BitMode() ? X86::EBX : X86::BX);
return X86Operand::CreateReg(RegNo, Start, End, /*GetAddress=*/true,
OffsetOfLoc, Identifier, Info.OpDecl);
}
@@ -2679,18 +2695,24 @@ bool X86AsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
}
/// ParseDirectiveCode
-/// ::= .code32 | .code64
+/// ::= .code16 | .code32 | .code64
bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) {
- if (IDVal == ".code32") {
+ if (IDVal == ".code16") {
+ Parser.Lex();
+ if (!is16BitMode()) {
+ SwitchMode(X86::Mode16Bit);
+ getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
+ }
+ } else if (IDVal == ".code32") {
Parser.Lex();
- if (is64BitMode()) {
- SwitchMode();
+ if (!is32BitMode()) {
+ SwitchMode(X86::Mode32Bit);
getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
}
} else if (IDVal == ".code64") {
Parser.Lex();
if (!is64BitMode()) {
- SwitchMode();
+ SwitchMode(X86::Mode64Bit);
getParser().getStreamer().EmitAssemblerFlag(MCAF_Code64);
}
} else {
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
index 293541a8438..51b90b1c497 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
@@ -49,7 +49,12 @@ public:
bool is32BitMode() const {
// FIXME: Can tablegen auto-generate this?
- return (STI.getFeatureBits() & X86::Mode64Bit) == 0;
+ return (STI.getFeatureBits() & X86::Mode32Bit) != 0;
+ }
+
+ bool is16BitMode() const {
+ // FIXME: Can tablegen auto-generate this?
+ return (STI.getFeatureBits() & X86::Mode16Bit) != 0;
}
unsigned GetX86RegNum(const MCOperand &MO) const {
@@ -1177,13 +1182,16 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
assert(!Is64BitMemOperand(MI, MemOperand));
need_address_override = Is16BitMemOperand(MI, MemOperand);
} else {
- need_address_override = false;
+ assert(is16BitMode());
+ assert(!Is64BitMemOperand(MI, MemOperand));
+ need_address_override = !Is16BitMemOperand(MI, MemOperand);
}
if (need_address_override)
EmitByte(0x67, CurByte, OS);
// Emit the operand size opcode prefix as needed.
+ // FIXME for is16BitMode().
if (TSFlags & X86II::OpSize)
EmitByte(0x66, CurByte, OS);
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
index 403e50dbf8a..09803f372f5 100644
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
@@ -47,9 +47,9 @@ std::string X86_MC::ParseX86Triple(StringRef TT) {
Triple TheTriple(TT);
std::string FS;
if (TheTriple.getArch() == Triple::x86_64)
- FS = "+64bit-mode";
+ FS = "+64bit-mode,-32bit-mode,-16bit-mode";
else
- FS = "-64bit-mode";
+ FS = "-64bit-mode,+32bit-mode,-16bit-mode";
return FS;
}
diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td
index d55178ea12d..e755faeb171 100644
--- a/llvm/lib/Target/X86/X86.td
+++ b/llvm/lib/Target/X86/X86.td
@@ -22,6 +22,10 @@ include "llvm/Target/Target.td"
def Mode64Bit : SubtargetFeature<"64bit-mode", "In64BitMode", "true",
"64-bit mode (x86_64)">;
+def Mode32Bit : SubtargetFeature<"32bit-mode", "In32BitMode", "true",
+ "32-bit mode (80386)">;
+def Mode16Bit : SubtargetFeature<"16bit-mode", "In16BitMode", "true",
+ "16-bit mode (i8086)">;
//===----------------------------------------------------------------------===//
// X86 Subtarget features
diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td
index 707a313f14b..9642a8926d5 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.td
+++ b/llvm/lib/Target/X86/X86InstrInfo.td
@@ -700,6 +700,12 @@ def Not64BitMode : Predicate<"!Subtarget->is64Bit()">,
AssemblerPredicate<"!Mode64Bit", "Not 64-bit mode">;
def In64BitMode : Predicate<"Subtarget->is64Bit()">,
AssemblerPredicate<"Mode64Bit", "64-bit mode">;
+def In16BitMode : Predicate<"Subtarget->is16Bit()">,
+ AssemblerPredicate<"Mode16Bit", "16-bit mode">;
+def Not16BitMode : Predicate<"!Subtarget->is16Bit()">,
+ AssemblerPredicate<"!Mode16Bit", "Not 16-bit mode">;
+def In32BitMode : Predicate<"Subtarget->is32Bit()">,
+ AssemblerPredicate<"Mode32Bit", "32-bit mode">;
def IsWin64 : Predicate<"Subtarget->isTargetWin64()">;
def IsNaCl : Predicate<"Subtarget->isTargetNaCl()">;
def NotNaCl : Predicate<"!Subtarget->isTargetNaCl()">;
diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp
index 597fccb9fdb..5ee986c9a82 100644
--- a/llvm/lib/Target/X86/X86Subtarget.cpp
+++ b/llvm/lib/Target/X86/X86Subtarget.cpp
@@ -482,6 +482,12 @@ void X86Subtarget::resetSubtargetFeatures(StringRef CPU, StringRef FS) {
// target data structure which is shared with MC code emitter, etc.
if (In64BitMode)
ToggleFeature(X86::Mode64Bit);
+ else if (In32BitMode)
+ ToggleFeature(X86::Mode32Bit);
+ else if (In16BitMode)
+ ToggleFeature(X86::Mode16Bit);
+ else
+ llvm_unreachable("Not 16-bit, 32-bit or 64-bit mode!");
DEBUG(dbgs() << "Subtarget features: SSELevel " << X86SSELevel
<< ", 3DNowLevel " << X863DNowLevel
@@ -551,7 +557,9 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU,
, PICStyle(PICStyles::None)
, TargetTriple(TT)
, StackAlignOverride(StackAlignOverride)
- , In64BitMode(is64Bit) {
+ , In64BitMode(is64Bit)
+ , In32BitMode(!is64Bit)
+ , In16BitMode(false) {
initializeEnvironment();
resetSubtargetFeatures(CPU, FS);
}
diff --git a/llvm/lib/Target/X86/X86Subtarget.h b/llvm/lib/Target/X86/X86Subtarget.h
index 93d251a6794..f39389e08c6 100644
--- a/llvm/lib/Target/X86/X86Subtarget.h
+++ b/llvm/lib/Target/X86/X86Subtarget.h
@@ -205,9 +205,15 @@ private:
/// StackAlignOverride - Override the stack alignment.
unsigned StackAlignOverride;
- /// In64BitMode - True if compiling for 64-bit, false for 32-bit.
+ /// In64BitMode - True if compiling for 64-bit, false for 16-bit or 32-bit.
bool In64BitMode;
+ /// In32BitMode - True if compiling for 32-bit, false for 16-bit or 64-bit.
+ bool In32BitMode;
+
+ /// In16BitMode - True if compiling for 16-bit, false for 32-bit or 64-bit.
+ bool In16BitMode;
+
public:
/// This constructor initializes the data members to match that
/// of the specified triple.
@@ -244,6 +250,14 @@ public:
return In64BitMode;
}
+ bool is32Bit() const {
+ return In32BitMode;
+ }
+
+ bool is16Bit() const {
+ return In16BitMode;
+ }
+
/// Is this x86_64 with the ILP32 programming model (x32 ABI)?
bool isTarget64BitILP32() const {
return In64BitMode && (TargetTriple.getEnvironment() == Triple::GNUX32 ||
OpenPOWER on IntegriCloud