[llvm-commits] CVS: llvm/lib/Target/X86/InstSelectSimple.cpp Printer.cpp X86InstrInfo.def X86TargetMachine.cpp X86TargetMachine.h
John Criswell
criswell at choi.cs.uiuc.edu
Thu Jun 26 16:42:15 PDT 2003
Changes in directory llvm/lib/Target/X86:
InstSelectSimple.cpp updated: 1.106 -> 1.106.2.1
Printer.cpp updated: 1.35 -> 1.35.2.1
X86InstrInfo.def updated: 1.57 -> 1.57.2.1
X86TargetMachine.cpp updated: 1.17 -> 1.17.2.1
X86TargetMachine.h updated: 1.9 -> 1.9.2.1
---
Log message:
Merged with mainline on Thursday, June 26, 2003.
---
Diffs of the changes:
Index: llvm/lib/Target/X86/InstSelectSimple.cpp
diff -u llvm/lib/Target/X86/InstSelectSimple.cpp:1.106 llvm/lib/Target/X86/InstSelectSimple.cpp:1.106.2.1
--- llvm/lib/Target/X86/InstSelectSimple.cpp:1.106 Thu Jun 5 14:30:30 2003
+++ llvm/lib/Target/X86/InstSelectSimple.cpp Thu Jun 26 16:35:24 2003
@@ -1069,8 +1069,6 @@
/// registers op0Reg and op1Reg, and put the result in DestReg. The type of the
/// result should be given as DestTy.
///
-/// FIXME: doMultiply should use one of the two address IMUL instructions!
-///
void ISel::doMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator &MBBI,
unsigned DestReg, const Type *DestTy,
unsigned op0Reg, unsigned op1Reg) {
@@ -1079,28 +1077,20 @@
case cFP: // Floating point multiply
BMI(BB, MBBI, X86::FpMUL, 2, DestReg).addReg(op0Reg).addReg(op1Reg);
return;
+ case cInt:
+ case cShort:
+ BMI(BB, MBBI, Class == cInt ? X86::IMULr32 : X86::IMULr16, 2, DestReg)
+ .addReg(op0Reg).addReg(op1Reg);
+ return;
+ case cByte:
+ // Must use the MUL instruction, which forces use of AL...
+ BMI(MBB, MBBI, X86::MOVrr8, 1, X86::AL).addReg(op0Reg);
+ BMI(MBB, MBBI, X86::MULr8, 1).addReg(op1Reg);
+ BMI(MBB, MBBI, X86::MOVrr8, 1, DestReg).addReg(X86::AL);
+ return;
default:
case cLong: assert(0 && "doMultiply cannot operate on LONG values!");
- case cByte:
- case cShort:
- case cInt: // Small integerals, handled below...
- break;
}
-
- static const unsigned Regs[] ={ X86::AL , X86::AX , X86::EAX };
- static const unsigned MulOpcode[]={ X86::MULr8 , X86::MULr16 , X86::MULr32 };
- static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 };
- unsigned Reg = Regs[Class];
-
- // Emit a MOV to put the first operand into the appropriately-sized
- // subreg of EAX.
- BMI(MBB, MBBI, MovOpcode[Class], 1, Reg).addReg(op0Reg);
-
- // Emit the appropriate multiply instruction.
- BMI(MBB, MBBI, MulOpcode[Class], 1).addReg(op1Reg);
-
- // Emit another MOV to put the result into the destination register.
- BMI(MBB, MBBI, MovOpcode[Class], 1, DestReg).addReg(Reg);
}
/// visitMul - Multiplies are not simple binary operators because they must deal
@@ -1126,16 +1116,16 @@
BuildMI(BB, X86::MOVrr32, 1, OverflowReg).addReg(X86::EDX); // AL*BL >> 32
MachineBasicBlock::iterator MBBI = BB->end();
- unsigned AHBLReg = makeAnotherReg(Type::UIntTy);
- doMultiply(BB, MBBI, AHBLReg, Type::UIntTy, Op0Reg+1, Op1Reg); // AH*BL
+ unsigned AHBLReg = makeAnotherReg(Type::UIntTy); // AH*BL
+ BMI(BB, MBBI, X86::IMULr32, 2, AHBLReg).addReg(Op0Reg+1).addReg(Op1Reg);
unsigned AHBLplusOverflowReg = makeAnotherReg(Type::UIntTy);
BuildMI(BB, X86::ADDrr32, 2, // AH*BL+(AL*BL >> 32)
AHBLplusOverflowReg).addReg(AHBLReg).addReg(OverflowReg);
MBBI = BB->end();
- unsigned ALBHReg = makeAnotherReg(Type::UIntTy);
- doMultiply(BB, MBBI, ALBHReg, Type::UIntTy, Op0Reg, Op1Reg+1); // AL*BH
+ unsigned ALBHReg = makeAnotherReg(Type::UIntTy); // AL*BH
+ BMI(BB, MBBI, X86::IMULr32, 2, ALBHReg).addReg(Op0Reg).addReg(Op1Reg+1);
BuildMI(BB, X86::ADDrr32, 2, // AL*BH + AH*BL + (AL*BL >> 32)
DestReg+1).addReg(AHBLplusOverflowReg).addReg(ALBHReg);
@@ -1189,7 +1179,7 @@
static const unsigned Regs[] ={ X86::AL , X86::AX , X86::EAX };
static const unsigned MovOpcode[]={ X86::MOVrr8, X86::MOVrr16, X86::MOVrr32 };
- static const unsigned ExtOpcode[]={ X86::CBW , X86::CWD , X86::CDQ };
+ static const unsigned SarOpcode[]={ X86::SARir8, X86::SARir16, X86::SARir32 };
static const unsigned ClrOpcode[]={ X86::XORrr8, X86::XORrr16, X86::XORrr32 };
static const unsigned ExtRegs[] ={ X86::AH , X86::DX , X86::EDX };
@@ -1207,7 +1197,9 @@
if (isSigned) {
// Emit a sign extension instruction...
- BuildMI(BB, ExtOpcode[Class], 0);
+ unsigned ShiftResult = makeAnotherReg(I.getType());
+ BuildMI(BB, SarOpcode[Class], 2, ShiftResult).addReg(Op0Reg).addZImm(31);
+ BuildMI(BB, MovOpcode[Class], 1, ExtReg).addReg(ShiftResult);
} else {
// If unsigned, emit a zeroing instruction... (reg = xor reg, reg)
BuildMI(BB, ClrOpcode[Class], 2, ExtReg).addReg(ExtReg).addReg(ExtReg);
@@ -1580,9 +1572,26 @@
/// visitCastInst - Here we have various kinds of copying with or without
/// sign extension going on.
void ISel::visitCastInst(CastInst &CI) {
+ Value *Op = CI.getOperand(0);
+ // If this is a cast from a 32-bit integer to a Long type, and the only uses
+ // of the case are GEP instructions, then the cast does not need to be
+ // generated explicitly, it will be folded into the GEP.
+ if (CI.getType() == Type::LongTy &&
+ (Op->getType() == Type::IntTy || Op->getType() == Type::UIntTy)) {
+ bool AllUsesAreGEPs = true;
+ for (Value::use_iterator I = CI.use_begin(), E = CI.use_end(); I != E; ++I)
+ if (!isa<GetElementPtrInst>(*I)) {
+ AllUsesAreGEPs = false;
+ break;
+ }
+
+ // No need to codegen this cast if all users are getelementptr instrs...
+ if (AllUsesAreGEPs) return;
+ }
+
unsigned DestReg = getReg(CI);
MachineBasicBlock::iterator MI = BB->end();
- emitCastOperation(BB, MI, CI.getOperand(0), CI.getType(), DestReg);
+ emitCastOperation(BB, MI, Op, CI.getType(), DestReg);
}
/// emitCastOperation - Common code shared between visitCastInst and
@@ -1936,6 +1945,13 @@
// indices, we may not know its actual value at code-generation
// time.
assert(idx->getType() == Type::LongTy && "Bad GEP array index!");
+
+ // Most GEP instructions use a [cast (int/uint) to LongTy] as their
+ // operand on X86. Handle this case directly now...
+ if (CastInst *CI = dyn_cast<CastInst>(idx))
+ if (CI->getOperand(0)->getType() == Type::IntTy ||
+ CI->getOperand(0)->getType() == Type::UIntTy)
+ idx = CI->getOperand(0);
// We want to add BaseReg to(idxReg * sizeof ElementType). First, we
// must find the size of the pointed-to type (Not coincidentally, the next
Index: llvm/lib/Target/X86/Printer.cpp
diff -u llvm/lib/Target/X86/Printer.cpp:1.35 llvm/lib/Target/X86/Printer.cpp:1.35.2.1
--- llvm/lib/Target/X86/Printer.cpp:1.35 Mon May 26 19:03:17 2003
+++ llvm/lib/Target/X86/Printer.cpp Thu Jun 26 16:35:24 2003
@@ -14,20 +14,41 @@
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "Support/Statistic.h"
+#include "Support/hash_map"
+#include "llvm/Type.h"
+#include "llvm/Constants.h"
+#include "llvm/Assembly/Writer.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/SlotCalculator.h"
+#include "Support/StringExtras.h"
+#include "llvm/Module.h"
namespace {
+
+
+ std::set<const Value*> MangledGlobals;
struct Printer : public MachineFunctionPass {
+
std::ostream &O;
unsigned ConstIdx;
Printer(std::ostream &o) : O(o), ConstIdx(0) {}
+ const TargetData *TD;
virtual const char *getPassName() const {
return "X86 Assembly Printer";
}
- void printConstantPool(MachineConstantPool *MCP, const TargetData &TD);
- bool runOnMachineFunction(MachineFunction &F);
+ void printConstantPool(MachineConstantPool *MCP);
+ bool runOnMachineFunction(MachineFunction &F);
+ std::string ConstantExprToString(const ConstantExpr* CE);
+ std::string valToExprString(const Value* V);
+ bool doInitialization(Module &M);
+ bool doFinalization(Module &M);
+ void PrintZeroBytesToPad(int numBytes);
+ void printConstantValueOnly(const Constant* CV, int numPadBytesAfter = 0);
+ void printSingleConstantValue(const Constant* CV);
};
+ std::map<const Value *, unsigned> NumberForBB;
}
/// createX86CodePrinterPass - Print out the specified machine code function to
@@ -38,44 +59,377 @@
return new Printer(O);
}
+// We dont want identifier names with ., space, - in them.
+// So we replace them with _
+static std::string makeNameProper(std::string x) {
+ std::string tmp;
+ for (std::string::iterator sI = x.begin(), sEnd = x.end(); sI != sEnd; sI++)
+ switch (*sI) {
+ case '.': tmp += "d_"; break;
+ case ' ': tmp += "s_"; break;
+ case '-': tmp += "D_"; break;
+ default: tmp += *sI;
+ }
+
+ return tmp;
+}
+
+std::string getValueName(const Value *V) {
+ if (V->hasName()) { // Print out the label if it exists...
+
+ // Name mangling occurs as follows:
+ // - If V is not a global, mangling always occurs.
+ // - Otherwise, mangling occurs when any of the following are true:
+ // 1) V has internal linkage
+ // 2) V's name would collide if it is not mangled.
+ //
+
+ if(const GlobalValue* gv = dyn_cast<GlobalValue>(V)) {
+ if(!gv->hasInternalLinkage() && !MangledGlobals.count(gv)) {
+ // No internal linkage, name will not collide -> no mangling.
+ return makeNameProper(gv->getName());
+ }
+ }
+
+ // Non-global, or global with internal linkage / colliding name -> mangle.
+ return "l" + utostr(V->getType()->getUniqueID()) + "_" +
+ makeNameProper(V->getName());
+ }
+
+ static int Count = 0;
+ Count++;
+ return "ltmp_" + itostr(Count) + "_" + utostr(V->getType()->getUniqueID());
+}
+
+
+// valToExprString - Helper function for ConstantExprToString().
+// Appends result to argument string S.
+//
+std::string Printer::valToExprString(const Value* V) {
+ std::string S;
+ bool failed = false;
+ if (const Constant* CV = dyn_cast<Constant>(V)) { // symbolic or known
+ if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV))
+ S += std::string(CB == ConstantBool::True ? "1" : "0");
+ else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
+ S += itostr(CI->getValue());
+ else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
+ S += utostr(CI->getValue());
+ else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
+ S += ftostr(CFP->getValue());
+ else if (isa<ConstantPointerNull>(CV))
+ S += "0";
+ else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(CV))
+ S += valToExprString(CPR->getValue());
+ else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV))
+ S += ConstantExprToString(CE);
+ else
+ failed = true;
+ } else if (const GlobalValue* GV = dyn_cast<GlobalValue>(V)) {
+ S += getValueName(GV);
+ }
+ else
+ failed = true;
+
+ if (failed) {
+ assert(0 && "Cannot convert value to string");
+ S += "<illegal-value>";
+ }
+ return S;
+}
+
+// ConstantExprToString() - Convert a ConstantExpr to an asm expression
+// and return this as a string.
+std::string Printer::ConstantExprToString(const ConstantExpr* CE) {
+ std::string S;
+ switch(CE->getOpcode()) {
+ case Instruction::GetElementPtr:
+ { // generate a symbolic expression for the byte address
+ const Value* ptrVal = CE->getOperand(0);
+ std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
+ S += "(" + valToExprString(ptrVal) + ") + ("
+ + utostr(TD->getIndexedOffset(ptrVal->getType(),idxVec)) + ")";
+ break;
+ }
+
+ case Instruction::Cast:
+ // Support only non-converting casts for now, i.e., a no-op.
+ // This assertion is not a complete check.
+ assert(TD->getTypeSize(CE->getType()) ==
+ TD->getTypeSize(CE->getOperand(0)->getType()));
+ S += "(" + valToExprString(CE->getOperand(0)) + ")";
+ break;
+
+ case Instruction::Add:
+ S += "(" + valToExprString(CE->getOperand(0)) + ") + ("
+ + valToExprString(CE->getOperand(1)) + ")";
+ break;
+
+ default:
+ assert(0 && "Unsupported operator in ConstantExprToString()");
+ break;
+ }
+
+ return S;
+}
+
+// Print a single constant value.
+void
+Printer::printSingleConstantValue(const Constant* CV)
+{
+ assert(CV->getType() != Type::VoidTy &&
+ CV->getType() != Type::TypeTy &&
+ CV->getType() != Type::LabelTy &&
+ "Unexpected type for Constant");
+
+ assert((!isa<ConstantArray>(CV) && ! isa<ConstantStruct>(CV))
+ && "Aggregate types should be handled outside this function");
+
+ const Type *type = CV->getType();
+ O << "\t";
+ switch(type->getPrimitiveID())
+ {
+ case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
+ O << ".byte";
+ break;
+ case Type::UShortTyID: case Type::ShortTyID:
+ O << ".word";
+ break;
+ case Type::UIntTyID: case Type::IntTyID: case Type::PointerTyID:
+ O << ".long";
+ break;
+ case Type::ULongTyID: case Type::LongTyID:
+ O << ".quad";
+ break;
+ case Type::FloatTyID:
+ O << ".long";
+ break;
+ case Type::DoubleTyID:
+ O << ".quad";
+ break;
+ case Type::ArrayTyID:
+ if ((cast<ArrayType>(type)->getElementType() == Type::UByteTy) ||
+ (cast<ArrayType>(type)->getElementType() == Type::SByteTy))
+ O << ".string";
+ else
+ assert (0 && "Can't handle printing this type of array");
+ break;
+ default:
+ assert (0 && "Can't handle printing this type of thing");
+ break;
+ }
+ O << "\t";
+
+ if (type->isPrimitiveType())
+ {
+ if (type->isFloatingPoint()) {
+ // FP Constants are printed as integer constants to avoid losing
+ // precision...
+ double Val = cast<ConstantFP>(CV)->getValue();
+ if (type == Type::FloatTy) {
+ float FVal = (float)Val;
+ char *ProxyPtr = (char*)&FVal; // Abide by C TBAA rules
+ O << *(unsigned int*)ProxyPtr;
+ } else if (type == Type::DoubleTy) {
+ char *ProxyPtr = (char*)&Val; // Abide by C TBAA rules
+ O << *(uint64_t*)ProxyPtr;
+ } else {
+ assert(0 && "Unknown floating point type!");
+ }
+
+ O << "\t# " << type->getDescription() << " value: " << Val << "\n";
+ } else {
+ WriteAsOperand(O, CV, false, false) << "\n";
+ }
+ }
+ else if (const ConstantPointerRef* CPR = dyn_cast<ConstantPointerRef>(CV))
+ {
+ // This is a constant address for a global variable or method.
+ // Use the name of the variable or method as the address value.
+ O << getValueName(CPR->getValue()) << "\n";
+ }
+ else if (isa<ConstantPointerNull>(CV))
+ {
+ // Null pointer value
+ O << "0\n";
+ }
+ else if (const ConstantExpr* CE = dyn_cast<ConstantExpr>(CV))
+ {
+ // Constant expression built from operators, constants, and
+ // symbolic addrs
+ O << ConstantExprToString(CE) << "\n";
+ }
+ else
+ {
+ assert(0 && "Unknown elementary type for constant");
+ }
+}
+
+// Can we treat the specified array as a string? Only if it is an array of
+// ubytes or non-negative sbytes.
+//
+static bool isStringCompatible(const ConstantArray *CVA) {
+ const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType();
+ if (ETy == Type::UByteTy) return true;
+ if (ETy != Type::SByteTy) return false;
+
+ for (unsigned i = 0; i < CVA->getNumOperands(); ++i)
+ if (cast<ConstantSInt>(CVA->getOperand(i))->getValue() < 0)
+ return false;
+
+ return true;
+}
+
+// toOctal - Convert the low order bits of X into an octal letter
+static inline char toOctal(int X) {
+ return (X&7)+'0';
+}
+
+// getAsCString - Return the specified array as a C compatible string, only if
+// the predicate isStringCompatible is true.
+//
+static std::string getAsCString(const ConstantArray *CVA) {
+ assert(isStringCompatible(CVA) && "Array is not string compatible!");
+
+ std::string Result;
+ const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType();
+ Result = "\"";
+ for (unsigned i = 0; i < CVA->getNumOperands(); ++i) {
+ unsigned char C = (ETy == Type::SByteTy) ?
+ (unsigned char)cast<ConstantSInt>(CVA->getOperand(i))->getValue() :
+ (unsigned char)cast<ConstantUInt>(CVA->getOperand(i))->getValue();
+
+ if (C == '"') {
+ Result += "\\\"";
+ } else if (C == '\\') {
+ Result += "\\\\";
+ } else if (isprint(C)) {
+ Result += C;
+ } else {
+ switch(C) {
+ case '\a': Result += "\\a"; break;
+ case '\b': Result += "\\b"; break;
+ case '\f': Result += "\\f"; break;
+ case '\n': Result += "\\n"; break;
+ case '\r': Result += "\\r"; break;
+ case '\t': Result += "\\t"; break;
+ case '\v': Result += "\\v"; break;
+ default:
+ Result += '\\';
+ Result += toOctal(C >> 6);
+ Result += toOctal(C >> 3);
+ Result += toOctal(C >> 0);
+ break;
+ }
+ }
+ }
+ Result += "\"";
+ return Result;
+}
+
+// Print a constant value or values (it may be an aggregate).
+// Uses printSingleConstantValue() to print each individual value.
+void
+Printer::printConstantValueOnly(const Constant* CV,
+ int numPadBytesAfter /* = 0 */)
+{
+ const ConstantArray *CVA = dyn_cast<ConstantArray>(CV);
+
+ if (CVA && isStringCompatible(CVA))
+ { // print the string alone and return
+ O << "\t" << ".string" << "\t" << getAsCString(CVA) << "\n";
+ }
+ else if (CVA)
+ { // Not a string. Print the values in successive locations
+ const std::vector<Use> &constValues = CVA->getValues();
+ for (unsigned i=0; i < constValues.size(); i++)
+ printConstantValueOnly(cast<Constant>(constValues[i].get()));
+ }
+ else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
+ { // Print the fields in successive locations. Pad to align if needed!
+ const StructLayout *cvsLayout =
+ TD->getStructLayout(CVS->getType());
+ const std::vector<Use>& constValues = CVS->getValues();
+ unsigned sizeSoFar = 0;
+ for (unsigned i=0, N = constValues.size(); i < N; i++)
+ {
+ const Constant* field = cast<Constant>(constValues[i].get());
+
+ // Check if padding is needed and insert one or more 0s.
+ unsigned fieldSize = TD->getTypeSize(field->getType());
+ int padSize = ((i == N-1? cvsLayout->StructSize
+ : cvsLayout->MemberOffsets[i+1])
+ - cvsLayout->MemberOffsets[i]) - fieldSize;
+ sizeSoFar += (fieldSize + padSize);
+
+ // Now print the actual field value
+ printConstantValueOnly(field, padSize);
+ }
+ assert(sizeSoFar == cvsLayout->StructSize &&
+ "Layout of constant struct may be incorrect!");
+ }
+ else
+ printSingleConstantValue(CV);
+
+ if (numPadBytesAfter) {
+ unsigned numBytes = numPadBytesAfter;
+ for ( ; numBytes >= 8; numBytes -= 8)
+ printSingleConstantValue(Constant::getNullValue(Type::ULongTy));
+ if (numBytes >= 4)
+ {
+ printSingleConstantValue(Constant::getNullValue(Type::UIntTy));
+ numBytes -= 4;
+ }
+ while (numBytes--)
+ printSingleConstantValue(Constant::getNullValue(Type::UByteTy));
+ }
+}
// printConstantPool - Print out any constants which have been spilled to
// memory...
-void Printer::printConstantPool(MachineConstantPool *MCP, const TargetData &TD){
+void Printer::printConstantPool(MachineConstantPool *MCP){
const std::vector<Constant*> &CP = MCP->getConstants();
if (CP.empty()) return;
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
O << "\t.section .rodata\n";
- O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType()) << "\n";
- O << ".CPI" << i+ConstIdx << ":\t\t\t\t\t;" << *CP[i] << "\n";
- O << "\t*Constant output not implemented yet!*\n\n";
+ O << "\t.align " << (unsigned)TD->getTypeAlignment(CP[i]->getType()) << "\n";
+ O << ".CPI" << i+ConstIdx << ":\t\t\t\t\t#" << *CP[i] << "\n";
+ printConstantValueOnly (CP[i]);
}
ConstIdx += CP.size(); // Don't recycle constant pool index numbers
}
-/// runOnFunction - This uses the X86InstructionInfo::print method
+/// runOnMachineFunction - This uses the X86InstructionInfo::print method
/// to print assembly for each instruction.
bool Printer::runOnMachineFunction(MachineFunction &MF) {
static unsigned BBNumber = 0;
const TargetMachine &TM = MF.getTarget();
const TargetInstrInfo &TII = TM.getInstrInfo();
+ TD = &TM.getTargetData();
// Print out constants referenced by the function
- printConstantPool(MF.getConstantPool(), TM.getTargetData());
+ printConstantPool(MF.getConstantPool());
// Print out labels for the function.
O << "\t.text\n";
O << "\t.align 16\n";
- O << "\t.globl\t" << MF.getFunction()->getName() << "\n";
- O << "\t.type\t" << MF.getFunction()->getName() << ", @function\n";
- O << MF.getFunction()->getName() << ":\n";
+ O << "\t.globl\t" << getValueName(MF.getFunction()) << "\n";
+ O << "\t.type\t" << getValueName(MF.getFunction()) << ", @function\n";
+ O << getValueName(MF.getFunction()) << ":\n";
+
+ NumberForBB.clear();
+ for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
+ I != E; ++I) {
+ NumberForBB[I->getBasicBlock()] = BBNumber++;
+ }
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
- O << ".BB" << BBNumber++ << ":\n";
+ O << ".BB" << NumberForBB[I->getBasicBlock()] << ":\t# "
+ << I->getBasicBlock()->getName() << "\n";
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
@@ -90,20 +444,20 @@
static bool isScale(const MachineOperand &MO) {
return MO.isImmediate() &&
- (MO.getImmedValue() == 1 || MO.getImmedValue() == 2 ||
- MO.getImmedValue() == 4 || MO.getImmedValue() == 8);
+ (MO.getImmedValue() == 1 || MO.getImmedValue() == 2 ||
+ MO.getImmedValue() == 4 || MO.getImmedValue() == 8);
}
static bool isMem(const MachineInstr *MI, unsigned Op) {
if (MI->getOperand(Op).isFrameIndex()) return true;
if (MI->getOperand(Op).isConstantPoolIndex()) return true;
return Op+4 <= MI->getNumOperands() &&
- MI->getOperand(Op ).isRegister() &&isScale(MI->getOperand(Op+1)) &&
- MI->getOperand(Op+2).isRegister() &&MI->getOperand(Op+3).isImmediate();
+ MI->getOperand(Op ).isRegister() &&isScale(MI->getOperand(Op+1)) &&
+ MI->getOperand(Op+2).isRegister() &&MI->getOperand(Op+3).isImmediate();
}
static void printOp(std::ostream &O, const MachineOperand &MO,
- const MRegisterInfo &RI) {
+ const MRegisterInfo &RI, bool elideOffsetKeyword = false) {
switch (MO.getType()) {
case MachineOperand::MO_VirtualRegister:
if (Value *V = MO.getVRegValueOrNull()) {
@@ -123,29 +477,30 @@
O << (int)MO.getImmedValue();
return;
case MachineOperand::MO_PCRelativeDisp:
- O << "<" << MO.getVRegValue()->getName() << ">";
+ O << ".BB" << NumberForBB[MO.getVRegValue()] << " # PC rel: "
+ << MO.getVRegValue()->getName();
return;
case MachineOperand::MO_GlobalAddress:
- O << "<" << MO.getGlobal()->getName() << ">";
+ if (!elideOffsetKeyword) O << "OFFSET "; O << getValueName(MO.getGlobal());
return;
case MachineOperand::MO_ExternalSymbol:
- O << "<" << MO.getSymbolName() << ">";
+ O << MO.getSymbolName();
return;
default:
- O << "<unknown op ty>"; return;
+ O << "<unknown operand type>"; return;
}
}
static const std::string sizePtr(const TargetInstrDescriptor &Desc) {
switch (Desc.TSFlags & X86II::ArgMask) {
- default: assert(0 && "Unknown arg size!");
- case X86II::Arg8: return "BYTE PTR";
- case X86II::Arg16: return "WORD PTR";
- case X86II::Arg32: return "DWORD PTR";
- case X86II::Arg64: return "QWORD PTR";
- case X86II::ArgF32: return "DWORD PTR";
- case X86II::ArgF64: return "QWORD PTR";
- case X86II::ArgF80: return "XWORD PTR";
+ default: assert(0 && "Unknown arg size!");
+ case X86II::Arg8: return "BYTE PTR";
+ case X86II::Arg16: return "WORD PTR";
+ case X86II::Arg32: return "DWORD PTR";
+ case X86II::Arg64: return "QWORD PTR";
+ case X86II::ArgF32: return "DWORD PTR";
+ case X86II::ArgF64: return "QWORD PTR";
+ case X86II::ArgF80: return "XWORD PTR";
}
}
@@ -208,6 +563,10 @@
switch (Desc.TSFlags & X86II::FormMask) {
case X86II::Pseudo:
+ // Print pseudo-instructions as comments; either they should have been
+ // turned into real instructions by now, or they don't need to be
+ // seen by the assembler (e.g., IMPLICIT_USEs.)
+ O << "# ";
if (Opcode == X86::PHI) {
printOp(O, MI->getOperand(0), RI);
O << " = phi ";
@@ -256,7 +615,7 @@
O << getName(MI->getOpcode()) << " ";
if (MI->getNumOperands() == 1) {
- printOp(O, MI->getOperand(0), RI);
+ printOp(O, MI->getOperand(0), RI, true); // Don't print "OFFSET"...
}
O << "\n";
return;
@@ -409,7 +768,7 @@
MI->getOperand(1).isRegister() || MI->getOperand(1).isImmediate())&&
"Bad MRMSxR format!");
assert((MI->getNumOperands() < 3 ||
- (MI->getOperand(1).isRegister() && MI->getOperand(2).isImmediate())) &&
+ (MI->getOperand(1).isRegister() && MI->getOperand(2).isImmediate())) &&
"Bad MRMSxR format!");
if (MI->getNumOperands() > 1 && MI->getOperand(1).isRegister() &&
@@ -456,4 +815,59 @@
default:
O << "\tUNKNOWN FORM:\t\t-"; MI->print(O, TM); break;
}
+}
+
+bool Printer::doInitialization(Module &M)
+{
+ // Tell gas we are outputting Intel syntax (not AT&T syntax) assembly,
+ // with no % decorations on register names.
+ O << "\t.intel_syntax noprefix\n";
+
+ // Ripped from CWriter:
+ // Calculate which global values have names that will collide when we throw
+ // away type information.
+ { // Scope to delete the FoundNames set when we are done with it...
+ std::set<std::string> FoundNames;
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
+ if (I->hasName()) // If the global has a name...
+ if (FoundNames.count(I->getName())) // And the name is already used
+ MangledGlobals.insert(I); // Mangle the name
+ else
+ FoundNames.insert(I->getName()); // Otherwise, keep track of name
+
+ for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
+ if (I->hasName()) // If the global has a name...
+ if (FoundNames.count(I->getName())) // And the name is already used
+ MangledGlobals.insert(I); // Mangle the name
+ else
+ FoundNames.insert(I->getName()); // Otherwise, keep track of name
+ }
+
+ return false; // success
+}
+
+bool Printer::doFinalization(Module &M)
+{
+ // Print out module-level global variables here.
+ for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I) {
+ std::string name(getValueName(I));
+ if (I->hasInitializer()) {
+ Constant *C = I->getInitializer();
+ O << "\t.data\n";
+ O << "\t.globl " << name << "\n";
+ O << "\t.type " << name << ", at object\n";
+ O << "\t.size " << name << ","
+ << (unsigned)TD->getTypeSize(I->getType()) << "\n";
+ O << "\t.align " << (unsigned)TD->getTypeAlignment(C->getType()) << "\n";
+ O << name << ":\t\t\t\t\t#" << *C << "\n";
+ printConstantValueOnly (C);
+ } else {
+ O << "\t.globl " << name << "\n";
+ O << "\t.comm " << name << ", "
+ << (unsigned)TD->getTypeSize(I->getType()) << ", "
+ << (unsigned)TD->getTypeAlignment(I->getType()) << "\n";
+ }
+ }
+ MangledGlobals.clear();
+ return false; // success
}
Index: llvm/lib/Target/X86/X86InstrInfo.def
diff -u llvm/lib/Target/X86/X86InstrInfo.def:1.57 llvm/lib/Target/X86/X86InstrInfo.def:1.57.2.1
--- llvm/lib/Target/X86/X86InstrInfo.def:1.57 Thu Jun 5 14:30:30 2003
+++ llvm/lib/Target/X86/X86InstrInfo.def Thu Jun 26 16:35:24 2003
@@ -48,7 +48,10 @@
// Arguments to be passed into the I macro
// #1: Enum name - This ends up being the opcode symbol in the X86 namespace
-// #2: Opcode name, as used by the gnu assembler
+// #2: Opcode name, as used by the Intel assembler. This should be in
+// ALL CAPS for pseudo-instructions (which the assembler should never
+// see), or all lowercase for real instructions (which the assembler
+// should see).
// #3: The base opcode for the instruction
// #4: Instruction Flags - This should be a field or'd together that contains
// constants from the TargetInstrInfo.h file.
@@ -60,7 +63,7 @@
//
// The first instruction must always be the PHI instruction:
-I(PHI , "phi", 0, 0, X86II::Pseudo , NoIR, NoIR)
+I(PHI , "PHI", 0, 0, X86II::Pseudo , NoIR, NoIR)
// The second instruction must always be the noop instruction:
I(NOOP , "nop", 0x90, 0, X86II::RawFrm | X86II::Void, NoIR, NoIR) // nop
@@ -72,18 +75,18 @@
// instruction turns into a noop, but if the frame pointer is retained, this
// turns into a 'sub ESP, <amount>'.
//
-I(ADJCALLSTACKDOWN, "adjcallstackdown", 0, 0, X86II::Pseudo, NoIR, NoIR)
+I(ADJCALLSTACKDOWN, "ADJCALLSTACKDOWN", 0, 0, X86II::Pseudo, NoIR, NoIR)
// This instruction is used to mark readjustment of the stack after a function
// call. If the frame pointer is retained, this becomes a 'add ESP, <amount>'
// instruction after the call.
-I(ADJCALLSTACKUP , "adjcallstackup" , 0, 0, X86II::Pseudo, NoIR, NoIR)
+I(ADJCALLSTACKUP , "ADJCALLSTACKUP" , 0, 0, X86II::Pseudo, NoIR, NoIR)
// This pseudo-instruction is used to record implicit uses of physical registers
// at the end of the function. This ensures that bad things aren't done to
// registes that are live on exit from the function (for example, EAX).
//
-I(IMPLICIT_USE, "implicit_use", 0, 0, X86II::Pseudo, NoIR, NoIR)
+I(IMPLICIT_USE, "IMPLICIT_USE", 0, 0, X86II::Pseudo, NoIR, NoIR)
// Flow control instructions
@@ -163,22 +166,24 @@
I(MULr8 , "mul", 0xF6, 0, X86II::MRMS4r | X86II::Void, O_AL, O_AX) // AX = AL*R8
I(MULr16 , "mul", 0xF7, 0, X86II::MRMS4r | X86II::Void | // DX:AX= AX*R16
- X86II::OpSize, O_AX, T_AXDX)
+ X86II::OpSize, O_AX, T_AXDX)
I(MULr32 , "mul", 0xF7, 0, X86II::MRMS4r | X86II::Void, O_EAX, T_EAXEDX) // ED:EA= EA*R32
+I(IMULr16 , "imul", 0xAF, M_2_ADDR_FLAG, X86II::MRMSrcReg | X86II::TB | // R16 *= R16
+ X86II::OpSize, NoIR, NoIR)
+I(IMULr32 , "imul", 0xAF, M_2_ADDR_FLAG, X86II::MRMSrcReg | X86II::TB, NoIR, NoIR) // R32 *= R32
+
// unsigned division/remainder
I(DIVr8 , "div", 0xF6, 0, X86II::MRMS6r | X86II::Void, O_AX, O_AX) // AX/r8= AL&AH
I(DIVr16 , "div", 0xF7, 0, X86II::MRMS6r | X86II::Void | // ED:EA/r16=AX&DX
- X86II::OpSize, T_AXDX, T_AXDX)
-I(DIVr32 , "div", 0xF7, 0, X86II::MRMS6r | X86II::Void, T_EAXEDX,
- T_EAXEDX) // ED:EA/r32=EA&ED
+ X86II::OpSize, T_AXDX, T_AXDX)
+I(DIVr32 , "div", 0xF7, 0, X86II::MRMS6r | X86II::Void, T_EAXEDX,T_EAXEDX)// ED:EA/r32=EA&ED
// signed division/remainder
I(IDIVr8 , "idiv", 0xF6, 0, X86II::MRMS7r | X86II::Void, O_AX, O_AX) // AX/r8= AL&AH
I(IDIVr16 , "idiv", 0xF7, 0, X86II::MRMS7r | X86II::Void | // DA/r16=AX&DX
- X86II::OpSize, T_AXDX, T_AXDX)
-I(IDIVr32 , "idiv", 0xF7, 0, X86II::MRMS7r | X86II::Void, T_EAXEDX,
- T_EAXEDX) // DA/r32=EAX&DX
+ X86II::OpSize, T_AXDX, T_AXDX)
+I(IDIVr32 , "idiv", 0xF7, 0, X86II::MRMS7r | X86II::Void, T_EAXEDX,T_EAXEDX)// DA/r32=EAX&DX
// Logical operators
I(ANDrr8 , "and", 0x20, M_2_ADDR_FLAG, X86II::MRMDestReg, NoIR, NoIR) // R8 &= R8
@@ -260,12 +265,12 @@
// Integer comparisons
-I(CMPrr8 , "cmpb", 0x38, 0, X86II::Void | X86II::MRMDestReg , NoIR, NoIR) // compare R8,R8
-I(CMPrr16 , "cmpw", 0x39, 0, X86II::Void | X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // compare R16,R16
-I(CMPrr32 , "cmpl", 0x39, 0, X86II::Void | X86II::MRMDestReg , NoIR, NoIR) // compare R32,R32
-I(CMPri8 , "cmpb", 0x80, 0, X86II::Void | X86II::MRMS7r | X86II::Arg8 , NoIR, NoIR) // compare R8, imm8
-I(CMPri16 , "cmpw", 0x81, 0, X86II::Void | X86II::MRMS7r | X86II::Arg16 | X86II::OpSize, NoIR, NoIR) // compare R8, imm8
-I(CMPri32 , "cmpl", 0x81, 0, X86II::Void | X86II::MRMS7r | X86II::Arg32 , NoIR, NoIR) // compare R8, imm8
+I(CMPrr8 , "cmp", 0x38, 0, X86II::Void | X86II::MRMDestReg , NoIR, NoIR) // compare R8,R8
+I(CMPrr16 , "cmp", 0x39, 0, X86II::Void | X86II::MRMDestReg | X86II::OpSize, NoIR, NoIR) // compare R16,R16
+I(CMPrr32 , "cmp", 0x39, 0, X86II::Void | X86II::MRMDestReg , NoIR, NoIR) // compare R32,R32
+I(CMPri8 , "cmp", 0x80, 0, X86II::Void | X86II::MRMS7r | X86II::Arg8 , NoIR, NoIR) // compare R8, imm8
+I(CMPri16 , "cmp", 0x81, 0, X86II::Void | X86II::MRMS7r | X86II::Arg16 | X86II::OpSize, NoIR, NoIR) // compare R8, imm8
+I(CMPri32 , "cmp", 0x81, 0, X86II::Void | X86II::MRMS7r | X86II::Arg32 , NoIR, NoIR) // compare R8, imm8
// Sign extenders (first 3 are good for DIV/IDIV; the others are more general)
I(CBW , "cbw", 0x98, 0, X86II::Void | X86II::RawFrm | X86II::OpSize, O_AL, O_AH) // AX = signext(AL)
@@ -299,60 +304,60 @@
I(FpSETRESULT , "FSETRESULT",0, M_PSEUDO_FLAG | M_TERMINATOR_FLAG, X86II::Void | X86II::Pseudo | X86II::SpecialFP, NoIR, NoIR) // ST(0) = FPR
// Floating point loads & stores... PREFIX ARGTYPE ENCODING FP INST TYPE REF MOD
-I(FLDr32 , "fld32", 0xD9, 0, X86II::ArgF32 | X86II::MRMS0m | X86II::ZeroArgFP, NoIR, NoIR) // load float
-I(FLDr64 , "fld64", 0xDD, 0, X86II::ArgF64 | X86II::MRMS0m | X86II::ZeroArgFP, NoIR, NoIR) // load double
-I(FLDr80 , "fld80", 0xDB, 0, X86II::ArgF80 | X86II::MRMS5m | X86II::ZeroArgFP, NoIR, NoIR) // load extended
+I(FLDr32 , "fld", 0xD9, 0, X86II::ArgF32 | X86II::MRMS0m | X86II::ZeroArgFP, NoIR, NoIR) // load float
+I(FLDr64 , "fld", 0xDD, 0, X86II::ArgF64 | X86II::MRMS0m | X86II::ZeroArgFP, NoIR, NoIR) // load double
+I(FLDr80 , "fld", 0xDB, 0, X86II::ArgF80 | X86II::MRMS5m | X86II::ZeroArgFP, NoIR, NoIR) // load extended
I(FLDrr , "fld" , 0xC0, 0, X86II::D9 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // push(ST(i))
-I(FILDr16 , "fild16", 0xDF, 0, X86II::Arg16 | X86II::MRMS0m | X86II::ZeroArgFP, NoIR, NoIR) // load signed short
-I(FILDr32 , "fild32", 0xDB, 0, X86II::Arg32 | X86II::MRMS0m | X86II::ZeroArgFP, NoIR, NoIR) // load signed int
-I(FILDr64 , "fild64", 0xDF, 0, X86II::Arg64 | X86II::MRMS5m | X86II::ZeroArgFP, NoIR, NoIR) // load signed long
+I(FILDr16 , "fild", 0xDF, 0, X86II::Arg16 | X86II::MRMS0m | X86II::ZeroArgFP, NoIR, NoIR) // load signed short
+I(FILDr32 , "fild", 0xDB, 0, X86II::Arg32 | X86II::MRMS0m | X86II::ZeroArgFP, NoIR, NoIR) // load signed int
+I(FILDr64 , "fild", 0xDF, 0, X86II::Arg64 | X86II::MRMS5m | X86II::ZeroArgFP, NoIR, NoIR) // load signed long
-I(FSTr32 , "fst32", 0xD9, 0, X86II::Void | X86II::ArgF32 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store float
-I(FSTr64 , "fst64", 0xDD, 0, X86II::Void | X86II::ArgF64 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store double
-I(FSTPr32 , "fst32p", 0xD9, 0, X86II::Void | X86II::ArgF32 | X86II::MRMS3m , NoIR, NoIR) // store float, pop
-I(FSTPr64 , "fst64p", 0xDD, 0, X86II::Void | X86II::ArgF64 | X86II::MRMS3m , NoIR, NoIR) // store double, pop
-I(FSTPr80 , "fst80p", 0xDB, 0, X86II::Void | X86II::ArgF80 | X86II::MRMS7m | X86II::OneArgFP , NoIR, NoIR) // store extended, pop
+I(FSTr32 , "fst", 0xD9, 0, X86II::Void | X86II::ArgF32 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store float
+I(FSTr64 , "fst", 0xDD, 0, X86II::Void | X86II::ArgF64 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store double
+I(FSTPr32 , "fstp", 0xD9, 0, X86II::Void | X86II::ArgF32 | X86II::MRMS3m , NoIR, NoIR) // store float, pop
+I(FSTPr64 , "fstp", 0xDD, 0, X86II::Void | X86II::ArgF64 | X86II::MRMS3m , NoIR, NoIR) // store double, pop
+I(FSTPr80 , "fstp", 0xDB, 0, X86II::Void | X86II::ArgF80 | X86II::MRMS7m | X86II::OneArgFP , NoIR, NoIR) // store extended, pop
I(FSTrr , "fst" , 0xD0, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0)
I(FSTPrr , "fstp" , 0xD8, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0), pop
-I(FISTr16 , "fist16", 0xDF, 0, X86II::Void | X86II::Arg16 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store signed short
-I(FISTr32 , "fist32", 0xDB, 0, X86II::Void | X86II::Arg32 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store signed int
-I(FISTPr16 , "fist16p", 0xDF, 0, X86II::Void | X86II::Arg16 | X86II::MRMS3m , NoIR, NoIR) // store short, pop
-I(FISTPr32 , "fist32p", 0xDB, 0, X86II::Void | X86II::Arg32 | X86II::MRMS3m , NoIR, NoIR) // store int, pop
-I(FISTPr64 , "fist64p", 0xDF, 0, X86II::Void | X86II::Arg64 | X86II::MRMS7m | X86II::OneArgFP , NoIR, NoIR) // store long, pop
+I(FISTr16 , "fist", 0xDF, 0, X86II::Void | X86II::Arg16 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store signed short
+I(FISTr32 , "fist", 0xDB, 0, X86II::Void | X86II::Arg32 | X86II::MRMS2m | X86II::OneArgFP , NoIR, NoIR) // store signed int
+I(FISTPr16 , "fistp", 0xDF, 0, X86II::Void | X86II::Arg16 | X86II::MRMS3m , NoIR, NoIR) // store short, pop
+I(FISTPr32 , "fistp", 0xDB, 0, X86II::Void | X86II::Arg32 | X86II::MRMS3m , NoIR, NoIR) // store int, pop
+I(FISTPr64 , "fistp", 0xDF, 0, X86II::Void | X86II::Arg64 | X86II::MRMS7m | X86II::OneArgFP , NoIR, NoIR) // store long, pop
I(FXCH , "fxch" , 0xC8, 0, X86II::D9 | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , O_ST0, O_ST0) // fxch ST(i), ST(0)
// Floating point constant loads...
-I(FLD0 , "fld0" , 0xEE, 0, X86II::D9 | X86II::ArgF80 | X86II::RawFrm | X86II::ZeroArgFP, NoIR, NoIR) // load +0.0
+I(FLD0 , "fldz" , 0xEE, 0, X86II::D9 | X86II::ArgF80 | X86II::RawFrm | X86II::ZeroArgFP, NoIR, NoIR) // load +0.0
I(FLD1 , "fld1" , 0xE8, 0, X86II::D9 | X86II::ArgF80 | X86II::RawFrm | X86II::ZeroArgFP, NoIR, NoIR) // load +1.0
// Binary arithmetic operations...
-I(FADDST0r , "fadd_0", 0xC0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) + ST(i)
-I(FADDrST0 , "fadd_i", 0xC0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) + ST(0)
-I(FADDPrST0 , "faddp_i", 0xC0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) + ST(0), pop
-
-I(FSUBRST0r , "fsubr_0" , 0xE8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(i) - ST(0)
-I(FSUBrST0 , "fsub_i" , 0xE8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) - ST(0)
-I(FSUBPrST0 , "fsubp_i" , 0xE8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) - ST(0), pop
-
-I(FSUBST0r , "fsub_0" , 0xE0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) - ST(i)
-I(FSUBRrST0 , "fsubr_i" , 0xE0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) - ST(i)
-I(FSUBRPrST0 , "fsubrp_i", 0xE0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) - ST(i), pop
-
-I(FMULST0r , "fmul_0", 0xC8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) * ST(i)
-I(FMULrST0 , "fmul_i", 0xC8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) * ST(0)
-I(FMULPrST0 , "fmulp_i", 0xC8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) * ST(0), pop
-
-I(FDIVRST0r , "fdivr_0" , 0xF8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(i) / ST(0)
-I(FDIVrST0 , "fdiv_i" , 0xF8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) / ST(0)
-I(FDIVPrST0 , "fdivp_i" , 0xF8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) / ST(0), pop
-
-I(FDIVST0r , "fdiv_0" , 0xF0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) / ST(i)
-I(FDIVRrST0 , "fdivr_i" , 0xF0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) / ST(i)
-I(FDIVRPrST0 , "fdivrp_i", 0xF0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) / ST(i), pop
+I(FADDST0r , "fadd", 0xC0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) + ST(i)
+I(FADDrST0 , "fadd", 0xC0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) + ST(0)
+I(FADDPrST0 , "faddp", 0xC0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) + ST(0), pop
+
+I(FSUBRST0r , "fsubr" , 0xE8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(i) - ST(0)
+I(FSUBrST0 , "fsub" , 0xE8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) - ST(0)
+I(FSUBPrST0 , "fsubp" , 0xE8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) - ST(0), pop
+
+I(FSUBST0r , "fsub" , 0xE0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) - ST(i)
+I(FSUBRrST0 , "fsubr" , 0xE0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) - ST(i)
+I(FSUBRPrST0 , "fsubrp", 0xE0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) - ST(i), pop
+
+I(FMULST0r , "fmul", 0xC8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) * ST(i)
+I(FMULrST0 , "fmul", 0xC8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) * ST(0)
+I(FMULPrST0 , "fmulp", 0xC8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) * ST(0), pop
+
+I(FDIVRST0r , "fdivr" , 0xF8, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(i) / ST(0)
+I(FDIVrST0 , "fdiv" , 0xF8, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) / ST(0)
+I(FDIVPrST0 , "fdivp" , 0xF8, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(i) / ST(0), pop
+
+I(FDIVST0r , "fdiv" , 0xF0, 0, X86II::D8 | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(0) = ST(0) / ST(i)
+I(FDIVRrST0 , "fdivr" , 0xF0, 0, X86II::DC | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) / ST(i)
+I(FDIVRPrST0 , "fdivrp", 0xF0, 0, X86II::DE | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // ST(i) = ST(0) / ST(i), pop
// Floating point compares
I(FUCOMr , "fucom" , 0xE0, 0, X86II::DD | X86II::Void | X86II::ArgF80 | X86II::AddRegFrm , NoIR, NoIR) // FPSW = compare ST(0) with ST(i)
Index: llvm/lib/Target/X86/X86TargetMachine.cpp
diff -u llvm/lib/Target/X86/X86TargetMachine.cpp:1.17 llvm/lib/Target/X86/X86TargetMachine.cpp:1.17.2.1
--- llvm/lib/Target/X86/X86TargetMachine.cpp:1.17 Sat Apr 26 15:11:04 2003
+++ llvm/lib/Target/X86/X86TargetMachine.cpp Thu Jun 26 16:35:24 2003
@@ -41,6 +41,19 @@
FrameInfo(TargetFrameInfo::StackGrowsDown, 8/*16 for SSE*/, 4) {
}
+// llc backend for x86
+bool X86TargetMachine::addPassesToEmitAssembly(PassManager &PM,
+ std::ostream &Out) {
+ PM.add(createLowerSwitchPass());
+ PM.add(createSimpleX86InstructionSelector(*this));
+ PM.add(createLocalRegisterAllocator());
+ PM.add(createX86FloatingPointStackifierPass());
+ PM.add(createPrologEpilogCodeInserter());
+ PM.add(createX86PeepholeOptimizerPass());
+ PM.add(createX86CodePrinterPass(Out));
+ return false; // success!
+}
+
/// addPassesToJITCompile - Add passes to the specified pass manager to
/// implement a fast dynamic compiler for this target. Return true if this is
/// not supported for this target.
Index: llvm/lib/Target/X86/X86TargetMachine.h
diff -u llvm/lib/Target/X86/X86TargetMachine.h:1.9 llvm/lib/Target/X86/X86TargetMachine.h:1.9.2.1
--- llvm/lib/Target/X86/X86TargetMachine.h:1.9 Sat Dec 28 21:13:05 2002
+++ llvm/lib/Target/X86/X86TargetMachine.h Thu Jun 26 16:35:24 2003
@@ -42,6 +42,8 @@
///
virtual bool addPassesToEmitMachineCode(PassManager &PM,
MachineCodeEmitter &MCE);
+
+ virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
};
#endif
More information about the llvm-commits
mailing list