aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/X86/InstSelectSimple.cpp61
-rw-r--r--lib/Target/X86/Printer.cpp91
-rw-r--r--lib/Target/X86/X86.td26
-rw-r--r--lib/Target/X86/X86AsmPrinter.cpp91
-rw-r--r--lib/Target/X86/X86ISelSimple.cpp61
-rw-r--r--lib/Target/X86/X86InstrInfo.h10
-rw-r--r--lib/Target/X86/X86InstrInfo.td27
7 files changed, 324 insertions, 43 deletions
diff --git a/lib/Target/X86/InstSelectSimple.cpp b/lib/Target/X86/InstSelectSimple.cpp
index 4a04b2910f..4988a0dc4c 100644
--- a/lib/Target/X86/InstSelectSimple.cpp
+++ b/lib/Target/X86/InstSelectSimple.cpp
@@ -1502,6 +1502,8 @@ void ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) {
case Intrinsic::frameaddress:
case Intrinsic::memcpy:
case Intrinsic::memset:
+ case Intrinsic::readport:
+ case Intrinsic::writeport:
// We directly implement these intrinsics
break;
default:
@@ -1663,6 +1665,65 @@ void ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) {
return;
}
+ case Intrinsic::readport:
+ //
+ // First, determine that the size of the operand falls within the
+ // acceptable range for this architecture.
+ //
+ assert (((CI.getOperand(1)->getType()->getPrimitiveSize()) == 2) &&
+ "llvm.readport operand size is not a 16 bit value!");
+
+ //
+ // Now, move the I/O port address into the DX register and use the IN
+ // instruction to get the input data.
+ //
+ BuildMI(BB, X86::MOV16rr, 1, X86::DX).addReg(getReg(CI.getOperand(1)));
+ switch (CI.getCalledFunction()->getReturnType()->getPrimitiveSize()) {
+ case 1:
+ BuildMI(BB, X86::IN8, 1);
+ break;
+ case 2:
+ BuildMI(BB, X86::IN16, 1);
+ break;
+ case 4:
+ BuildMI(BB, X86::IN32, 1);
+ break;
+ default:
+ assert (0 && "Cannot do input on this data type");
+ }
+ return;
+
+ case Intrinsic::writeport:
+ //
+ // First, determine that the size of the operand falls within the
+ // acceptable range for this architecture.
+ //
+ assert (((CI.getOperand(1)->getType()->getPrimitiveSize()) == 2) &&
+ "llvm.readport operand size is not a 16 bit value!");
+
+ //
+ // Now, move the I/O port address into the DX register and the value to
+ // write into the AL/AX/EAX register.
+ //
+ BuildMI(BB, X86::MOV16rr, 1, X86::DX).addReg(getReg(CI.getOperand(1)));
+ switch (CI.getOperand(2)->getType()->getPrimitiveSize()) {
+ case 1:
+ BuildMI(BB, X86::MOV8rr, 1, X86::AL).addReg(getReg(CI.getOperand(2)));
+ BuildMI(BB, X86::OUT8, 1);
+ break;
+ case 2:
+ BuildMI(BB, X86::MOV16rr, 1, X86::AX).addReg(getReg(CI.getOperand(2)));
+ BuildMI(BB, X86::OUT16, 1);
+ break;
+ case 4:
+ BuildMI(BB, X86::MOV32rr, 1, X86::EAX).addReg(getReg(CI.getOperand(2)));
+ BuildMI(BB, X86::OUT32, 1);
+ break;
+ default:
+ assert (0 && "Cannot do input on this data type");
+ }
+ return;
+
default: assert(0 && "Error: unknown intrinsics should have been lowered!");
}
}
diff --git a/lib/Target/X86/Printer.cpp b/lib/Target/X86/Printer.cpp
index 73971bbe7f..e2f06846d9 100644
--- a/lib/Target/X86/Printer.cpp
+++ b/lib/Target/X86/Printer.cpp
@@ -105,7 +105,8 @@ namespace {
}
void printImplUsesBefore(const TargetInstrDescriptor &Desc);
- void printImplUsesAfter(const TargetInstrDescriptor &Desc);
+ bool printImplUsesAfter(const TargetInstrDescriptor &Desc, const bool LC);
+ bool printImplDefsAfter(const TargetInstrDescriptor &Desc, const bool LC);
void printMachineInstruction(const MachineInstr *MI);
void printOp(const MachineOperand &MO,
bool elideOffsetKeyword = false);
@@ -546,14 +547,65 @@ void Printer::printImplUsesBefore(const TargetInstrDescriptor &Desc) {
/// printImplUsesAfter - Emit the implicit-use registers for the instruction
/// described by DESC, if its PrintImplUsesAfter flag is set.
///
-void Printer::printImplUsesAfter(const TargetInstrDescriptor &Desc) {
+/// Inputs:
+/// Comma - List of registers will need a leading comma.
+/// Desc - Description of the Instruction.
+///
+/// Return value:
+/// true - Emitted one or more registers.
+/// false - Emitted no registers.
+///
+bool Printer::printImplUsesAfter(const TargetInstrDescriptor &Desc,
+ const bool Comma = true) {
const MRegisterInfo &RI = *TM.getRegisterInfo();
if (Desc.TSFlags & X86II::PrintImplUsesAfter) {
- for (const unsigned *p = Desc.ImplicitUses; *p; ++p) {
+ bool emitted = false;
+ const unsigned *p = Desc.ImplicitUses;
+ if (*p) {
+ O << (Comma ? ", %" : "%") << RI.get (*p).Name;
+ emitted = true;
+ ++p;
+ }
+ while (*p) {
// Bug Workaround: See note in Printer::doInitialization about %.
O << ", %" << RI.get(*p).Name;
+ ++p;
}
+ return emitted;
}
+ return false;
+}
+
+/// printImplDefsAfter - Emit the implicit-definition registers for the
+/// instruction described by DESC, if its PrintImplDefsAfter flag is set.
+///
+/// Inputs:
+/// Comma - List of registers will need a leading comma.
+/// Desc - Description of the Instruction
+///
+/// Return value:
+/// true - Emitted one or more registers.
+/// false - Emitted no registers.
+///
+bool Printer::printImplDefsAfter(const TargetInstrDescriptor &Desc,
+ const bool Comma = true) {
+ const MRegisterInfo &RI = *TM.getRegisterInfo();
+ if (Desc.TSFlags & X86II::PrintImplDefsAfter) {
+ bool emitted = false;
+ const unsigned *p = Desc.ImplicitDefs;
+ if (*p) {
+ O << (Comma ? ", %" : "%") << RI.get (*p).Name;
+ emitted = true;
+ ++p;
+ }
+ while (*p) {
+ // Bug Workaround: See note in Printer::doInitialization about %.
+ O << ", %" << RI.get(*p).Name;
+ ++p;
+ }
+ return emitted;
+ }
+ return false;
}
/// printMachineInstruction -- Print out a single X86 LLVM instruction
@@ -575,33 +627,36 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
printOp(MI->getOperand(0));
O << " = phi ";
for (unsigned i = 1, e = MI->getNumOperands(); i != e; i+=2) {
- if (i != 1) O << ", ";
- O << "[";
- printOp(MI->getOperand(i));
- O << ", ";
- printOp(MI->getOperand(i+1));
- O << "]";
+ if (i != 1) O << ", ";
+ O << "[";
+ printOp(MI->getOperand(i));
+ O << ", ";
+ printOp(MI->getOperand(i+1));
+ O << "]";
}
} else {
unsigned i = 0;
if (MI->getNumOperands() && MI->getOperand(0).isDef()) {
- printOp(MI->getOperand(0));
- O << " = ";
- ++i;
+ printOp(MI->getOperand(0));
+ O << " = ";
+ ++i;
}
O << TII.getName(MI->getOpcode());
for (unsigned e = MI->getNumOperands(); i != e; ++i) {
- O << " ";
- if (MI->getOperand(i).isDef()) O << "*";
- printOp(MI->getOperand(i));
- if (MI->getOperand(i).isDef()) O << "*";
+ O << " ";
+ if (MI->getOperand(i).isDef()) O << "*";
+ printOp(MI->getOperand(i));
+ if (MI->getOperand(i).isDef()) O << "*";
}
}
O << "\n";
return;
case X86II::RawFrm:
+ {
+ bool LeadingComma = false;
+
// The accepted forms of Raw instructions are:
// 1. nop - No operand required
// 2. jmp foo - PC relative displacement operand
@@ -617,9 +672,13 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
if (MI->getNumOperands() == 1) {
printOp(MI->getOperand(0), true); // Don't print "OFFSET"...
+ LeadingComma = true;
}
+ LeadingComma = printImplDefsAfter(Desc, LeadingComma) || LeadingComma;
+ printImplUsesAfter(Desc, LeadingComma);
O << "\n";
return;
+ }
case X86II::AddRegFrm: {
// There are currently two forms of acceptable AddRegFrm instructions.
diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td
index 5584dd0d19..3cb54b6dc9 100644
--- a/lib/Target/X86/X86.td
+++ b/lib/Target/X86/X86.td
@@ -33,12 +33,26 @@ def X86InstrInfo : InstrInfo {
// Define how we want to layout our TargetSpecific information field... This
// should be kept up-to-date with the fields in the X86InstrInfo.h file.
- let TSFlagsFields = ["FormBits" , "hasOpSizePrefix" , "Prefix", "MemTypeBits",
- "ImmTypeBits", "FPFormBits", "printImplicitUsesAfter",
- "printImplicitUsesBefore", "Opcode"];
- let TSFlagsShifts = [0, 5, 6, 10, 13,
- 15, 18, 19,
- 20];
+ let TSFlagsFields = ["FormBits",
+ "hasOpSizePrefix",
+ "Prefix",
+ "MemTypeBits",
+ "ImmTypeBits",
+ "FPFormBits",
+ "printImplicitUsesAfter",
+ "printImplicitUsesBefore",
+ "printImplicitDefsAfter",
+ "Opcode"];
+ let TSFlagsShifts = [0,
+ 5,
+ 6,
+ 10,
+ 13,
+ 15,
+ 18,
+ 19,
+ 20,
+ 21];
}
def X86 : Target {
diff --git a/lib/Target/X86/X86AsmPrinter.cpp b/lib/Target/X86/X86AsmPrinter.cpp
index 73971bbe7f..e2f06846d9 100644
--- a/lib/Target/X86/X86AsmPrinter.cpp
+++ b/lib/Target/X86/X86AsmPrinter.cpp
@@ -105,7 +105,8 @@ namespace {
}
void printImplUsesBefore(const TargetInstrDescriptor &Desc);
- void printImplUsesAfter(const TargetInstrDescriptor &Desc);
+ bool printImplUsesAfter(const TargetInstrDescriptor &Desc, const bool LC);
+ bool printImplDefsAfter(const TargetInstrDescriptor &Desc, const bool LC);
void printMachineInstruction(const MachineInstr *MI);
void printOp(const MachineOperand &MO,
bool elideOffsetKeyword = false);
@@ -546,14 +547,65 @@ void Printer::printImplUsesBefore(const TargetInstrDescriptor &Desc) {
/// printImplUsesAfter - Emit the implicit-use registers for the instruction
/// described by DESC, if its PrintImplUsesAfter flag is set.
///
-void Printer::printImplUsesAfter(const TargetInstrDescriptor &Desc) {
+/// Inputs:
+/// Comma - List of registers will need a leading comma.
+/// Desc - Description of the Instruction.
+///
+/// Return value:
+/// true - Emitted one or more registers.
+/// false - Emitted no registers.
+///
+bool Printer::printImplUsesAfter(const TargetInstrDescriptor &Desc,
+ const bool Comma = true) {
const MRegisterInfo &RI = *TM.getRegisterInfo();
if (Desc.TSFlags & X86II::PrintImplUsesAfter) {
- for (const unsigned *p = Desc.ImplicitUses; *p; ++p) {
+ bool emitted = false;
+ const unsigned *p = Desc.ImplicitUses;
+ if (*p) {
+ O << (Comma ? ", %" : "%") << RI.get (*p).Name;
+ emitted = true;
+ ++p;
+ }
+ while (*p) {
// Bug Workaround: See note in Printer::doInitialization about %.
O << ", %" << RI.get(*p).Name;
+ ++p;
}
+ return emitted;
}
+ return false;
+}
+
+/// printImplDefsAfter - Emit the implicit-definition registers for the
+/// instruction described by DESC, if its PrintImplDefsAfter flag is set.
+///
+/// Inputs:
+/// Comma - List of registers will need a leading comma.
+/// Desc - Description of the Instruction
+///
+/// Return value:
+/// true - Emitted one or more registers.
+/// false - Emitted no registers.
+///
+bool Printer::printImplDefsAfter(const TargetInstrDescriptor &Desc,
+ const bool Comma = true) {
+ const MRegisterInfo &RI = *TM.getRegisterInfo();
+ if (Desc.TSFlags & X86II::PrintImplDefsAfter) {
+ bool emitted = false;
+ const unsigned *p = Desc.ImplicitDefs;
+ if (*p) {
+ O << (Comma ? ", %" : "%") << RI.get (*p).Name;
+ emitted = true;
+ ++p;
+ }
+ while (*p) {
+ // Bug Workaround: See note in Printer::doInitialization about %.
+ O << ", %" << RI.get(*p).Name;
+ ++p;
+ }
+ return emitted;
+ }
+ return false;
}
/// printMachineInstruction -- Print out a single X86 LLVM instruction
@@ -575,33 +627,36 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
printOp(MI->getOperand(0));
O << " = phi ";
for (unsigned i = 1, e = MI->getNumOperands(); i != e; i+=2) {
- if (i != 1) O << ", ";
- O << "[";
- printOp(MI->getOperand(i));
- O << ", ";
- printOp(MI->getOperand(i+1));
- O << "]";
+ if (i != 1) O << ", ";
+ O << "[";
+ printOp(MI->getOperand(i));
+ O << ", ";
+ printOp(MI->getOperand(i+1));
+ O << "]";
}
} else {
unsigned i = 0;
if (MI->getNumOperands() && MI->getOperand(0).isDef()) {
- printOp(MI->getOperand(0));
- O << " = ";
- ++i;
+ printOp(MI->getOperand(0));
+ O << " = ";
+ ++i;
}
O << TII.getName(MI->getOpcode());
for (unsigned e = MI->getNumOperands(); i != e; ++i) {
- O << " ";
- if (MI->getOperand(i).isDef()) O << "*";
- printOp(MI->getOperand(i));
- if (MI->getOperand(i).isDef()) O << "*";
+ O << " ";
+ if (MI->getOperand(i).isDef()) O << "*";
+ printOp(MI->getOperand(i));
+ if (MI->getOperand(i).isDef()) O << "*";
}
}
O << "\n";
return;
case X86II::RawFrm:
+ {
+ bool LeadingComma = false;
+
// The accepted forms of Raw instructions are:
// 1. nop - No operand required
// 2. jmp foo - PC relative displacement operand
@@ -617,9 +672,13 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
if (MI->getNumOperands() == 1) {
printOp(MI->getOperand(0), true); // Don't print "OFFSET"...
+ LeadingComma = true;
}
+ LeadingComma = printImplDefsAfter(Desc, LeadingComma) || LeadingComma;
+ printImplUsesAfter(Desc, LeadingComma);
O << "\n";
return;
+ }
case X86II::AddRegFrm: {
// There are currently two forms of acceptable AddRegFrm instructions.
diff --git a/lib/Target/X86/X86ISelSimple.cpp b/lib/Target/X86/X86ISelSimple.cpp
index 4a04b2910f..4988a0dc4c 100644
--- a/lib/Target/X86/X86ISelSimple.cpp
+++ b/lib/Target/X86/X86ISelSimple.cpp
@@ -1502,6 +1502,8 @@ void ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) {
case Intrinsic::frameaddress:
case Intrinsic::memcpy:
case Intrinsic::memset:
+ case Intrinsic::readport:
+ case Intrinsic::writeport:
// We directly implement these intrinsics
break;
default:
@@ -1663,6 +1665,65 @@ void ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) {
return;
}
+ case Intrinsic::readport:
+ //
+ // First, determine that the size of the operand falls within the
+ // acceptable range for this architecture.
+ //
+ assert (((CI.getOperand(1)->getType()->getPrimitiveSize()) == 2) &&
+ "llvm.readport operand size is not a 16 bit value!");
+
+ //
+ // Now, move the I/O port address into the DX register and use the IN
+ // instruction to get the input data.
+ //
+ BuildMI(BB, X86::MOV16rr, 1, X86::DX).addReg(getReg(CI.getOperand(1)));
+ switch (CI.getCalledFunction()->getReturnType()->getPrimitiveSize()) {
+ case 1:
+ BuildMI(BB, X86::IN8, 1);
+ break;
+ case 2:
+ BuildMI(BB, X86::IN16, 1);
+ break;
+ case 4:
+ BuildMI(BB, X86::IN32, 1);
+ break;
+ default:
+ assert (0 && "Cannot do input on this data type");
+ }
+ return;
+
+ case Intrinsic::writeport:
+ //
+ // First, determine that the size of the operand falls within the
+ // acceptable range for this architecture.
+ //
+ assert (((CI.getOperand(1)->getType()->getPrimitiveSize()) == 2) &&
+ "llvm.readport operand size is not a 16 bit value!");
+
+ //
+ // Now, move the I/O port address into the DX register and the value to
+ // write into the AL/AX/EAX register.
+ //
+ BuildMI(BB, X86::MOV16rr, 1, X86::DX).addReg(getReg(CI.getOperand(1)));
+ switch (CI.getOperand(2)->getType()->getPrimitiveSize()) {
+ case 1:
+ BuildMI(BB, X86::MOV8rr, 1, X86::AL).addReg(getReg(CI.getOperand(2)));
+ BuildMI(BB, X86::OUT8, 1);
+ break;
+ case 2:
+ BuildMI(BB, X86::MOV16rr, 1, X86::AX).addReg(getReg(CI.getOperand(2)));
+ BuildMI(BB, X86::OUT16, 1);
+ break;
+ case 4:
+ BuildMI(BB, X86::MOV32rr, 1, X86::EAX).addReg(getReg(CI.getOperand(2)));
+ BuildMI(BB, X86::OUT32, 1);
+ break;
+ default:
+ assert (0 && "Cannot do input on this data type");
+ }
+ return;
+
default: assert(0 && "Error: unknown intrinsics should have been lowered!");
}
}
diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h
index 5570062355..90e8d524ef 100644
--- a/lib/Target/X86/X86InstrInfo.h
+++ b/lib/Target/X86/X86InstrInfo.h
@@ -121,7 +121,7 @@ namespace X86II {
Mem128 = 6 << MemShift,
//===------------------------------------------------------------------===//
- // This tow-bit field describes the size of an immediate operand. Zero is
+ // This two-bit field describes the size of an immediate operand. Zero is
// unused so that we can tell if we forgot to set a value.
ImmShift = 13,
ImmMask = 7 << ImmShift,
@@ -169,9 +169,13 @@ namespace X86II {
// before the normal operands.
PrintImplUsesBefore = 1 << 19,
- OpcodeShift = 20,
+ // PrintImplDefsAfter - Print out implicit defs in the assembly output
+ // after the normal operands.
+ PrintImplDefsAfter = 1 << 20,
+
+ OpcodeShift = 21,
OpcodeMask = 0xFF << OpcodeShift,
- // Bits 25 -> 31 are unused
+ // Bits 26 -> 31 are unused
};
}
diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td
index d44e0c61ee..1ddaaabd82 100644
--- a/lib/Target/X86/X86InstrInfo.td
+++ b/lib/Target/X86/X86InstrInfo.td
@@ -82,10 +82,20 @@ class X86Inst<string nam, bits<8> opcod, Format f, MemType m, ImmType i> : Instr
ImmType ImmT = i;
bits<2> ImmTypeBits = ImmT.Value;
+ //
// Attributes specific to X86 instructions...
+ //
bit hasOpSizePrefix = 0; // Does this inst have a 0x66 prefix?
- bit printImplicitUsesBefore = 0; // Should we print implicit uses before this inst?
- bit printImplicitUsesAfter = 0; // Should we print implicit uses after this inst?
+
+ // Flag whether implicit register usage is printed before/after the
+ // instruction
+ bit printImplicitUsesBefore = 0;
+ bit printImplicitUsesAfter = 0;
+
+ // Flag whether implicit register definitions are printed before/after the
+ // instruction
+ bit printImplicitDefsBefore = 0;
+ bit printImplicitDefsAfter = 0;
bits<4> Prefix = 0; // Which prefix byte does this inst have?
FPFormat FPForm; // What flavor of FP instruction is this?
@@ -141,6 +151,8 @@ class Im32i8<string n, bits<8> o, Format f> : X86Inst<n, o, f, Mem32, Imm8>;
// Helper for shift instructions
class UsesCL { list<Register> Uses = [CL]; bit printImplicitUsesAfter = 1; }
+class PrintImpUsesAfter {bit printImplicitUsesAfter = 1;}
+class PrintImpDefsAfter {bit printImplicitDefsAfter = 1;}
//===----------------------------------------------------------------------===//
// Instruction list...
@@ -234,6 +246,17 @@ def REP_STOSD : I<"rep stosd", 0xAB, RawFrm>, REP,
Imp<[EAX,ECX,EDI], [ECX,EDI]>;
//===----------------------------------------------------------------------===//
+// Input/Output Instructions...
+//
+def IN8 : I<"in", 0xEC, RawFrm>, Imp<[DX],[AL]>, PrintImpUsesAfter, PrintImpDefsAfter; // in AL = I/O address DX
+def IN16 : I<"in", 0xED, RawFrm>, Imp<[DX],[AX]>, PrintImpUsesAfter, PrintImpDefsAfter; // in AX = I/O address DX
+def IN32 : I<"in", 0xED, RawFrm>, Imp<[DX],[EAX]>, PrintImpUsesAfter, PrintImpDefsAfter; // in EAX = I/O address DX
+
+def OUT8 : I<"out", 0xEE, RawFrm>, Imp<[DX, AL], []>, PrintImpUsesAfter;
+def OUT16 : I<"out", 0xEF, RawFrm>, Imp<[DX, AX], []>, PrintImpUsesAfter;
+def OUT32 : I<"out", 0xEF, RawFrm>, Imp<[DX, EAX], []>, PrintImpUsesAfter;
+
+//===----------------------------------------------------------------------===//
// Move Instructions...
//
def MOV8rr : I <"mov", 0x88, MRMDestReg>, Pattern<(set R8 , R8 )>;