// 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() {
} // 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) &&
}
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) &&
// 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);
}
// 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);
}
}
/// 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 {
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 {
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);
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;
}
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
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()">;
// 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
, PICStyle(PICStyles::None)
, TargetTriple(TT)
, StackAlignOverride(StackAlignOverride)
- , In64BitMode(is64Bit) {
+ , In64BitMode(is64Bit)
+ , In32BitMode(!is64Bit)
+ , In16BitMode(false) {
initializeEnvironment();
resetSubtargetFeatures(CPU, FS);
}
/// 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.
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 ||
// 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]
--- /dev/null
+// 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)
+