[PATCH v2 02/14] [x86] Add basic support for .code16
Craig Topper
craig.topper at gmail.com
Sun Jan 5 17:09:11 PST 2014
+ assert(0 && "Not 16-bit, 32-bit or 64-bit mode!");
This should be llvm_unreachable("Not 16-bit, 32-bit or 64-bit mode!");
The optimizers get to have more fun with that.
On Sun, Jan 5, 2014 at 6:34 PM, David Woodhouse <dwmw2 at infradead.org> wrote:
> On Sun, 2014-01-05 at 17:22 -0600, Craig Topper wrote:
> > Looking again, I think In16BitMode in the subtarget is also
> > unitialized. It needs to be set to false by the X86Subtarget
> > constructor.
>
> Ah, right. How's this version? I think I captured everything you
> mentioned...?
>
> From 9ea3cf8ed4e1d32d3b50d380715bac6087bf7e6d Mon Sep 17 00:00:00 2001
> From: David Woodhouse <David.Woodhouse at intel.com>
> Date: Fri, 13 Dec 2013 13:10:33 +0000
> Subject: [PATCH] Add basic support for .code16
>
> This is not really expected to work right yet. Mostly because we will
> still emit the OpSize (0x66) prefix in all the wrong places, along with
> a number of other corner cases. Those will all be fixed in the subsequent
> commits.
>
> Review feedback suggested that the best approach was to enable this
> incrementally with progressive test cases, rather than a series of
> preparatory work followed by flipping the switch to actually accept
> ".code16" at the end.
> ---
> lib/Target/X86/AsmParser/X86AsmParser.cpp | 42 +++-
> lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 12 +-
> lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp | 4 +-
> lib/Target/X86/X86.td | 4 +
> lib/Target/X86/X86InstrInfo.td | 6 +
> lib/Target/X86/X86Subtarget.cpp | 10 +-
> lib/Target/X86/X86Subtarget.h | 16 +-
> test/MC/X86/address-size.s | 8 +
> test/MC/X86/x86-16.s | 259
> +++++++++++++++++++++++
> 9 files changed, 344 insertions(+), 17 deletions(-)
> create mode 100644 test/MC/X86/x86-16.s
>
> diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp
> b/lib/Target/X86/AsmParser/X86AsmParser.cpp
> index 0f8e9f7..d97ff75 100644
> --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp
> +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp
> @@ -544,8 +544,18 @@ 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);
> }
>
> @@ -1033,7 +1043,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 +1054,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 +1205,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 +1625,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 +2693,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/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
> b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
> index 293541a..5b59cb6 100644
> --- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp
> +++ b/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() && "Not 16-bit, 32-bit or 64-bit mode!");
> + 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/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
> b/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
> index 403e50d..40b1be0 100644
> --- a/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
> +++ b/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";
> else
> - FS = "-64bit-mode";
> + FS = "-64bit-mode,+32bit-mode";
> return FS;
> }
>
> diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td
> index d55178e..e755fae 100644
> --- a/lib/Target/X86/X86.td
> +++ b/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/lib/Target/X86/X86InstrInfo.td
> b/lib/Target/X86/X86InstrInfo.td
> index 707a313..9642a89 100644
> --- a/lib/Target/X86/X86InstrInfo.td
> +++ b/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/lib/Target/X86/X86Subtarget.cpp
> b/lib/Target/X86/X86Subtarget.cpp
> index 597fccb..ea8bc25 100644
> --- a/lib/Target/X86/X86Subtarget.cpp
> +++ b/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
> + assert(0 && "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/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h
> index 93d251a..f39389e 100644
> --- a/lib/Target/X86/X86Subtarget.h
> +++ b/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 ||
> diff --git a/test/MC/X86/address-size.s b/test/MC/X86/address-size.s
> index 936cd57..c9d04c4 100644
> --- a/test/MC/X86/address-size.s
> +++ b/test/MC/X86/address-size.s
> @@ -17,3 +17,11 @@
> // CHECK: encoding: [0x67,0xc7,0x00,0x78,0x56,0x34,0x12]
> movw $0x1234, 0x5678(%bp)
> // CHECK: encoding: [0x67,0x66,0xc7,0x86,0x78,0x56,0x34,0x12]
> +
> + .code16
> + movb $0x0, (%si)
> +// CHECK: encoding: [0xc6,0x04,0x00]
> + movb $0x0, (%esi)
> +// CHECK: encoding: [0x67,0xc6,0x06,0x00]
> + movb $0x5a, (%di,%bp,1)
> +// CHECK: encoding: [0xc6,0x03,0x5a]
> diff --git a/test/MC/X86/x86-16.s b/test/MC/X86/x86-16.s
> new file mode 100644
> index 0000000..36f3b19
> --- /dev/null
> +++ b/test/MC/X86/x86-16.s
> @@ -0,0 +1,259 @@
> +// RUN: llvm-mc -triple i386-unknown-unknown --show-encoding %s |
> FileCheck %s
> +
> + .code16
> +
> + pause
> +// CHECK: pause
> +// CHECK: encoding: [0xf3,0x90]
> + sfence
> +// CHECK: sfence
> +// CHECK: encoding: [0x0f,0xae,0xf8]
> + lfence
> +// CHECK: lfence
> +// CHECK: encoding: [0x0f,0xae,0xe8]
> + mfence
> + stgi
> +// CHECK: stgi
> +// CHECK: encoding: [0x0f,0x01,0xdc]
> + clgi
> +// CHECK: clgi
> +// CHECK: encoding: [0x0f,0x01,0xdd]
> +
> + rdtscp
> +// CHECK: rdtscp
> +// CHECK: encoding: [0x0f,0x01,0xf9]
> +
> +
> +// CHECK: testb %bl, %cl # encoding: [0x84,0xcb]
> + testb %bl, %cl
> +
> +into
> +// CHECK: into
> +// CHECK: encoding: [0xce]
> +int3
> +// CHECK: int3
> +// CHECK: encoding: [0xcc]
> +int $4
> +// CHECK: int $4
> +// CHECK: encoding: [0xcd,0x04]
> +int $255
> +// CHECK: int $255
> +// CHECK: encoding: [0xcd,0xff]
> +
> +// CHECK: fmul %st(0)
> +// CHECK: encoding: [0xd8,0xc8]
> + fmul %st(0), %st
> +
> +// CHECK: fadd %st(0)
> +// CHECK: encoding: [0xd8,0xc0]
> + fadd %st(0), %st
> +
> +// CHECK: fsub %st(0)
> +// CHECK: encoding: [0xd8,0xe0]
> + fsub %st(0), %st
> +
> +// CHECK: fsubr %st(0)
> +// CHECK: encoding: [0xd8,0xe8]
> + fsubr %st(0), %st
> +
> +// CHECK: fdivr %st(0)
> +// CHECK: encoding: [0xd8,0xf8]
> + fdivr %st(0), %st
> +
> +// CHECK: fdiv %st(0)
> +// CHECK: encoding: [0xd8,0xf0]
> + fdiv %st(0), %st
> +
> +// CHECK: wait
> +// CHECK: encoding: [0x9b]
> + fwait
> +
> +
> + setc %bl
> + setnae %bl
> + setnb %bl
> + setnc %bl
> + setna %bl
> + setnbe %bl
> + setpe %bl
> + setpo %bl
> + setnge %bl
> + setnl %bl
> + setng %bl
> + setnle %bl
> +
> + setneb %cl // CHECK: setne %cl
> + setcb %bl // CHECK: setb %bl
> + setnaeb %bl // CHECK: setb %bl
> +
> +
> +// CHECK: lcalll $31438, $31438
> +// CHECK: lcalll $31438, $31438
> +// CHECK: ljmpl $31438, $31438
> +// CHECK: ljmpl $31438, $31438
> +
> +calll $0x7ace,$0x7ace
> +lcalll $0x7ace,$0x7ace
> +jmpl $0x7ace,$0x7ace
> +ljmpl $0x7ace,$0x7ace
> +
> +// CHECK: calll a
> + calll a
> +
> +// CHECK: incb %al # encoding: [0xfe,0xc0]
> + incb %al
> +
> +// CHECK: decb %al # encoding: [0xfe,0xc8]
> + decb %al
> +
> +// CHECK: pshufw $14, %mm4, %mm0 # encoding: [0x0f,0x70,0xc4,0x0e]
> +pshufw $14, %mm4, %mm0
> +
> +// CHECK: pshufw $90, %mm4, %mm0 # encoding: [0x0f,0x70,0xc4,0x5a]
> +pshufw $90, %mm4, %mm0
> +
> +// CHECK: aaa
> +// CHECK: encoding: [0x37]
> + aaa
> +
> +// CHECK: aad $1
> +// CHECK: encoding: [0xd5,0x01]
> + aad $1
> +
> +// CHECK: aad
> +// CHECK: encoding: [0xd5,0x0a]
> + aad $0xA
> +
> +// CHECK: aad
> +// CHECK: encoding: [0xd5,0x0a]
> + aad
> +
> +// CHECK: aam $2
> +// CHECK: encoding: [0xd4,0x02]
> + aam $2
> +
> +// CHECK: aam
> +// CHECK: encoding: [0xd4,0x0a]
> + aam $0xA
> +
> +// CHECK: aam
> +// CHECK: encoding: [0xd4,0x0a]
> + aam
> +
> +// CHECK: aas
> +// CHECK: encoding: [0x3f]
> + aas
> +
> +// CHECK: daa
> +// CHECK: encoding: [0x27]
> + daa
> +
> +// CHECK: das
> +// CHECK: encoding: [0x2f]
> + das
> +
> +// CHECK: arpl %bx, %bx
> +// CHECK: encoding: [0x63,0xdb]
> + arpl %bx,%bx
> +
> +// CHECK: arpl %bx, 6(%ecx)
> +// CHECK: encoding: [0x67,0x63,0x59,0x06]
> + arpl %bx,6(%ecx)
> +
> +// CHECK: fcompi %st(2)
> +// CHECK: encoding: [0xdf,0xf2]
> + fcompi %st(2), %st
> +
> +// CHECK: fcompi %st(2)
> +// CHECK: encoding: [0xdf,0xf2]
> + fcompi %st(2)
> +
> +// CHECK: fcompi
> +// CHECK: encoding: [0xdf,0xf1]
> + fcompi
> +
> +// CHECK: fucompi %st(2)
> +// CHECK: encoding: [0xdf,0xea]
> + fucompi %st(2),%st
> +
> +// CHECK: fucompi %st(2)
> +// CHECK: encoding: [0xdf,0xea]
> + fucompi %st(2)
> +
> +// CHECK: fucompi
> +// CHECK: encoding: [0xdf,0xe9]
> + fucompi
> +
> +// CHECK: wait
> +// CHECK: encoding: [0x9b]
> + fclex
> +
> +// CHECK: fnclex
> +// CHECK: encoding: [0xdb,0xe2]
> + fnclex
> +
> +// CHECK: ud2
> +// CHECK: encoding: [0x0f,0x0b]
> + ud2
> +
> +// CHECK: ud2
> +// CHECK: encoding: [0x0f,0x0b]
> + ud2a
> +
> +// CHECK: ud2b
> +// CHECK: encoding: [0x0f,0xb9]
> + ud2b
> +
> +// CHECK: loope 0
> +// CHECK: encoding: [0xe1,A]
> + loopz 0
> +
> +// CHECK: loopne 0
> +// CHECK: encoding: [0xe0,A]
> + loopnz 0
> +
> +// CHECK: outsb # encoding: [0x6e]
> +// CHECK: outsb
> +// CHECK: outsb
> + outsb
> + outsb %ds:(%si), %dx
> + outsb (%si), %dx
> +
> +// CHECK: insb # encoding: [0x6c]
> +// CHECK: insb
> + insb
> + insb %dx, %es:(%di)
> +
> +// CHECK: movsb # encoding: [0xa4]
> +// CHECK: movsb
> +// CHECK: movsb
> + movsb
> + movsb %ds:(%si), %es:(%di)
> + movsb (%si), %es:(%di)
> +
> +// CHECK: lodsb # encoding: [0xac]
> +// CHECK: lodsb
> +// CHECK: lodsb
> +// CHECK: lodsb
> +// CHECK: lodsb
> + lodsb
> + lodsb %ds:(%si), %al
> + lodsb (%si), %al
> + lods %ds:(%si), %al
> + lods (%si), %al
> +
> +// CHECK: stosb # encoding: [0xaa]
> +// CHECK: stosb
> +// CHECK: stosb
> + stosb
> + stosb %al, %es:(%di)
> + stos %al, %es:(%di)
> +
> +// CHECK: fsubp
> +// CHECK: encoding: [0xde,0xe1]
> +fsubp %st,%st(1)
> +
> +// CHECK: fsubp %st(2)
> +// CHECK: encoding: [0xde,0xe2]
> +fsubp %st, %st(2)
> +
> --
> 1.8.3.1
>
>
>
> --
> dwmw2
>
>
--
~Craig
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20140105/d51ca332/attachment.html>
More information about the llvm-commits
mailing list