[PATCH] [x86] Add x86_16 target

David Woodhouse dwmw2 at infradead.org
Wed Jan 8 05:48:47 PST 2014


This is now fairly trivial. With the corresponding patch (qv) to Clang
to enable -m16, and with PR18303 fixed and PR3997 worked around, I can
now correctly build all the Linux kernel's 16-bit startup code and get a
bootable kernel.

The x86_16 target is equivalent to building with GCC and
asm(".code16gcc"). It doesn't have sizeof(int)==2 etc.; it uses the same
ABI as 32-bit x86, and you just see a lot of OpSize and AdSize prefixes
in the resulting code. Thus, it won't actually run on a *real* i8086 but
it does work fine on modern CPUs in 16-bit mode.

---
 include/llvm/ADT/Triple.h                       |  1 +
 lib/MC/MCObjectFileInfo.cpp                     |  5 ++--
 lib/Support/Triple.cpp                          | 10 +++++++-
 lib/Target/TargetLibraryInfo.cpp                |  2 +-
 lib/Target/X86/AsmParser/X86AsmParser.cpp       |  1 +
 lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp | 32 +++++++++++++++++++++----
 lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h   |  2 +-
 lib/Target/X86/TargetInfo/X86TargetInfo.cpp     |  5 +++-
 lib/Target/X86/X86AsmPrinter.cpp                |  1 +
 lib/Target/X86/X86Subtarget.cpp                 |  2 +-
 lib/Target/X86/X86TargetMachine.cpp             |  1 +
 11 files changed, 50 insertions(+), 12 deletions(-)

diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h
index 314ee4e..633c6c4 100644
--- a/include/llvm/ADT/Triple.h
+++ b/include/llvm/ADT/Triple.h
@@ -65,6 +65,7 @@ public:
     thumb,   // Thumb: thumb, thumbv.*
     x86,     // X86: i[3-9]86
     x86_64,  // X86-64: amd64, x86_64
+    x86_16,  // X86-16: 16-bit mode (equivalent to .code16gcc)
     xcore,   // XCore: xcore
     nvptx,   // NVPTX: 32-bit
     nvptx64, // NVPTX: 64-bit
diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp
index 5d7a5f8..5d28667 100644
--- a/lib/MC/MCObjectFileInfo.cpp
+++ b/lib/MC/MCObjectFileInfo.cpp
@@ -156,7 +156,8 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) {
                            MCSectionMachO::S_ATTR_DEBUG,
                            SectionKind::getReadOnly());
 
-    if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86)
+    if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86 ||
+        T.getArch() == Triple::x86_16)
       CompactUnwindDwarfEHFrameOnly = 0x04000000;
   }
 
@@ -252,7 +253,7 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) {
   else
     FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4;
 
-  if (T.getArch() == Triple::x86) {
+  if (T.getArch() == Triple::x86 || T.getArch() == Triple::x86_16) {
     PersonalityEncoding = (RelocM == Reloc::PIC_)
      ? dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4
      : dwarf::DW_EH_PE_absptr;
diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp
index 273316a..8acf319 100644
--- a/lib/Support/Triple.cpp
+++ b/lib/Support/Triple.cpp
@@ -38,6 +38,7 @@ const char *Triple::getArchTypeName(ArchType Kind) {
   case thumb:   return "thumb";
   case x86:     return "i386";
   case x86_64:  return "x86_64";
+  case x86_16:  return "x86_16";
   case xcore:   return "xcore";
   case nvptx:   return "nvptx";
   case nvptx64: return "nvptx64";
@@ -79,7 +80,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) {
   case systemz: return "systemz";
 
   case x86:
-  case x86_64:  return "x86";
+  case x86_64:
+  case x86_16:  return "x86";
 
   case xcore:   return "xcore";
 
@@ -181,6 +183,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
     .Case("thumb", thumb)
     .Case("x86", x86)
     .Case("x86-64", x86_64)
+    .Case("x86-16", x86_16)
     .Case("xcore", xcore)
     .Case("nvptx", nvptx)
     .Case("nvptx64", nvptx64)
@@ -199,6 +202,7 @@ const char *Triple::getArchNameForAssembler() {
   return StringSwitch<const char*>(getArchName())
     .Case("i386", "i386")
     .Case("x86_64", "x86_64")
+    .Case("x86_16", "x86_16")
     .Case("powerpc", "ppc")
     .Case("powerpc64", "ppc64")
     .Case("powerpc64le", "ppc64le")
@@ -223,6 +227,7 @@ static Triple::ArchType parseArch(StringRef ArchName) {
     // FIXME: Do we need to support these?
     .Cases("i786", "i886", "i986", Triple::x86)
     .Cases("amd64", "x86_64", "x86_64h", Triple::x86_64)
+    .Cases("x86_16", "i8086", "i86", Triple::x86_16)
     .Case("powerpc", Triple::ppc)
     .Cases("powerpc64", "ppu", Triple::ppc64)
     .Case("powerpc64le", Triple::ppc64le)
@@ -688,6 +693,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) {
   case llvm::Triple::tce:
   case llvm::Triple::thumb:
   case llvm::Triple::x86:
+  case llvm::Triple::x86_16:
   case llvm::Triple::xcore:
   case llvm::Triple::spir:
     return 32;
@@ -744,6 +750,7 @@ Triple Triple::get32BitArchVariant() const {
   case Triple::tce:
   case Triple::thumb:
   case Triple::x86:
+  case Triple::x86_16:
   case Triple::xcore:
     // Already 32-bit.
     break;
@@ -793,6 +800,7 @@ Triple Triple::get64BitArchVariant() const {
   case Triple::nvptx:   T.setArch(Triple::nvptx64);   break;
   case Triple::ppc:     T.setArch(Triple::ppc64);     break;
   case Triple::sparc:   T.setArch(Triple::sparcv9);   break;
+  case Triple::x86_16:
   case Triple::x86:     T.setArch(Triple::x86_64);    break;
   case Triple::spir:    T.setArch(Triple::spir64);    break;
   }
diff --git a/lib/Target/TargetLibraryInfo.cpp b/lib/Target/TargetLibraryInfo.cpp
index 93c008a..59fc07d 100644
--- a/lib/Target/TargetLibraryInfo.cpp
+++ b/lib/Target/TargetLibraryInfo.cpp
@@ -349,7 +349,7 @@ static bool hasSinCosPiStret(const Triple &T) {
     return false;
 
   // The ABI is rather complicated on x86, so don't do anything special there.
-  if (T.getArch() == Triple::x86)
+  if (T.getArch() == Triple::x86 || T.getArch() == Triple::x86_16)
     return false;
 
   if (T.isMacOSX() && T.isMacOSXVersionLT(10, 9))
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 3ed20d9..c2cde2e 100644
--- a/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -2759,6 +2759,7 @@ bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) {
 
 // Force static initialization.
 extern "C" void LLVMInitializeX86AsmParser() {
+  RegisterMCAsmParser<X86AsmParser> W(TheX86_16Target);
   RegisterMCAsmParser<X86AsmParser> X(TheX86_32Target);
   RegisterMCAsmParser<X86AsmParser> Y(TheX86_64Target);
 }
diff --git a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
index 9d5ff10..0fdd9de 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
@@ -48,8 +48,12 @@ std::string X86_MC::ParseX86Triple(StringRef TT) {
   std::string FS;
   if (TheTriple.getArch() == Triple::x86_64)
     FS = "+64bit-mode,-32bit-mode,-16bit-mode";
-  else
+  else if (TheTriple.getArch() == Triple::x86)
     FS = "-64bit-mode,+32bit-mode,-16bit-mode";
+  else if (TheTriple.getArch() == Triple::x86_16)
+    FS = "-64bit-mode,-32bit-mode,+16bit-mode";
+  else
+    llvm_unreachable("no valid arch type");
   return FS;
 }
 
@@ -402,58 +406,76 @@ static MCInstrAnalysis *createX86MCInstrAnalysis(const MCInstrInfo *Info) {
 // Force static initialization.
 extern "C" void LLVMInitializeX86TargetMC() {
   // Register the MC asm info.
-  RegisterMCAsmInfoFn A(TheX86_32Target, createX86MCAsmInfo);
-  RegisterMCAsmInfoFn B(TheX86_64Target, createX86MCAsmInfo);
+  RegisterMCAsmInfoFn A(TheX86_16Target, createX86MCAsmInfo);
+  RegisterMCAsmInfoFn B(TheX86_32Target, createX86MCAsmInfo);
+  RegisterMCAsmInfoFn C(TheX86_64Target, createX86MCAsmInfo);
 
   // Register the MC codegen info.
-  RegisterMCCodeGenInfoFn C(TheX86_32Target, createX86MCCodeGenInfo);
-  RegisterMCCodeGenInfoFn D(TheX86_64Target, createX86MCCodeGenInfo);
+  RegisterMCCodeGenInfoFn D(TheX86_16Target, createX86MCCodeGenInfo);
+  RegisterMCCodeGenInfoFn E(TheX86_32Target, createX86MCCodeGenInfo);
+  RegisterMCCodeGenInfoFn F(TheX86_64Target, createX86MCCodeGenInfo);
 
   // Register the MC instruction info.
+  TargetRegistry::RegisterMCInstrInfo(TheX86_16Target, createX86MCInstrInfo);
   TargetRegistry::RegisterMCInstrInfo(TheX86_32Target, createX86MCInstrInfo);
   TargetRegistry::RegisterMCInstrInfo(TheX86_64Target, createX86MCInstrInfo);
 
   // Register the MC register info.
+  TargetRegistry::RegisterMCRegInfo(TheX86_16Target, createX86MCRegisterInfo);
   TargetRegistry::RegisterMCRegInfo(TheX86_32Target, createX86MCRegisterInfo);
   TargetRegistry::RegisterMCRegInfo(TheX86_64Target, createX86MCRegisterInfo);
 
   // Register the MC subtarget info.
+  TargetRegistry::RegisterMCSubtargetInfo(TheX86_16Target,
+                                          X86_MC::createX86MCSubtargetInfo);
   TargetRegistry::RegisterMCSubtargetInfo(TheX86_32Target,
                                           X86_MC::createX86MCSubtargetInfo);
   TargetRegistry::RegisterMCSubtargetInfo(TheX86_64Target,
                                           X86_MC::createX86MCSubtargetInfo);
 
   // Register the MC instruction analyzer.
+  TargetRegistry::RegisterMCInstrAnalysis(TheX86_16Target,
+                                          createX86MCInstrAnalysis);
   TargetRegistry::RegisterMCInstrAnalysis(TheX86_32Target,
                                           createX86MCInstrAnalysis);
   TargetRegistry::RegisterMCInstrAnalysis(TheX86_64Target,
                                           createX86MCInstrAnalysis);
 
   // Register the code emitter.
+  TargetRegistry::RegisterMCCodeEmitter(TheX86_16Target,
+                                        createX86MCCodeEmitter);
   TargetRegistry::RegisterMCCodeEmitter(TheX86_32Target,
                                         createX86MCCodeEmitter);
   TargetRegistry::RegisterMCCodeEmitter(TheX86_64Target,
                                         createX86MCCodeEmitter);
 
   // Register the asm backend.
+  TargetRegistry::RegisterMCAsmBackend(TheX86_16Target,
+                                       createX86_32AsmBackend);
   TargetRegistry::RegisterMCAsmBackend(TheX86_32Target,
                                        createX86_32AsmBackend);
   TargetRegistry::RegisterMCAsmBackend(TheX86_64Target,
                                        createX86_64AsmBackend);
 
   // Register the object streamer.
+  TargetRegistry::RegisterMCObjectStreamer(TheX86_16Target,
+                                           createMCStreamer);
   TargetRegistry::RegisterMCObjectStreamer(TheX86_32Target,
                                            createMCStreamer);
   TargetRegistry::RegisterMCObjectStreamer(TheX86_64Target,
                                            createMCStreamer);
 
   // Register the MCInstPrinter.
+  TargetRegistry::RegisterMCInstPrinter(TheX86_16Target,
+                                        createX86MCInstPrinter);
   TargetRegistry::RegisterMCInstPrinter(TheX86_32Target,
                                         createX86MCInstPrinter);
   TargetRegistry::RegisterMCInstPrinter(TheX86_64Target,
                                         createX86MCInstPrinter);
 
   // Register the MC relocation info.
+  TargetRegistry::RegisterMCRelocationInfo(TheX86_16Target,
+                                           createX86MCRelocationInfo);
   TargetRegistry::RegisterMCRelocationInfo(TheX86_32Target,
                                            createX86MCRelocationInfo);
   TargetRegistry::RegisterMCRelocationInfo(TheX86_64Target,
diff --git a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
index 41ae435..6febed2 100644
--- a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
+++ b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h
@@ -30,7 +30,7 @@ class Target;
 class StringRef;
 class raw_ostream;
 
-extern Target TheX86_32Target, TheX86_64Target;
+extern Target TheX86_16Target, TheX86_32Target, TheX86_64Target;
 
 /// DWARFFlavour - Flavour of dwarf regnumbers
 ///
diff --git a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
index 815d235..4e89c25 100644
--- a/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
+++ b/lib/Target/X86/TargetInfo/X86TargetInfo.cpp
@@ -12,9 +12,12 @@
 #include "llvm/Support/TargetRegistry.h"
 using namespace llvm;
 
-Target llvm::TheX86_32Target, llvm::TheX86_64Target;
+Target llvm::TheX86_16Target, llvm::TheX86_32Target, llvm::TheX86_64Target;
 
 extern "C" void LLVMInitializeX86TargetInfo() { 
+  RegisterTarget<Triple::x86_16, /*HasJIT=*/true>
+    W(TheX86_16Target, "x86-16", "16-bit X86: Pentium-Pro and above");
+
   RegisterTarget<Triple::x86, /*HasJIT=*/true>
     X(TheX86_32Target, "x86", "32-bit X86: Pentium-Pro and above");
 
diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp
index 70f9e17..513b6de 100644
--- a/lib/Target/X86/X86AsmPrinter.cpp
+++ b/lib/Target/X86/X86AsmPrinter.cpp
@@ -718,6 +718,7 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
 
 // Force static initialization.
 extern "C" void LLVMInitializeX86AsmPrinter() {
+  RegisterAsmPrinter<X86AsmPrinter> W(TheX86_16Target);
   RegisterAsmPrinter<X86AsmPrinter> X(TheX86_32Target);
   RegisterAsmPrinter<X86AsmPrinter> Y(TheX86_64Target);
 }
diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp
index b183ed0..cc8935b 100644
--- a/lib/Target/X86/X86Subtarget.cpp
+++ b/lib/Target/X86/X86Subtarget.cpp
@@ -559,7 +559,7 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &CPU,
   , StackAlignOverride(StackAlignOverride)
   , In64BitMode(TargetTriple.getArch() == Triple::x86_64)
   , In32BitMode(TargetTriple.getArch() == Triple::x86)
-  , In16BitMode(false) {
+  , In16BitMode(TargetTriple.getArch() == Triple::x86_16) {
   initializeEnvironment();
   resetSubtargetFeatures(CPU, FS);
 }
diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp
index 462dae3..1a903b8 100644
--- a/lib/Target/X86/X86TargetMachine.cpp
+++ b/lib/Target/X86/X86TargetMachine.cpp
@@ -24,6 +24,7 @@ using namespace llvm;
 
 extern "C" void LLVMInitializeX86Target() {
   // Register the target.
+  RegisterTargetMachine<X86TargetMachine> W(TheX86_16Target);
   RegisterTargetMachine<X86TargetMachine> X(TheX86_32Target);
   RegisterTargetMachine<X86TargetMachine> Y(TheX86_64Target);
 }
-- 
1.8.4.2


-- 
dwmw2
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 5745 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140108/9736ac1a/attachment.bin>


More information about the llvm-commits mailing list