mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
and so it begins...
PHASE 1: write instruction selector PHASE 2: ??? PHASE 3: profit! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@20652 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7805fa4acc
commit
9b9d45f60e
50
lib/Target/IA64/IA64.h
Normal file
50
lib/Target/IA64/IA64.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
//===-- IA64.h - Top-level interface for IA64 representation ------*- C++ -*-===//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duraid Madina and is distributed under the
|
||||||
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the entry points for global functions defined in the IA64
|
||||||
|
// target library, as used by the LLVM JIT.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef TARGET_IA64_H
|
||||||
|
#define TARGET_IA64_H
|
||||||
|
|
||||||
|
#include <iosfwd>
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
class TargetMachine;
|
||||||
|
class FunctionPass;
|
||||||
|
class IntrinsicLowering;
|
||||||
|
|
||||||
|
/// createIA64PatternInstructionSelector - This pass converts an LLVM function
|
||||||
|
/// into a machine code representation in a more aggressive way.
|
||||||
|
///
|
||||||
|
FunctionPass *createIA64PatternInstructionSelector(TargetMachine &TM);
|
||||||
|
|
||||||
|
/// createIA64CodePrinterPass - Returns a pass that prints the IA64
|
||||||
|
/// assembly code for a MachineFunction to the given output stream,
|
||||||
|
/// using the given target machine description. This should work
|
||||||
|
/// regardless of whether the function is in SSA form.
|
||||||
|
///
|
||||||
|
FunctionPass *createIA64CodePrinterPass(std::ostream &o,TargetMachine &tm);
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
// Defines symbolic names for IA64 registers. This defines a mapping from
|
||||||
|
// register name to register number.
|
||||||
|
//
|
||||||
|
#include "IA64GenRegisterNames.inc"
|
||||||
|
|
||||||
|
// Defines symbolic names for the IA64 instructions.
|
||||||
|
//
|
||||||
|
#include "IA64GenInstrNames.inc"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
93
lib/Target/IA64/IA64.td
Normal file
93
lib/Target/IA64/IA64.td
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
//===-- IA64.td - Target definition file for Intel IA64 -------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duraid Madina and is distributed under the
|
||||||
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This is a target description file for the Intel IA64 architecture,
|
||||||
|
// also known variously as ia64, IA-64, IPF, "the Itanium architecture" etc.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// Get the target-independent interfaces which we are implementing...
|
||||||
|
//
|
||||||
|
include "../Target.td"
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Register File Description
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
include "IA64RegisterInfo.td"
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Instruction Descriptions
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
include "IA64InstrInfo.td"
|
||||||
|
|
||||||
|
def IA64InstrInfo : InstrInfo {
|
||||||
|
let PHIInst = PHI;
|
||||||
|
}
|
||||||
|
|
||||||
|
def IA64 : Target {
|
||||||
|
// The following registers are always saved across calls:
|
||||||
|
let CalleeSavedRegisters =
|
||||||
|
|
||||||
|
//'preserved' GRs:
|
||||||
|
|
||||||
|
[r4, r5, r6, r7,
|
||||||
|
|
||||||
|
//'special' GRs:
|
||||||
|
|
||||||
|
r1, // global data pointer (GP)
|
||||||
|
r12, // memory stack pointer (SP)
|
||||||
|
// **** r13 (thread pointer) we do not touch, ever. it's not here. ****//
|
||||||
|
//r15, // our frame pointer (FP)
|
||||||
|
|
||||||
|
//'stacked' GRs the RSE takes care of, we don't worry about
|
||||||
|
/* We don't want PEI::calculateCallerSavedRegisters to worry about them,
|
||||||
|
since the RSE takes care of them (and we determinethe appropriate
|
||||||
|
'alloc' instructions and save/restore ar.pfs ourselves, in instruction
|
||||||
|
selection)
|
||||||
|
|
||||||
|
**************************************************************************
|
||||||
|
* r32, r33, r34, r35,
|
||||||
|
* r36, r37, r38, r39, r40, r41, r42, r43, r44, r45, r46, r47,
|
||||||
|
* r48, r49, r50, r51, r52, r53, r54, r55, r56, r57, r58, r59,
|
||||||
|
* r60, r61, r62, r63, r64, r65, r66, r67, r68, r69, r70, r71,
|
||||||
|
* r72, r73, r74, r75, r76, r77, r78, r79, r80, r81, r82, r83,
|
||||||
|
* r84, r85, r86, r87, r88, r89, r90, r91, r92, r93, r94, r95,
|
||||||
|
* r96, r97, r98, r99, r100, r101, r102, r103, r104, r105, r106, r107,
|
||||||
|
* r108, r109, r110, r111, r112, r113, r114, r115, r116, r117, r118, r119,
|
||||||
|
* r120, r121, r122, r123, r124, r125, r126, r127,
|
||||||
|
**************************************************************************
|
||||||
|
*/
|
||||||
|
//'preserved' FP regs:
|
||||||
|
|
||||||
|
F2,F3,F4,F5,
|
||||||
|
F16,F17,F18,F19,F20,F21,F22,F23,
|
||||||
|
F24,F25,F26,F27,F28,F29,F30,F31,
|
||||||
|
|
||||||
|
//'preserved' predicate regs:
|
||||||
|
|
||||||
|
p1, p2, p3, p4, p5,
|
||||||
|
p16, p17, p18, p19, p20, p21, p22, p23,
|
||||||
|
p24, p25, p26, p27, p28, p29, p30, p31,
|
||||||
|
p32, p33, p34, p35, p36, p37, p38, p39,
|
||||||
|
p40, p41, p42, p43, p44, p45, p46, p47,
|
||||||
|
p48, p49, p50, p51, p52, p53, p54, p55,
|
||||||
|
p56, p57, p58, p59, p60, p61, p62, p63];
|
||||||
|
|
||||||
|
// We don't go anywhere near the LP32 variant of IA64 as
|
||||||
|
// sometimes seen in (for example) HP-UX
|
||||||
|
let PointerType = i64;
|
||||||
|
|
||||||
|
// Our instruction set
|
||||||
|
let InstructionSet = IA64InstrInfo;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
399
lib/Target/IA64/IA64AsmPrinter.cpp
Normal file
399
lib/Target/IA64/IA64AsmPrinter.cpp
Normal file
@ -0,0 +1,399 @@
|
|||||||
|
//===-- IA64AsmPrinter.cpp - Print out IA64 LLVM as assembly --------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duraid Madina and is distributed under the
|
||||||
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains a printer that converts from our internal representation
|
||||||
|
// of machine-dependent LLVM code to assembly accepted by the GNU binutils 'gas'
|
||||||
|
// assembler. The Intel 'ias' and HP-UX 'as' assemblers *may* choke on this
|
||||||
|
// output, but if so that's a bug I'd like to hear about: please file a bug
|
||||||
|
// report in bugzilla. FYI, the excellent 'ias' assembler is bundled with
|
||||||
|
// the Intel C/C++ compiler for Itanium Linux.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "IA64.h"
|
||||||
|
#include "IA64TargetMachine.h"
|
||||||
|
#include "llvm/Module.h"
|
||||||
|
#include "llvm/Assembly/Writer.h"
|
||||||
|
#include "llvm/CodeGen/AsmPrinter.h"
|
||||||
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||||
|
#include "llvm/CodeGen/ValueTypes.h"
|
||||||
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
#include "llvm/Support/Mangler.h"
|
||||||
|
#include "llvm/ADT/Statistic.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
|
||||||
|
|
||||||
|
struct IA64SharedAsmPrinter : public AsmPrinter {
|
||||||
|
|
||||||
|
std::set<std::string> ExternalFunctionNames;
|
||||||
|
|
||||||
|
IA64SharedAsmPrinter(std::ostream &O, TargetMachine &TM)
|
||||||
|
: AsmPrinter(O, TM) { }
|
||||||
|
|
||||||
|
void printConstantPool(MachineConstantPool *MCP);
|
||||||
|
bool doFinalization(Module &M);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isScale(const MachineOperand &MO) {
|
||||||
|
return MO.isImmediate() &&
|
||||||
|
(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+3).isGlobalAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
// SwitchSection - Switch to the specified section of the executable if we are
|
||||||
|
// not already in it!
|
||||||
|
//
|
||||||
|
static void SwitchSection(std::ostream &OS, std::string &CurSection,
|
||||||
|
const char *NewSection) {
|
||||||
|
if (CurSection != NewSection) {
|
||||||
|
CurSection = NewSection;
|
||||||
|
if (!CurSection.empty())
|
||||||
|
OS << "\t" << NewSection << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// printConstantPool - Print to the current output stream assembly
|
||||||
|
/// representations of the constants in the constant pool MCP. This is
|
||||||
|
/// used to print out constants which have been "spilled to memory" by
|
||||||
|
/// the code generator.
|
||||||
|
///
|
||||||
|
void IA64SharedAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
|
||||||
|
const std::vector<Constant*> &CP = MCP->getConstants();
|
||||||
|
const TargetData &TD = TM.getTargetData();
|
||||||
|
|
||||||
|
if (CP.empty()) return;
|
||||||
|
|
||||||
|
O << "\n\t.section .data\n"; // would be nice to have this rodata? hmmm
|
||||||
|
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
|
||||||
|
emitAlignment(TD.getTypeAlignmentShift(CP[i]->getType()));
|
||||||
|
O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t" << CommentString
|
||||||
|
<< *CP[i] << "\n";
|
||||||
|
emitGlobalConstant(CP[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IA64SharedAsmPrinter::doFinalization(Module &M) {
|
||||||
|
const TargetData &TD = TM.getTargetData();
|
||||||
|
std::string CurSection;
|
||||||
|
|
||||||
|
// Print out module-level global variables here.
|
||||||
|
for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
|
||||||
|
if (I->hasInitializer()) { // External global require no code
|
||||||
|
O << "\n\n";
|
||||||
|
std::string name = Mang->getValueName(I);
|
||||||
|
Constant *C = I->getInitializer();
|
||||||
|
unsigned Size = TD.getTypeSize(C->getType());
|
||||||
|
unsigned Align = TD.getTypeAlignmentShift(C->getType());
|
||||||
|
|
||||||
|
if (C->isNullValue() &&
|
||||||
|
(I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
|
||||||
|
I->hasWeakLinkage() /* FIXME: Verify correct */)) {
|
||||||
|
SwitchSection(O, CurSection, ".data");
|
||||||
|
if (I->hasInternalLinkage())
|
||||||
|
O << "\t.local " << name << "\n";
|
||||||
|
|
||||||
|
O << "\t.common " << name << "," << TD.getTypeSize(C->getType())
|
||||||
|
<< "," << (1 << Align);
|
||||||
|
O << "\t\t// ";
|
||||||
|
WriteAsOperand(O, I, true, true, &M);
|
||||||
|
O << "\n";
|
||||||
|
} else {
|
||||||
|
switch (I->getLinkage()) {
|
||||||
|
case GlobalValue::LinkOnceLinkage:
|
||||||
|
case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
|
||||||
|
// Nonnull linkonce -> weak
|
||||||
|
O << "\t.weak " << name << "\n";
|
||||||
|
SwitchSection(O, CurSection, "");
|
||||||
|
O << "\t.section\t.llvm.linkonce.d." << name
|
||||||
|
<< ", \"aw\", \"progbits\"\n";
|
||||||
|
break;
|
||||||
|
case GlobalValue::AppendingLinkage:
|
||||||
|
// FIXME: appending linkage variables should go into a section of
|
||||||
|
// their name or something. For now, just emit them as external.
|
||||||
|
case GlobalValue::ExternalLinkage:
|
||||||
|
// If external or appending, declare as a global symbol
|
||||||
|
O << "\t.global " << name << "\n";
|
||||||
|
// FALL THROUGH
|
||||||
|
case GlobalValue::InternalLinkage:
|
||||||
|
if (C->isNullValue())
|
||||||
|
SwitchSection(O, CurSection, ".data"); // FIXME: this was
|
||||||
|
// '.bss', but in ia64-land .bss means "nobits" (i.e. uninitialized)
|
||||||
|
// hmm.
|
||||||
|
else
|
||||||
|
SwitchSection(O, CurSection, ".data");
|
||||||
|
break;
|
||||||
|
case GlobalValue::GhostLinkage:
|
||||||
|
std::cerr << "GhostLinkage cannot appear in IA64AsmPrinter!\n";
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
emitAlignment(Align);
|
||||||
|
O << "\t.type " << name << ",@object\n";
|
||||||
|
O << "\t.size " << name << "," << Size << "\n";
|
||||||
|
O << name << ":\t\t\t\t// ";
|
||||||
|
WriteAsOperand(O, I, true, true, &M);
|
||||||
|
O << " = ";
|
||||||
|
WriteAsOperand(O, C, false, false, &M);
|
||||||
|
O << "\n";
|
||||||
|
emitGlobalConstant(C);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we print out ".global X \n .type X, @function" for each external function
|
||||||
|
O << "\n\n// br.call targets referenced (and not defined) above: \n";
|
||||||
|
for (std::set<std::string>::iterator i = ExternalFunctionNames.begin(),
|
||||||
|
e = ExternalFunctionNames.end(); i!=e; ++i) {
|
||||||
|
O << "\t.global " << *i << "\n\t.type " << *i << ", @function\n";
|
||||||
|
}
|
||||||
|
O << "\n\n";
|
||||||
|
|
||||||
|
AsmPrinter::doFinalization(M);
|
||||||
|
return false; // success
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct IA64AsmPrinter : public IA64SharedAsmPrinter {
|
||||||
|
IA64AsmPrinter(std::ostream &O, TargetMachine &TM)
|
||||||
|
: IA64SharedAsmPrinter(O, TM) {
|
||||||
|
|
||||||
|
CommentString = "//";
|
||||||
|
Data8bitsDirective = "\tdata1\t";
|
||||||
|
Data16bitsDirective = "\tdata2\t";
|
||||||
|
Data32bitsDirective = "\tdata4\t";
|
||||||
|
Data64bitsDirective = "\tdata8\t";
|
||||||
|
ZeroDirective = "\t.skip\t";
|
||||||
|
AsciiDirective = "\tstring\t";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const char *getPassName() const {
|
||||||
|
return "IA64 Assembly Printer";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// printInstruction - This method is automatically generated by tablegen
|
||||||
|
/// from the instruction set description. This method returns true if the
|
||||||
|
/// machine instruction was sufficiently described to print it, otherwise it
|
||||||
|
/// returns false.
|
||||||
|
bool printInstruction(const MachineInstr *MI);
|
||||||
|
|
||||||
|
// This method is used by the tablegen'erated instruction printer.
|
||||||
|
void printOperand(const MachineInstr *MI, unsigned OpNo, MVT::ValueType VT){
|
||||||
|
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||||
|
if (MO.getType() == MachineOperand::MO_MachineRegister) {
|
||||||
|
assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physref??");
|
||||||
|
//XXX Bug Workaround: See note in Printer::doInitialization about %.
|
||||||
|
O << TM.getRegisterInfo()->get(MO.getReg()).Name;
|
||||||
|
} else {
|
||||||
|
printOp(MO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void printS16ImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
|
MVT::ValueType VT) {
|
||||||
|
O << (short)MI->getOperand(OpNo).getImmedValue();
|
||||||
|
}
|
||||||
|
void printU16ImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
|
MVT::ValueType VT) {
|
||||||
|
O << (unsigned short)MI->getOperand(OpNo).getImmedValue();
|
||||||
|
}
|
||||||
|
void printS21ImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
|
MVT::ValueType VT) {
|
||||||
|
O << (int)MI->getOperand(OpNo).getImmedValue(); // FIXME (21, not 32!)
|
||||||
|
}
|
||||||
|
void printS32ImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
|
MVT::ValueType VT) {
|
||||||
|
O << (int)MI->getOperand(OpNo).getImmedValue();
|
||||||
|
}
|
||||||
|
void printU32ImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
|
MVT::ValueType VT) {
|
||||||
|
O << (unsigned int)MI->getOperand(OpNo).getImmedValue();
|
||||||
|
}
|
||||||
|
void printU64ImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
|
MVT::ValueType VT) {
|
||||||
|
O << (uint64_t)MI->getOperand(OpNo).getImmedValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
void printCallOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
|
MVT::ValueType VT) {
|
||||||
|
printOp(MI->getOperand(OpNo), true); // this is a br.call instruction
|
||||||
|
}
|
||||||
|
|
||||||
|
void printMachineInstruction(const MachineInstr *MI);
|
||||||
|
void printOp(const MachineOperand &MO, bool isBRCALLinsn= false);
|
||||||
|
bool runOnMachineFunction(MachineFunction &F);
|
||||||
|
bool doInitialization(Module &M);
|
||||||
|
};
|
||||||
|
} // end of anonymous namespace
|
||||||
|
|
||||||
|
|
||||||
|
// Include the auto-generated portion of the assembly writer.
|
||||||
|
#include "IA64GenAsmWriter.inc"
|
||||||
|
|
||||||
|
|
||||||
|
/// runOnMachineFunction - This uses the printMachineInstruction()
|
||||||
|
/// method to print assembly for each instruction.
|
||||||
|
///
|
||||||
|
bool IA64AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
||||||
|
setupMachineFunction(MF);
|
||||||
|
O << "\n\n";
|
||||||
|
|
||||||
|
// Print out constants referenced by the function
|
||||||
|
printConstantPool(MF.getConstantPool());
|
||||||
|
|
||||||
|
// Print out labels for the function.
|
||||||
|
O << "\n\t.section .text, \"ax\", \"progbits\"\n";
|
||||||
|
// ^^ means "Allocated instruXions in mem, initialized"
|
||||||
|
emitAlignment(4);
|
||||||
|
O << "\t.global\t" << CurrentFnName << "\n";
|
||||||
|
O << "\t.type\t" << CurrentFnName << ", @function\n";
|
||||||
|
O << CurrentFnName << ":\n";
|
||||||
|
|
||||||
|
// 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 if there are any predecessors.
|
||||||
|
if (I->pred_begin() != I->pred_end())
|
||||||
|
O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t"
|
||||||
|
<< CommentString << " " << I->getBasicBlock()->getName() << "\n";
|
||||||
|
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
|
||||||
|
II != E; ++II) {
|
||||||
|
// Print the assembly for the instruction.
|
||||||
|
O << "\t";
|
||||||
|
printMachineInstruction(II);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We didn't modify anything.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IA64AsmPrinter::printOp(const MachineOperand &MO,
|
||||||
|
bool isBRCALLinsn /* = false */) {
|
||||||
|
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||||
|
switch (MO.getType()) {
|
||||||
|
case MachineOperand::MO_VirtualRegister:
|
||||||
|
if (Value *V = MO.getVRegValueOrNull()) {
|
||||||
|
O << "<" << V->getName() << ">";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// FALLTHROUGH
|
||||||
|
case MachineOperand::MO_MachineRegister:
|
||||||
|
case MachineOperand::MO_CCRegister: {
|
||||||
|
O << RI.get(MO.getReg()).Name;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MachineOperand::MO_SignExtendedImmed:
|
||||||
|
case MachineOperand::MO_UnextendedImmed:
|
||||||
|
O << /*(unsigned int)*/MO.getImmedValue();
|
||||||
|
return;
|
||||||
|
case MachineOperand::MO_MachineBasicBlock: {
|
||||||
|
MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
|
||||||
|
O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
|
||||||
|
<< "_" << MBBOp->getNumber () << "\t// "
|
||||||
|
<< MBBOp->getBasicBlock ()->getName ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case MachineOperand::MO_PCRelativeDisp:
|
||||||
|
std::cerr << "Shouldn't use addPCDisp() when building IA64 MachineInstrs";
|
||||||
|
abort ();
|
||||||
|
return;
|
||||||
|
|
||||||
|
case MachineOperand::MO_ConstantPoolIndex: {
|
||||||
|
O << "@gprel(.CPI" << CurrentFnName << "_"
|
||||||
|
<< MO.getConstantPoolIndex() << ")";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MachineOperand::MO_GlobalAddress: {
|
||||||
|
|
||||||
|
// functions need @ltoff(@fptr(fn_name)) form
|
||||||
|
GlobalValue *GV = MO.getGlobal();
|
||||||
|
Function *F = dyn_cast<Function>(GV);
|
||||||
|
|
||||||
|
bool Needfptr=false; // if we're computing an address @ltoff(X), do
|
||||||
|
// we need to decorate it so it becomes
|
||||||
|
// @ltoff(@fptr(X)) ?
|
||||||
|
if(F && !isBRCALLinsn && F->isExternal())
|
||||||
|
Needfptr=true;
|
||||||
|
|
||||||
|
// if this is the target of a call instruction, we should define
|
||||||
|
// the function somewhere (GNU gas has no problem without this, but
|
||||||
|
// Intel ias rightly complains of an 'undefined symbol')
|
||||||
|
|
||||||
|
if(F && isBRCALLinsn && F->isExternal())
|
||||||
|
ExternalFunctionNames.insert(Mang->getValueName(MO.getGlobal()));
|
||||||
|
|
||||||
|
if (!isBRCALLinsn)
|
||||||
|
O << "@ltoff(";
|
||||||
|
if (Needfptr)
|
||||||
|
O << "@fptr(";
|
||||||
|
O << Mang->getValueName(MO.getGlobal());
|
||||||
|
if (Needfptr)
|
||||||
|
O << ")"; // close fptr(
|
||||||
|
if (!isBRCALLinsn)
|
||||||
|
O << ")"; // close ltoff(
|
||||||
|
int Offset = MO.getOffset();
|
||||||
|
if (Offset > 0)
|
||||||
|
O << " + " << Offset;
|
||||||
|
else if (Offset < 0)
|
||||||
|
O << " - " << -Offset;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case MachineOperand::MO_ExternalSymbol:
|
||||||
|
O << MO.getSymbolName();
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
O << "<AsmPrinter: unknown operand type: " << MO.getType() << " >"; return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// printMachineInstruction -- Print out a single IA64 LLVM instruction
|
||||||
|
/// MI to the current output stream.
|
||||||
|
///
|
||||||
|
void IA64AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
||||||
|
|
||||||
|
++EmittedInsts;
|
||||||
|
|
||||||
|
// Call the autogenerated instruction printer routines.
|
||||||
|
printInstruction(MI);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IA64AsmPrinter::doInitialization(Module &M) {
|
||||||
|
AsmPrinter::doInitialization(M);
|
||||||
|
|
||||||
|
O << "\t.psr lsb\n" // should be "msb" on HP-UX, for starters
|
||||||
|
<< "\t.radix C\n"
|
||||||
|
<< "\t.psr abi64\n"; // we only support 64 bits for now
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// createIA64CodePrinterPass - Returns a pass that prints the IA64
|
||||||
|
/// assembly code for a MachineFunction to the given output stream, using
|
||||||
|
/// the given target machine description.
|
||||||
|
///
|
||||||
|
FunctionPass *llvm::createIA64CodePrinterPass(std::ostream &o,TargetMachine &tm){
|
||||||
|
return new IA64AsmPrinter(o, tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
1640
lib/Target/IA64/IA64ISelPattern.cpp
Normal file
1640
lib/Target/IA64/IA64ISelPattern.cpp
Normal file
File diff suppressed because it is too large
Load Diff
52
lib/Target/IA64/IA64InstrBuilder.h
Normal file
52
lib/Target/IA64/IA64InstrBuilder.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
//===-- IA64PCInstrBuilder.h - Aids for building IA64 insts -----*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duraid Madina and is distributed under the
|
||||||
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file exposes functions that may be used with BuildMI from the
|
||||||
|
// MachineInstrBuilder.h file to simplify generating frame and constant pool
|
||||||
|
// references.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef IA64_INSTRBUILDER_H
|
||||||
|
#define IA64_INSTRBUILDER_H
|
||||||
|
|
||||||
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
/// addFrameReference - This function is used to add a reference to the base of
|
||||||
|
/// an abstract object on the stack frame of the current function. This
|
||||||
|
/// reference has base register as the FrameIndex offset until it is resolved.
|
||||||
|
/// This allows a constant offset to be specified as well...
|
||||||
|
///
|
||||||
|
inline const MachineInstrBuilder&
|
||||||
|
addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0,
|
||||||
|
bool mem = true) {
|
||||||
|
if (mem)
|
||||||
|
return MIB.addSImm(Offset).addFrameIndex(FI);
|
||||||
|
else
|
||||||
|
return MIB.addFrameIndex(FI).addSImm(Offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// addConstantPoolReference - This function is used to add a reference to the
|
||||||
|
/// base of a constant value spilled to the per-function constant pool. The
|
||||||
|
/// reference has base register ConstantPoolIndex offset which is retained until
|
||||||
|
/// either machine code emission or assembly output. This allows an optional
|
||||||
|
/// offset to be added as well.
|
||||||
|
///
|
||||||
|
inline const MachineInstrBuilder&
|
||||||
|
addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI,
|
||||||
|
int Offset = 0) {
|
||||||
|
return MIB.addSImm(Offset).addConstantPoolIndex(CPI);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
67
lib/Target/IA64/IA64InstrFormats.td
Normal file
67
lib/Target/IA64/IA64InstrFormats.td
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
//===- IA64InstrFormats.td - IA64 Instruction Formats --*- tablegen -*-=//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duraid Madina and is distributed under the
|
||||||
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// - Warning: the stuff in here isn't really being used, so is mostly
|
||||||
|
// junk. It'll get fixed as the JIT gets built.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Instruction format superclass
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
class InstIA64<bits<4> op, dag OL, string asmstr> : Instruction {
|
||||||
|
// IA64 instruction baseline
|
||||||
|
field bits<41> Inst;
|
||||||
|
let Namespace = "IA64";
|
||||||
|
let OperandList = OL;
|
||||||
|
let AsmString = asmstr;
|
||||||
|
|
||||||
|
let Inst{40-37} = op;
|
||||||
|
}
|
||||||
|
|
||||||
|
//"Each Itanium instruction is categorized into one of six types."
|
||||||
|
//We should have:
|
||||||
|
// A, I, M, F, B, L+X
|
||||||
|
|
||||||
|
class AForm<bits<4> opcode, bits<6> qpReg, dag OL, string asmstr> :
|
||||||
|
InstIA64<opcode, OL, asmstr> {
|
||||||
|
|
||||||
|
let Inst{5-0} = qpReg;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isBranch = 1, isTerminator = 1 in
|
||||||
|
class BForm<bits<4> opcode, bits<6> x6, bits<3> btype, dag OL, string asmstr> :
|
||||||
|
InstIA64<opcode, OL, asmstr> {
|
||||||
|
|
||||||
|
let Inst{32-27} = x6;
|
||||||
|
let Inst{8-6} = btype;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MForm<bits<4> opcode, bits<6> x6, dag OL, string asmstr> :
|
||||||
|
InstIA64<opcode, OL, asmstr> {
|
||||||
|
bits<7> Ra;
|
||||||
|
bits<7> Rb;
|
||||||
|
bits<16> disp;
|
||||||
|
|
||||||
|
let Inst{35-30} = x6;
|
||||||
|
// let Inst{20-16} = Rb;
|
||||||
|
let Inst{15-0} = disp;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RawForm<bits<4> opcode, bits<26> rest, dag OL, string asmstr> :
|
||||||
|
InstIA64<opcode, OL, asmstr> {
|
||||||
|
let Inst{25-0} = rest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pseudo instructions.
|
||||||
|
class PseudoInstIA64<dag OL, string nm> : InstIA64<0, OL, nm> {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
47
lib/Target/IA64/IA64InstrInfo.cpp
Normal file
47
lib/Target/IA64/IA64InstrInfo.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
//===- IA64InstrInfo.cpp - IA64 Instruction Information -----------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by the LLVM research group and is distributed under
|
||||||
|
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the IA64 implementation of the TargetInstrInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "IA64InstrInfo.h"
|
||||||
|
#include "IA64.h"
|
||||||
|
#include "IA64InstrBuilder.h"
|
||||||
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
|
#include "IA64GenInstrInfo.inc"
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
IA64InstrInfo::IA64InstrInfo()
|
||||||
|
: TargetInstrInfo(IA64Insts, sizeof(IA64Insts)/sizeof(IA64Insts[0])) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IA64InstrInfo::isMoveInstr(const MachineInstr& MI,
|
||||||
|
unsigned& sourceReg,
|
||||||
|
unsigned& destReg) const {
|
||||||
|
MachineOpCode oc = MI.getOpcode();
|
||||||
|
if (oc == IA64::MOV || oc == IA64::FMOV) {
|
||||||
|
assert(MI.getNumOperands() == 2 &&
|
||||||
|
/* MI.getOperand(0).isRegister() &&
|
||||||
|
MI.getOperand(1).isRegister() && */
|
||||||
|
"invalid register-register move instruction");
|
||||||
|
if( MI.getOperand(0).isRegister() &&
|
||||||
|
MI.getOperand(1).isRegister() ) {
|
||||||
|
// if both operands of the MOV/FMOV are registers, then
|
||||||
|
// yes, this is a move instruction
|
||||||
|
sourceReg = MI.getOperand(1).getReg();
|
||||||
|
destReg = MI.getOperand(0).getReg();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false; // we don't consider e.g. %regN = MOV <FrameIndex #x> a
|
||||||
|
// move instruction
|
||||||
|
}
|
||||||
|
|
50
lib/Target/IA64/IA64InstrInfo.h
Normal file
50
lib/Target/IA64/IA64InstrInfo.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
//===- IA64InstrInfo.h - IA64 Instruction Information ----------*- C++ -*- ===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duraid Madina and is distributed under the
|
||||||
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the IA64 implementation of the TargetInstrInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef IA64INSTRUCTIONINFO_H
|
||||||
|
#define IA64INSTRUCTIONINFO_H
|
||||||
|
|
||||||
|
#include "llvm/Target/TargetInstrInfo.h"
|
||||||
|
#include "IA64RegisterInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
/// IA64II - This namespace holds all of the target specific flags that
|
||||||
|
/// instruction info tracks.
|
||||||
|
/// FIXME: now gone!
|
||||||
|
|
||||||
|
class IA64InstrInfo : public TargetInstrInfo {
|
||||||
|
const IA64RegisterInfo RI;
|
||||||
|
public:
|
||||||
|
IA64InstrInfo();
|
||||||
|
|
||||||
|
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
|
||||||
|
/// such, whenever a client has an instance of instruction info, it should
|
||||||
|
/// always be able to get register info as well (through this method).
|
||||||
|
///
|
||||||
|
virtual const MRegisterInfo &getRegisterInfo() const { return RI; }
|
||||||
|
|
||||||
|
//
|
||||||
|
// Return true if the instruction is a register to register move and
|
||||||
|
// leave the source and dest operands in the passed parameters.
|
||||||
|
//
|
||||||
|
virtual bool isMoveInstr(const MachineInstr& MI,
|
||||||
|
unsigned& sourceReg,
|
||||||
|
unsigned& destReg) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
319
lib/Target/IA64/IA64InstrInfo.td
Normal file
319
lib/Target/IA64/IA64InstrInfo.td
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
//===- IA64InstrInfo.td - Describe the IA64 Instruction Set -----*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duraid Madina and is distributed under the
|
||||||
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file describes the IA64 instruction set, defining the instructions, and
|
||||||
|
// properties of the instructions which are needed for code generation, machine
|
||||||
|
// code emission, and analysis.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
include "IA64InstrFormats.td"
|
||||||
|
|
||||||
|
def u6imm : Operand<i8>;
|
||||||
|
def s16imm : Operand<i16>;
|
||||||
|
def s21imm : Operand<i32> {
|
||||||
|
let PrintMethod = "printS21ImmOperand";
|
||||||
|
}
|
||||||
|
def u32imm : Operand<i32> {
|
||||||
|
let PrintMethod = "printU32ImmOperand";
|
||||||
|
}
|
||||||
|
def s32imm : Operand<i32> {
|
||||||
|
let PrintMethod = "printS32ImmOperand";
|
||||||
|
}
|
||||||
|
def u64imm : Operand<i64> {
|
||||||
|
let PrintMethod = "printU64ImmOperand";
|
||||||
|
}
|
||||||
|
|
||||||
|
// the asmprinter needs to know about calls
|
||||||
|
let PrintMethod = "printCallOperand" in
|
||||||
|
def calltarget : Operand<i64>;
|
||||||
|
|
||||||
|
def PHI : PseudoInstIA64<(ops), "PHI">;
|
||||||
|
def IDEF : PseudoInstIA64<(ops), "// IDEF">;
|
||||||
|
def WTF : PseudoInstIA64<(ops), "que??">;
|
||||||
|
def ADJUSTCALLSTACKUP : PseudoInstIA64<(ops), "// ADJUSTCALLSTACKUP">;
|
||||||
|
def ADJUSTCALLSTACKDOWN : PseudoInstIA64<(ops), "// ADJUSTCALLSTACKDOWN">;
|
||||||
|
def PSEUDO_ALLOC : PseudoInstIA64<(ops), "// PSEUDO_ALLOC">;
|
||||||
|
|
||||||
|
def ALLOC : AForm<0x03, 0x0b,
|
||||||
|
(ops GR:$dst, i8imm:$inputs, i8imm:$locals, i8imm:$outputs, i8imm:$rotating),
|
||||||
|
"alloc $dst = ar.pfs,$inputs,$locals,$outputs,$rotating;;">;
|
||||||
|
|
||||||
|
def MOV : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "mov $dst = $src;;">;
|
||||||
|
def PMOV : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src, PR:$qp),
|
||||||
|
"($qp) mov $dst = $src;;">;
|
||||||
|
|
||||||
|
def SPILL_ALL_PREDICATES_TO_GR : AForm<0x03, 0x0b, (ops GR:$dst),
|
||||||
|
"mov $dst = pr;;">;
|
||||||
|
def FILL_ALL_PREDICATES_FROM_GR : AForm<0x03, 0x0b, (ops GR:$src),
|
||||||
|
"mov pr = $src;;">;
|
||||||
|
|
||||||
|
let isTwoAddress = 1 in {
|
||||||
|
def CMOV : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src2, GR:$src, PR:$qp),
|
||||||
|
"($qp) mov $dst = $src;;">;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isTwoAddress = 1 in {
|
||||||
|
def TCMPNE : AForm<0x03, 0x0b,
|
||||||
|
(ops PR:$dst, PR:$src2, GR:$src3, GR:$src4),
|
||||||
|
"cmp.ne $dst, p0 = $src3, $src4;;">;
|
||||||
|
|
||||||
|
def TPCMPEQOR : AForm<0x03, 0x0b,
|
||||||
|
(ops PR:$dst, PR:$src2, GR:$src3, GR:$src4, PR:$qp),
|
||||||
|
"($qp) cmp.eq.or $dst, p0 = $src3, $src4;;">;
|
||||||
|
|
||||||
|
def TPCMPNE : AForm<0x03, 0x0b,
|
||||||
|
(ops PR:$dst, PR:$src2, GR:$src3, GR:$src4, PR:$qp),
|
||||||
|
"($qp) cmp.ne $dst, p0 = $src3, $src4;;">;
|
||||||
|
|
||||||
|
def TPCMPEQ : AForm<0x03, 0x0b,
|
||||||
|
(ops PR:$dst, PR:$src2, GR:$src3, GR:$src4, PR:$qp),
|
||||||
|
"($qp) cmp.eq $dst, p0 = $src3, $src4;;">;
|
||||||
|
}
|
||||||
|
|
||||||
|
def MOVI32 : AForm<0x03, 0x0b, (ops GR:$dst, u32imm:$imm),
|
||||||
|
"mov $dst = $imm;;">;
|
||||||
|
def MOVLI32 : AForm<0x03, 0x0b, (ops GR:$dst, u32imm:$imm),
|
||||||
|
"movl $dst = $imm;;">;
|
||||||
|
def MOVLSI32 : AForm<0x03, 0x0b, (ops GR:$dst, s32imm:$imm),
|
||||||
|
"movl $dst = $imm;;">;
|
||||||
|
def MOVLI64 : AForm<0x03, 0x0b, (ops GR:$dst, u64imm:$imm),
|
||||||
|
"movl $dst = $imm;;">;
|
||||||
|
|
||||||
|
def AND : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"and $dst = $src1, $src2;;">;
|
||||||
|
def OR : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"or $dst = $src1, $src2;;">;
|
||||||
|
def XOR : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"xor $dst = $src1, $src2;;">;
|
||||||
|
def SHL : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"shl $dst = $src1, $src2;;">;
|
||||||
|
def SHLI : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, s21imm:$imm),
|
||||||
|
"shl $dst = $src1, $imm;;">; // FIXME: 6 immediate bits, not 21
|
||||||
|
def SHRU : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"shr.u $dst = $src1, $src2;;">;
|
||||||
|
def SHRS : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"shr $dst = $src1, $src2;;">;
|
||||||
|
|
||||||
|
def DEPZ : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, u6imm:$imm1, u6imm:$imm2), "dep.z $dst = $src1, $imm1, $imm2;;">;
|
||||||
|
|
||||||
|
def SXT1 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "sxt1 $dst = $src;;">;
|
||||||
|
def ZXT1 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "zxt1 $dst = $src;;">;
|
||||||
|
def SXT2 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "sxt2 $dst = $src;;">;
|
||||||
|
def ZXT2 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "zxt2 $dst = $src;;">;
|
||||||
|
def SXT4 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "sxt4 $dst = $src;;">;
|
||||||
|
def ZXT4 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src), "zxt4 $dst = $src;;">;
|
||||||
|
|
||||||
|
// the following are all a bit unfortunate: we throw away the complement
|
||||||
|
// of the compare!
|
||||||
|
def CMPEQ : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"cmp.eq $dst, p0 = $src1, $src2;;">;
|
||||||
|
def CMPGT : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"cmp.gt $dst, p0 = $src1, $src2;;">;
|
||||||
|
def CMPGE : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"cmp.ge $dst, p0 = $src1, $src2;;">;
|
||||||
|
def CMPLT : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"cmp.lt $dst, p0 = $src1, $src2;;">;
|
||||||
|
def CMPLE : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"cmp.le $dst, p0 = $src1, $src2;;">;
|
||||||
|
def CMPNE : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"cmp.ne $dst, p0 = $src1, $src2;;">;
|
||||||
|
def CMPLTU : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"cmp.ltu $dst, p0 = $src1, $src2;;">;
|
||||||
|
def CMPGTU : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"cmp.gtu $dst, p0 = $src1, $src2;;">;
|
||||||
|
def CMPLEU : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"cmp.leu $dst, p0 = $src1, $src2;;">;
|
||||||
|
def CMPGEU : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"cmp.geu $dst, p0 = $src1, $src2;;">;
|
||||||
|
|
||||||
|
// and we do the whole thing again for FP compares!
|
||||||
|
def FCMPEQ : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fcmp.eq $dst, p0 = $src1, $src2;;">;
|
||||||
|
def FCMPGT : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fcmp.gt $dst, p0 = $src1, $src2;;">;
|
||||||
|
def FCMPGE : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fcmp.ge $dst, p0 = $src1, $src2;;">;
|
||||||
|
def FCMPLT : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fcmp.lt $dst, p0 = $src1, $src2;;">;
|
||||||
|
def FCMPLE : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fcmp.le $dst, p0 = $src1, $src2;;">;
|
||||||
|
def FCMPNE : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fcmp.neq $dst, p0 = $src1, $src2;;">;
|
||||||
|
def FCMPLTU : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fcmp.ltu $dst, p0 = $src1, $src2;;">;
|
||||||
|
def FCMPGTU : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fcmp.gtu $dst, p0 = $src1, $src2;;">;
|
||||||
|
def FCMPLEU : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fcmp.leu $dst, p0 = $src1, $src2;;">;
|
||||||
|
def FCMPGEU : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fcmp.geu $dst, p0 = $src1, $src2;;">;
|
||||||
|
|
||||||
|
def PCMPEQOR : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2, PR:$qp),
|
||||||
|
"($qp) cmp.eq.or $dst, p0 = $src1, $src2;;">;
|
||||||
|
def PCMPEQUNC : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2, PR:$qp),
|
||||||
|
"($qp) cmp.eq.unc $dst, p0 = $src1, $src2;;">;
|
||||||
|
def PCMPNE : AForm<0x03, 0x0b, (ops PR:$dst, GR:$src1, GR:$src2, PR:$qp),
|
||||||
|
"($qp) cmp.ne $dst, p0 = $src1, $src2;;">;
|
||||||
|
|
||||||
|
// two destinations!
|
||||||
|
def BCMPEQ : AForm<0x03, 0x0b, (ops PR:$dst1, PR:$dst2, GR:$src1, GR:$src2),
|
||||||
|
"cmp.eq $dst1, dst2 = $src1, $src2;;">;
|
||||||
|
|
||||||
|
def ADD : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"add $dst = $src1, $src2;;">;
|
||||||
|
|
||||||
|
def ADDIMM22 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, s21imm:$imm),
|
||||||
|
"add $dst = $imm, $src1;;">;
|
||||||
|
def CADDIMM22 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, s21imm:$imm, PR:$qp),
|
||||||
|
"($qp) add $dst = $imm, $src1;;">;
|
||||||
|
|
||||||
|
let isTwoAddress = 1 in {
|
||||||
|
def TPCADDIMM22 : AForm<0x03, 0x0b,
|
||||||
|
(ops GR:$dst, GR:$src1, s21imm:$imm, PR:$qp),
|
||||||
|
"($qp) add $dst = $imm, $dst;;">;
|
||||||
|
def TPCMPIMM8NE : AForm<0x03, 0x0b,
|
||||||
|
(ops PR:$dst, PR:$src1, s21imm:$imm, GR:$src2, PR:$qp),
|
||||||
|
"($qp) cmp.ne $dst , p0 = $imm, $src2;;">;
|
||||||
|
}
|
||||||
|
|
||||||
|
def SUB : AForm<0x03, 0x0b, (ops GR:$dst, GR:$src1, GR:$src2),
|
||||||
|
"sub $dst = $src1, $src2;;">;
|
||||||
|
|
||||||
|
def ST1 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value),
|
||||||
|
"st1 [$dstPtr] = $value;;">;
|
||||||
|
def ST2 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value),
|
||||||
|
"st2 [$dstPtr] = $value;;">;
|
||||||
|
def ST4 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value),
|
||||||
|
"st4 [$dstPtr] = $value;;">;
|
||||||
|
def ST8 : AForm<0x03, 0x0b, (ops GR:$dstPtr, GR:$value),
|
||||||
|
"st8 [$dstPtr] = $value;;">;
|
||||||
|
|
||||||
|
def LD1 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$srcPtr),
|
||||||
|
"ld1 $dst = [$srcPtr];;">;
|
||||||
|
def LD2 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$srcPtr),
|
||||||
|
"ld2 $dst = [$srcPtr];;">;
|
||||||
|
def LD4 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$srcPtr),
|
||||||
|
"ld4 $dst = [$srcPtr];;">;
|
||||||
|
def LD8 : AForm<0x03, 0x0b, (ops GR:$dst, GR:$srcPtr),
|
||||||
|
"ld8 $dst = [$srcPtr];;">;
|
||||||
|
|
||||||
|
// some FP stuff:
|
||||||
|
def FADD : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fadd $dst = $src1, $src2;;">;
|
||||||
|
def FADDS: AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fadd.s $dst = $src1, $src2;;">;
|
||||||
|
def FSUB : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fsub $dst = $src1, $src2;;">;
|
||||||
|
def FMPY : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
|
||||||
|
"fmpy $dst = $src1, $src2;;">;
|
||||||
|
def FMOV : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
|
||||||
|
"mov $dst = $src;;">; // XXX: there _is_ no fmov
|
||||||
|
def FMA : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
|
||||||
|
"fma $dst = $src1, $src2, $src3;;">;
|
||||||
|
def FNMA : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
|
||||||
|
"fnma $dst = $src1, $src2, $src3;;">;
|
||||||
|
|
||||||
|
def CFMAS1 : AForm<0x03, 0x0b,
|
||||||
|
(ops FP:$dst, FP:$src1, FP:$src2, FP:$src3, PR:$qp),
|
||||||
|
"($qp) fma.s1 $dst = $src1, $src2, $src3;;">;
|
||||||
|
def CFNMAS1 : AForm<0x03, 0x0b,
|
||||||
|
(ops FP:$dst, FP:$src1, FP:$src2, FP:$src3, PR:$qp),
|
||||||
|
"($qp) fnma.s1 $dst = $src1, $src2, $src3;;">;
|
||||||
|
|
||||||
|
// FIXME: we 'explode' FRCPA (which should write two registers) into two
|
||||||
|
// operations that write one each. this is a waste, and is also destroying
|
||||||
|
// f127. not cool.
|
||||||
|
def FRCPAS1FLOAT : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2),
|
||||||
|
"frcpa.s1 $dst , p0 = $src1, $src2;;">;
|
||||||
|
// XXX: this _will_ break things: (f127)
|
||||||
|
def FRCPAS1PREDICATE : AForm<0x03, 0x0b, (ops PR:$dst, FP:$src1, FP:$src2),
|
||||||
|
"frcpa.s1 f127 , $dst = $src1, $src2;; // XXX FIXME!!!!">;
|
||||||
|
|
||||||
|
def XMAL : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src1, FP:$src2, FP:$src3),
|
||||||
|
"xma.l $dst = $src1, $src2, $src3;;">;
|
||||||
|
|
||||||
|
def FCVTXF : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
|
||||||
|
"fcvt.xf $dst = $src;;">;
|
||||||
|
def FCVTXUF : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
|
||||||
|
"fcvt.xuf $dst = $src;;">;
|
||||||
|
def FCVTXUFS1 : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
|
||||||
|
"fcvt.xuf.s1 $dst = $src;;">;
|
||||||
|
def FCVTFX : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
|
||||||
|
"fcvt.fx $dst = $src;;">;
|
||||||
|
def FCVTFXU : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
|
||||||
|
"fcvt.fxu $dst = $src;;">;
|
||||||
|
|
||||||
|
def FCVTFXTRUNC : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
|
||||||
|
"fcvt.fx.trunc $dst = $src;;">;
|
||||||
|
def FCVTFXUTRUNC : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
|
||||||
|
"fcvt.fxu.trunc $dst = $src;;">;
|
||||||
|
|
||||||
|
def FCVTFXTRUNCS1 : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
|
||||||
|
"fcvt.fx.trunc.s1 $dst = $src;;">;
|
||||||
|
def FCVTFXUTRUNCS1 : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
|
||||||
|
"fcvt.fxu.trunc.s1 $dst = $src;;">;
|
||||||
|
|
||||||
|
def FNORMD : AForm<0x03, 0x0b, (ops FP:$dst, FP:$src),
|
||||||
|
"fnorm.d $dst = $src;;">;
|
||||||
|
|
||||||
|
def GETFD : AForm<0x03, 0x0b, (ops GR:$dst, FP:$src),
|
||||||
|
"getf.d $dst = $src;;">;
|
||||||
|
def SETFD : AForm<0x03, 0x0b, (ops FP:$dst, GR:$src),
|
||||||
|
"setf.d $dst = $src;;">;
|
||||||
|
|
||||||
|
def GETFSIG : AForm<0x03, 0x0b, (ops GR:$dst, FP:$src),
|
||||||
|
"getf.sig $dst = $src;;">;
|
||||||
|
def SETFSIG : AForm<0x03, 0x0b, (ops FP:$dst, GR:$src),
|
||||||
|
"setf.sig $dst = $src;;">;
|
||||||
|
|
||||||
|
def LDF4 : AForm<0x03, 0x0b, (ops FP:$dst, GR:$srcPtr),
|
||||||
|
"ldfs $dst = [$srcPtr];;">;
|
||||||
|
def LDF8 : AForm<0x03, 0x0b, (ops FP:$dst, GR:$srcPtr),
|
||||||
|
"ldfd $dst = [$srcPtr];;">;
|
||||||
|
|
||||||
|
def STF4 : AForm<0x03, 0x0b, (ops GR:$dstPtr, FP:$value),
|
||||||
|
"stfs [$dstPtr] = $value;;">;
|
||||||
|
def STF8 : AForm<0x03, 0x0b, (ops GR:$dstPtr, FP:$value),
|
||||||
|
"stfd [$dstPtr] = $value;;">;
|
||||||
|
|
||||||
|
let isTerminator = 1, isBranch = 1 in {
|
||||||
|
def BRLCOND_NOTCALL : RawForm<0x03, 0xb0, (ops PR:$qp, i64imm:$dst),
|
||||||
|
"($qp) brl.cond.sptk $dst;;">;
|
||||||
|
def BRCOND_NOTCALL : RawForm<0x03, 0xb0, (ops PR:$qp, GR:$dst),
|
||||||
|
"($qp) br.cond.sptk $dst;;">;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isCall = 1, isTerminator = 1, isBranch = 1,
|
||||||
|
// all calls clobber non-callee-saved registers, and for now, they are these:
|
||||||
|
Defs = [r2,r3,r8,r9,r10,r11,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24,
|
||||||
|
r25,r26,r27,r28,r29,r30,r31,
|
||||||
|
p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,
|
||||||
|
F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,
|
||||||
|
F32,F33,F34,F35,F36,F37,F38,F39,F40,F41,F42,F43,F44,F45,F46,F47,F48,F49,
|
||||||
|
F50,F51,F52,F53,F54,F55,F56,
|
||||||
|
F57,F58,F59,F60,F61,F62,F63,F64,F65,F66,F67,F68,F69,F70,F71,F72,F73,F74,
|
||||||
|
F75,F76,F77,F78,F79,F80,F81,
|
||||||
|
F82,F83,F84,F85,F86,F87,F88,F89,F90,F91,F92,F93,F94,F95,F96,F97,F98,F99,
|
||||||
|
F100,F101,F102,F103,F104,F105,
|
||||||
|
F106,F107,F108,F109,F110,F111,F112,F113,F114,F115,F116,F117,F118,F119,
|
||||||
|
F120,F121,F122,F123,F124,F125,F126,F127,
|
||||||
|
out0,out1,out2,out3,out4,out5,out6,out7] in {
|
||||||
|
def BRCALL : RawForm<0x03, 0xb0, (ops calltarget:$dst),
|
||||||
|
"br.call.sptk rp = $dst;;">; // FIXME: teach llvm about branch regs?
|
||||||
|
def BRLCOND_CALL : RawForm<0x03, 0xb0, (ops PR:$qp, i64imm:$dst),
|
||||||
|
"($qp) brl.cond.call.sptk $dst;;">;
|
||||||
|
def BRCOND_CALL : RawForm<0x03, 0xb0, (ops PR:$qp, GR:$dst),
|
||||||
|
"($qp) br.cond.call.sptk $dst;;">;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isTerminator = 1, isReturn = 1 in
|
||||||
|
def RET : RawForm<0x03, 0xb0, (ops), "br.ret.sptk.many rp;;">; // return
|
||||||
|
|
||||||
|
|
34
lib/Target/IA64/IA64MachineFunctionInfo.h
Normal file
34
lib/Target/IA64/IA64MachineFunctionInfo.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
//===-- IA64MachineFunctionInfo.h - IA64-specific information ---*- C++ -*-===//
|
||||||
|
//===-- for MachineFunction ---*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file declares IA64-specific per-machine-function information.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef IA64MACHINEFUNCTIONINFO_H
|
||||||
|
#define IA64MACHINEFUNCTIONINFO_H
|
||||||
|
|
||||||
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
//#include "IA64JITInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
class IA64FunctionInfo : public MachineFunctionInfo {
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned outRegsUsed; // how many 'out' registers are used
|
||||||
|
// by this machinefunction? (used to compute the appropriate
|
||||||
|
// entry in the 'alloc' instruction at the top of the
|
||||||
|
// machinefunction)
|
||||||
|
IA64FunctionInfo(MachineFunction& MF) { outRegsUsed=0; };
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
362
lib/Target/IA64/IA64RegisterInfo.cpp
Normal file
362
lib/Target/IA64/IA64RegisterInfo.cpp
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
//===- IA64RegisterInfo.cpp - IA64 Register Information ---------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duraid Madina and is distributed under the
|
||||||
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the IA64 implementation of the MRegisterInfo class. This
|
||||||
|
// file is responsible for the frame pointer elimination optimization on IA64.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "IA64.h"
|
||||||
|
#include "IA64RegisterInfo.h"
|
||||||
|
#include "IA64InstrBuilder.h"
|
||||||
|
#include "IA64MachineFunctionInfo.h"
|
||||||
|
#include "llvm/Constants.h"
|
||||||
|
#include "llvm/Type.h"
|
||||||
|
#include "llvm/CodeGen/ValueTypes.h"
|
||||||
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
#include "llvm/Target/TargetOptions.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
}
|
||||||
|
|
||||||
|
IA64RegisterInfo::IA64RegisterInfo()
|
||||||
|
: IA64GenRegisterInfo(IA64::ADJUSTCALLSTACKDOWN, IA64::ADJUSTCALLSTACKUP) {}
|
||||||
|
|
||||||
|
static const TargetRegisterClass *getClass(unsigned SrcReg) {
|
||||||
|
if (IA64::FPRegisterClass->contains(SrcReg))
|
||||||
|
return IA64::FPRegisterClass;
|
||||||
|
if (IA64::PRRegisterClass->contains(SrcReg))
|
||||||
|
return IA64::PRRegisterClass;
|
||||||
|
|
||||||
|
assert(IA64::GRRegisterClass->contains(SrcReg) &&
|
||||||
|
"PROBLEM: Reg is not FP, predicate or GR!");
|
||||||
|
return IA64::GRRegisterClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IA64RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MI,
|
||||||
|
unsigned SrcReg, int FrameIdx) const {
|
||||||
|
|
||||||
|
if (getClass(SrcReg) == IA64::FPRegisterClass) {
|
||||||
|
BuildMI(MBB, MI, IA64::STF8, 2).addFrameIndex(FrameIdx).addReg(SrcReg);
|
||||||
|
}
|
||||||
|
else if (getClass(SrcReg) == IA64::GRRegisterClass) {
|
||||||
|
BuildMI(MBB, MI, IA64::ST8, 2).addFrameIndex(FrameIdx).addReg(SrcReg);
|
||||||
|
}
|
||||||
|
else if (getClass(SrcReg) == IA64::PRRegisterClass) {
|
||||||
|
/* we use IA64::r2 as a temporary register for doing this hackery. */
|
||||||
|
// first we load 0:
|
||||||
|
BuildMI(MBB, MI, IA64::MOV, 1, IA64::r2).addReg(IA64::r0);
|
||||||
|
// then conditionally add 1:
|
||||||
|
BuildMI(MBB, MI, IA64::CADDIMM22, 3, IA64::r2).addReg(IA64::r2)
|
||||||
|
.addImm(1).addReg(SrcReg);
|
||||||
|
// and then store it to the stack
|
||||||
|
BuildMI(MBB, MI, IA64::ST8, 2).addFrameIndex(FrameIdx).addReg(IA64::r2);
|
||||||
|
} else assert(0 &&
|
||||||
|
"sorry, I don't know how to store this sort of reg in the stack\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void IA64RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MI,
|
||||||
|
unsigned DestReg, int FrameIdx)const{
|
||||||
|
|
||||||
|
if (getClass(DestReg) == IA64::FPRegisterClass) {
|
||||||
|
BuildMI(MBB, MI, IA64::LDF8, 1, DestReg).addFrameIndex(FrameIdx);
|
||||||
|
} else if (getClass(DestReg) == IA64::GRRegisterClass) {
|
||||||
|
BuildMI(MBB, MI, IA64::LD8, 1, DestReg).addFrameIndex(FrameIdx);
|
||||||
|
} else if (getClass(DestReg) == IA64::PRRegisterClass) {
|
||||||
|
// first we load a byte from the stack into r2, our 'predicate hackery'
|
||||||
|
// scratch reg
|
||||||
|
BuildMI(MBB, MI, IA64::LD8, 1, IA64::r2).addFrameIndex(FrameIdx);
|
||||||
|
// then we compare it to zero. If it _is_ zero, compare-not-equal to
|
||||||
|
// r0 gives us 0, which is what we want, so that's nice.
|
||||||
|
BuildMI(MBB, MI, IA64::CMPNE, 2, DestReg).addReg(IA64::r2).addReg(IA64::r0);
|
||||||
|
} else assert(0 &&
|
||||||
|
"sorry, I don't know how to load this sort of reg from the stack\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void IA64RegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MI,
|
||||||
|
unsigned DestReg, unsigned SrcReg,
|
||||||
|
const TargetRegisterClass *RC) const {
|
||||||
|
|
||||||
|
if(RC == IA64::PRRegisterClass ) // if a bool, we use pseudocode
|
||||||
|
// (SrcReg) DestReg = cmp.eq.unc(r0, r0)
|
||||||
|
BuildMI(MBB, MI, IA64::PCMPEQUNC, 1, DestReg).addReg(IA64::r0).addReg(IA64::r0).addReg(SrcReg);
|
||||||
|
else // otherwise, MOV works (for both gen. regs and FP regs)
|
||||||
|
BuildMI(MBB, MI, IA64::MOV, 1, DestReg).addReg(SrcReg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Stack Frame Processing methods
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// hasFP - Return true if the specified function should have a dedicated frame
|
||||||
|
// pointer register. This is true if the function has variable sized allocas or
|
||||||
|
// if frame pointer elimination is disabled.
|
||||||
|
//
|
||||||
|
static bool hasFP(MachineFunction &MF) {
|
||||||
|
return NoFramePointerElim || MF.getFrameInfo()->hasVarSizedObjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IA64RegisterInfo::
|
||||||
|
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator I) const {
|
||||||
|
|
||||||
|
if (hasFP(MF)) {
|
||||||
|
// If we have a frame pointer, turn the adjcallstackup instruction into a
|
||||||
|
// 'sub SP, <amt>' and the adjcallstackdown instruction into 'add SP,
|
||||||
|
// <amt>'
|
||||||
|
MachineInstr *Old = I;
|
||||||
|
unsigned Amount = Old->getOperand(0).getImmedValue();
|
||||||
|
if (Amount != 0) {
|
||||||
|
// We need to keep the stack aligned properly. To do this, we round the
|
||||||
|
// amount of space needed for the outgoing arguments up to the next
|
||||||
|
// alignment boundary.
|
||||||
|
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
|
||||||
|
Amount = (Amount+Align-1)/Align*Align;
|
||||||
|
|
||||||
|
MachineInstr *New;
|
||||||
|
if (Old->getOpcode() == IA64::ADJUSTCALLSTACKDOWN) {
|
||||||
|
New=BuildMI(IA64::ADDIMM22, 2, IA64::r12).addReg(IA64::r12)
|
||||||
|
.addImm(-Amount);
|
||||||
|
} else {
|
||||||
|
assert(Old->getOpcode() == IA64::ADJUSTCALLSTACKUP);
|
||||||
|
New=BuildMI(IA64::ADDIMM22, 2, IA64::r12).addReg(IA64::r12)
|
||||||
|
.addImm(Amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace the pseudo instruction with a new instruction...
|
||||||
|
MBB.insert(I, New);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MBB.erase(I);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IA64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
|
||||||
|
unsigned i = 0;
|
||||||
|
MachineInstr &MI = *II;
|
||||||
|
MachineBasicBlock &MBB = *MI.getParent();
|
||||||
|
MachineFunction &MF = *MBB.getParent();
|
||||||
|
|
||||||
|
bool FP = hasFP(MF);
|
||||||
|
|
||||||
|
while (!MI.getOperand(i).isFrameIndex()) {
|
||||||
|
++i;
|
||||||
|
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
|
||||||
|
}
|
||||||
|
|
||||||
|
int FrameIndex = MI.getOperand(i).getFrameIndex();
|
||||||
|
|
||||||
|
// choose a base register: ( hasFP? framepointer : stack pointer )
|
||||||
|
unsigned BaseRegister = FP ? IA64::r15 : IA64::r12;
|
||||||
|
// Add the base register
|
||||||
|
MI.SetMachineOperandReg(i, BaseRegister);
|
||||||
|
|
||||||
|
// Now add the frame object offset to the offset from r1.
|
||||||
|
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
|
||||||
|
|
||||||
|
// If we're not using a Frame Pointer that has been set to the value of the
|
||||||
|
// SP before having the stack size subtracted from it, then add the stack size
|
||||||
|
// to Offset to get the correct offset.
|
||||||
|
Offset += MF.getFrameInfo()->getStackSize();
|
||||||
|
|
||||||
|
// XXX: we use 'r22' as another hack+slash temporary register here :(
|
||||||
|
if ( Offset <= 8191 && Offset >= -8192) { // smallish offset
|
||||||
|
//fix up the old:
|
||||||
|
MI.SetMachineOperandReg(i, IA64::r22);
|
||||||
|
//insert the new
|
||||||
|
MachineInstr* nMI=BuildMI(IA64::ADDIMM22, 2, IA64::r22)
|
||||||
|
.addReg(BaseRegister).addSImm(Offset);
|
||||||
|
MBB.insert(II, nMI);
|
||||||
|
} else { // it's big
|
||||||
|
//fix up the old:
|
||||||
|
MI.SetMachineOperandReg(i, IA64::r22);
|
||||||
|
MachineInstr* nMI;
|
||||||
|
nMI=BuildMI(IA64::MOVLSI32, 1, IA64::r22).addSImm(Offset);
|
||||||
|
MBB.insert(II, nMI);
|
||||||
|
nMI=BuildMI(IA64::ADD, 2, IA64::r22).addReg(BaseRegister)
|
||||||
|
.addReg(IA64::r22);
|
||||||
|
MBB.insert(II, nMI);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void IA64RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||||
|
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
||||||
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
MachineInstr *MI;
|
||||||
|
bool FP = hasFP(MF);
|
||||||
|
|
||||||
|
// first, we handle the 'alloc' instruction, that should be right up the
|
||||||
|
// top of any function
|
||||||
|
static const unsigned RegsInOrder[96] = { // there are 96 GPRs the
|
||||||
|
// RSE worries about
|
||||||
|
IA64::r32, IA64::r33, IA64::r34, IA64::r35,
|
||||||
|
IA64::r36, IA64::r37, IA64::r38, IA64::r39, IA64::r40, IA64::r41,
|
||||||
|
IA64::r42, IA64::r43, IA64::r44, IA64::r45, IA64::r46, IA64::r47,
|
||||||
|
IA64::r48, IA64::r49, IA64::r50, IA64::r51, IA64::r52, IA64::r53,
|
||||||
|
IA64::r54, IA64::r55, IA64::r56, IA64::r57, IA64::r58, IA64::r59,
|
||||||
|
IA64::r60, IA64::r61, IA64::r62, IA64::r63, IA64::r64, IA64::r65,
|
||||||
|
IA64::r66, IA64::r67, IA64::r68, IA64::r69, IA64::r70, IA64::r71,
|
||||||
|
IA64::r72, IA64::r73, IA64::r74, IA64::r75, IA64::r76, IA64::r77,
|
||||||
|
IA64::r78, IA64::r79, IA64::r80, IA64::r81, IA64::r82, IA64::r83,
|
||||||
|
IA64::r84, IA64::r85, IA64::r86, IA64::r87, IA64::r88, IA64::r89,
|
||||||
|
IA64::r90, IA64::r91, IA64::r92, IA64::r93, IA64::r94, IA64::r95,
|
||||||
|
IA64::r96, IA64::r97, IA64::r98, IA64::r99, IA64::r100, IA64::r101,
|
||||||
|
IA64::r102, IA64::r103, IA64::r104, IA64::r105, IA64::r106, IA64::r107,
|
||||||
|
IA64::r108, IA64::r109, IA64::r110, IA64::r111, IA64::r112, IA64::r113,
|
||||||
|
IA64::r114, IA64::r115, IA64::r116, IA64::r117, IA64::r118, IA64::r119,
|
||||||
|
IA64::r120, IA64::r121, IA64::r122, IA64::r123, IA64::r124, IA64::r125,
|
||||||
|
IA64::r126, IA64::r127 };
|
||||||
|
|
||||||
|
unsigned numStackedGPRsUsed=0;
|
||||||
|
for(int i=0; i<96; i++) {
|
||||||
|
if(MF.isPhysRegUsed(RegsInOrder[i]))
|
||||||
|
numStackedGPRsUsed=i+1; // (i+1 and not ++ - consider fn(fp, fp, int)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned numOutRegsUsed=MF.getInfo<IA64FunctionInfo>()->outRegsUsed;
|
||||||
|
|
||||||
|
// XXX FIXME : this code should be a bit more reliable (in case there _isn't_ a pseudo_alloc in the MBB)
|
||||||
|
unsigned dstRegOfPseudoAlloc;
|
||||||
|
for(MBBI = MBB.begin(); /*MBBI->getOpcode() != IA64::PSEUDO_ALLOC*/; ++MBBI) {
|
||||||
|
assert(MBBI != MBB.end());
|
||||||
|
if(MBBI->getOpcode() == IA64::PSEUDO_ALLOC) {
|
||||||
|
dstRegOfPseudoAlloc=MBBI->getOperand(0).getReg();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MI=BuildMI(IA64::ALLOC,5).addReg(dstRegOfPseudoAlloc).addImm(0).\
|
||||||
|
addImm(numStackedGPRsUsed).addImm(numOutRegsUsed).addImm(0);
|
||||||
|
MBB.insert(MBBI, MI);
|
||||||
|
|
||||||
|
// Get the number of bytes to allocate from the FrameInfo
|
||||||
|
unsigned NumBytes = MFI->getStackSize();
|
||||||
|
|
||||||
|
if (MFI->hasCalls() && !FP) {
|
||||||
|
// We reserve argument space for call sites in the function immediately on
|
||||||
|
// entry to the current function. This eliminates the need for add/sub
|
||||||
|
// brackets around call sites.
|
||||||
|
NumBytes += MFI->getMaxCallFrameSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(FP)
|
||||||
|
NumBytes += 8; // reserve space for the old FP
|
||||||
|
|
||||||
|
// Do we need to allocate space on the stack?
|
||||||
|
if (NumBytes == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Add 16 bytes at the bottom of the stack (scratch area)
|
||||||
|
// and round the size to a multiple of the alignment.
|
||||||
|
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
|
||||||
|
unsigned Size = 16 + (FP ? 8 : 0);
|
||||||
|
NumBytes = (NumBytes+Size+Align-1)/Align*Align;
|
||||||
|
|
||||||
|
// Update frame info to pretend that this is part of the stack...
|
||||||
|
MFI->setStackSize(NumBytes);
|
||||||
|
|
||||||
|
// adjust stack pointer: r12 -= numbytes
|
||||||
|
if (NumBytes <= 8191) {
|
||||||
|
MI=BuildMI(IA64::ADDIMM22, 2, IA64::r12).addReg(IA64::r12).addImm(-NumBytes);
|
||||||
|
MBB.insert(MBBI, MI);
|
||||||
|
} else { // we use r22 as a scratch register here
|
||||||
|
MI=BuildMI(IA64::MOVLSI32, 1, IA64::r22).addSImm(-NumBytes);
|
||||||
|
// FIXME: MOVLSI32 expects a _u_32imm
|
||||||
|
MBB.insert(MBBI, MI); // first load the decrement into r22
|
||||||
|
MI=BuildMI(IA64::ADD, 2, IA64::r12).addReg(IA64::r12).addReg(IA64::r22);
|
||||||
|
MBB.insert(MBBI, MI); // then add (subtract) it to r12 (stack ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// now if we need to, save the old FP and set the new
|
||||||
|
if (FP) {
|
||||||
|
MI = BuildMI(IA64::ST8, 2).addReg(IA64::r12).addReg(IA64::r15);
|
||||||
|
MBB.insert(MBBI, MI);
|
||||||
|
// this must be the last instr in the prolog ? (XXX: why??)
|
||||||
|
MI = BuildMI(IA64::MOV, 1, IA64::r15).addReg(IA64::r12);
|
||||||
|
MBB.insert(MBBI, MI);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void IA64RegisterInfo::emitEpilogue(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB) const {
|
||||||
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||||
|
MachineInstr *MI;
|
||||||
|
assert(MBBI->getOpcode() == IA64::RET &&
|
||||||
|
"Can only insert epilog into returning blocks");
|
||||||
|
|
||||||
|
bool FP = hasFP(MF);
|
||||||
|
|
||||||
|
// Get the number of bytes allocated from the FrameInfo...
|
||||||
|
unsigned NumBytes = MFI->getStackSize();
|
||||||
|
|
||||||
|
//now if we need to, restore the old FP
|
||||||
|
if (FP)
|
||||||
|
{
|
||||||
|
//copy the FP into the SP (discards allocas)
|
||||||
|
MI=BuildMI(IA64::MOV, 1, IA64::r12).addReg(IA64::r15);
|
||||||
|
MBB.insert(MBBI, MI);
|
||||||
|
//restore the FP
|
||||||
|
MI=BuildMI(IA64::LD8, 1, IA64::r15).addReg(IA64::r15);
|
||||||
|
MBB.insert(MBBI, MI);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NumBytes != 0)
|
||||||
|
{
|
||||||
|
if (NumBytes <= 8191) {
|
||||||
|
MI=BuildMI(IA64::ADDIMM22, 2, IA64::r12).addReg(IA64::r12).addImm(NumBytes);
|
||||||
|
MBB.insert(MBBI, MI);
|
||||||
|
} else {
|
||||||
|
MI=BuildMI(IA64::MOVLI32, 1, IA64::r22).addImm(NumBytes);
|
||||||
|
MBB.insert(MBBI, MI);
|
||||||
|
MI=BuildMI(IA64::ADD, 2, IA64::r12).addReg(IA64::r12).addReg(IA64::r22);
|
||||||
|
MBB.insert(MBBI, MI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "IA64GenRegisterInfo.inc"
|
||||||
|
|
||||||
|
const TargetRegisterClass*
|
||||||
|
IA64RegisterInfo::getRegClassForType(const Type* Ty) const {
|
||||||
|
switch (Ty->getTypeID()) {
|
||||||
|
default: assert(0 && "Invalid type to getClass!");
|
||||||
|
case Type::LongTyID:
|
||||||
|
case Type::ULongTyID:
|
||||||
|
case Type::BoolTyID:
|
||||||
|
case Type::SByteTyID:
|
||||||
|
case Type::UByteTyID:
|
||||||
|
case Type::ShortTyID:
|
||||||
|
case Type::UShortTyID:
|
||||||
|
case Type::IntTyID:
|
||||||
|
case Type::UIntTyID:
|
||||||
|
case Type::PointerTyID: return &GRInstance;
|
||||||
|
|
||||||
|
case Type::FloatTyID:
|
||||||
|
case Type::DoubleTyID: return &FPInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
55
lib/Target/IA64/IA64RegisterInfo.h
Normal file
55
lib/Target/IA64/IA64RegisterInfo.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//===- IA64RegisterInfo.h - IA64 Register Information Impl ------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duraid Madina and is distributed under the
|
||||||
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file contains the IA64 implementation of the MRegisterInfo class.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef IA64REGISTERINFO_H
|
||||||
|
#define IA64REGISTERINFO_H
|
||||||
|
|
||||||
|
#include "llvm/Target/MRegisterInfo.h"
|
||||||
|
#include "IA64GenRegisterInfo.h.inc"
|
||||||
|
|
||||||
|
namespace llvm { class llvm::Type; }
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
|
||||||
|
struct IA64RegisterInfo : public IA64GenRegisterInfo {
|
||||||
|
IA64RegisterInfo();
|
||||||
|
const TargetRegisterClass* getRegClassForType(const Type* Ty) const;
|
||||||
|
|
||||||
|
/// Code Generation virtual methods...
|
||||||
|
void storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MI,
|
||||||
|
unsigned SrcReg, int FrameIndex) const;
|
||||||
|
|
||||||
|
void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MI,
|
||||||
|
unsigned DestReg, int FrameIndex) const;
|
||||||
|
|
||||||
|
void copyRegToReg(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MI,
|
||||||
|
unsigned DestReg, unsigned SrcReg,
|
||||||
|
const TargetRegisterClass *RC) const;
|
||||||
|
|
||||||
|
void eliminateCallFramePseudoInstr(MachineFunction &MF,
|
||||||
|
MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator MI) const;
|
||||||
|
|
||||||
|
void eliminateFrameIndex(MachineBasicBlock::iterator MI) const;
|
||||||
|
|
||||||
|
void emitPrologue(MachineFunction &MF) const;
|
||||||
|
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
291
lib/Target/IA64/IA64RegisterInfo.td
Normal file
291
lib/Target/IA64/IA64RegisterInfo.td
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
//===- IA64RegisterInfo.td - Describe the IA64 Register File ----*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duraid Madina and is distributed under the
|
||||||
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file describes the IA64 register file, defining the registers
|
||||||
|
// themselves, aliases between the registers, and the register classes built
|
||||||
|
// out of the registers.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Register definitions...
|
||||||
|
//
|
||||||
|
|
||||||
|
class IA64Register<string n> : Register<n> {
|
||||||
|
let Namespace = "IA64";
|
||||||
|
}
|
||||||
|
|
||||||
|
// GR - One of 128 32-bit general registers
|
||||||
|
class GR<bits<7> num, string n> : IA64Register<n> {
|
||||||
|
field bits<7> Num = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FP - One of 128 82-bit floating-point registers
|
||||||
|
class FP<bits<7> num, string n> : IA64Register<n> {
|
||||||
|
field bits<7> Num = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PR - One of 64 1-bit predicate registers
|
||||||
|
class PR<bits<6> num, string n> : IA64Register<n> {
|
||||||
|
field bits<6> Num = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* general registers */
|
||||||
|
def r0 : GR< 0, "r0">; def r1 : GR< 1, "r1">;
|
||||||
|
def r2 : GR< 2, "r2">; def r3 : GR< 3, "r3">;
|
||||||
|
def r4 : GR< 4, "r4">; def r5 : GR< 5, "r5">;
|
||||||
|
def r6 : GR< 6, "r6">; def r7 : GR< 7, "r7">;
|
||||||
|
def r8 : GR< 8, "r8">; def r9 : GR< 9, "r9">;
|
||||||
|
def r10 : GR< 10, "r10">; def r11 : GR< 11, "r11">;
|
||||||
|
def r12 : GR< 12, "r12">; def r13 : GR< 13, "r13">;
|
||||||
|
def r14 : GR< 14, "r14">; def r15 : GR< 15, "r15">;
|
||||||
|
def r16 : GR< 16, "r16">; def r17 : GR< 17, "r17">;
|
||||||
|
def r18 : GR< 18, "r18">; def r19 : GR< 19, "r19">;
|
||||||
|
def r20 : GR< 20, "r20">; def r21 : GR< 21, "r21">;
|
||||||
|
def r22 : GR< 22, "r22">; def r23 : GR< 23, "r23">;
|
||||||
|
def r24 : GR< 24, "r24">; def r25 : GR< 25, "r25">;
|
||||||
|
def r26 : GR< 26, "r26">; def r27 : GR< 27, "r27">;
|
||||||
|
def r28 : GR< 28, "r28">; def r29 : GR< 29, "r29">;
|
||||||
|
def r30 : GR< 30, "r30">; def r31 : GR< 31, "r31">;
|
||||||
|
def r32 : GR< 32, "r32">; def r33 : GR< 33, "r33">;
|
||||||
|
def r34 : GR< 34, "r34">; def r35 : GR< 35, "r35">;
|
||||||
|
def r36 : GR< 36, "r36">; def r37 : GR< 37, "r37">;
|
||||||
|
def r38 : GR< 38, "r38">; def r39 : GR< 39, "r39">;
|
||||||
|
def r40 : GR< 40, "r40">; def r41 : GR< 41, "r41">;
|
||||||
|
def r42 : GR< 42, "r42">; def r43 : GR< 43, "r43">;
|
||||||
|
def r44 : GR< 44, "r44">; def r45 : GR< 45, "r45">;
|
||||||
|
def r46 : GR< 46, "r46">; def r47 : GR< 47, "r47">;
|
||||||
|
def r48 : GR< 48, "r48">; def r49 : GR< 49, "r49">;
|
||||||
|
def r50 : GR< 50, "r50">; def r51 : GR< 51, "r51">;
|
||||||
|
def r52 : GR< 52, "r52">; def r53 : GR< 53, "r53">;
|
||||||
|
def r54 : GR< 54, "r54">; def r55 : GR< 55, "r55">;
|
||||||
|
def r56 : GR< 56, "r56">; def r57 : GR< 57, "r57">;
|
||||||
|
def r58 : GR< 58, "r58">; def r59 : GR< 59, "r59">;
|
||||||
|
def r60 : GR< 60, "r60">; def r61 : GR< 61, "r61">;
|
||||||
|
def r62 : GR< 62, "r62">; def r63 : GR< 63, "r63">;
|
||||||
|
def r64 : GR< 64, "r64">; def r65 : GR< 65, "r65">;
|
||||||
|
def r66 : GR< 66, "r66">; def r67 : GR< 67, "r67">;
|
||||||
|
def r68 : GR< 68, "r68">; def r69 : GR< 69, "r69">;
|
||||||
|
def r70 : GR< 70, "r70">; def r71 : GR< 71, "r71">;
|
||||||
|
def r72 : GR< 72, "r72">; def r73 : GR< 73, "r73">;
|
||||||
|
def r74 : GR< 74, "r74">; def r75 : GR< 75, "r75">;
|
||||||
|
def r76 : GR< 76, "r76">; def r77 : GR< 77, "r77">;
|
||||||
|
def r78 : GR< 78, "r78">; def r79 : GR< 79, "r79">;
|
||||||
|
def r80 : GR< 80, "r80">; def r81 : GR< 81, "r81">;
|
||||||
|
def r82 : GR< 82, "r82">; def r83 : GR< 83, "r83">;
|
||||||
|
def r84 : GR< 84, "r84">; def r85 : GR< 85, "r85">;
|
||||||
|
def r86 : GR< 86, "r86">; def r87 : GR< 87, "r87">;
|
||||||
|
def r88 : GR< 88, "r88">; def r89 : GR< 89, "r89">;
|
||||||
|
def r90 : GR< 90, "r90">; def r91 : GR< 91, "r91">;
|
||||||
|
def r92 : GR< 92, "r92">; def r93 : GR< 93, "r93">;
|
||||||
|
def r94 : GR< 94, "r94">; def r95 : GR< 95, "r95">;
|
||||||
|
def r96 : GR< 96, "r96">; def r97 : GR< 97, "r97">;
|
||||||
|
def r98 : GR< 98, "r98">; def r99 : GR< 99, "r99">;
|
||||||
|
def r100 : GR< 100, "r100">; def r101 : GR< 101, "r101">;
|
||||||
|
def r102 : GR< 102, "r102">; def r103 : GR< 103, "r103">;
|
||||||
|
def r104 : GR< 104, "r104">; def r105 : GR< 105, "r105">;
|
||||||
|
def r106 : GR< 106, "r106">; def r107 : GR< 107, "r107">;
|
||||||
|
def r108 : GR< 108, "r108">; def r109 : GR< 109, "r109">;
|
||||||
|
def r110 : GR< 110, "r110">; def r111 : GR< 111, "r111">;
|
||||||
|
def r112 : GR< 112, "r112">; def r113 : GR< 113, "r113">;
|
||||||
|
def r114 : GR< 114, "r114">; def r115 : GR< 115, "r115">;
|
||||||
|
def r116 : GR< 116, "r116">; def r117 : GR< 117, "r117">;
|
||||||
|
def r118 : GR< 118, "r118">; def r119 : GR< 119, "r119">;
|
||||||
|
def r120 : GR< 120, "r120">; def r121 : GR< 121, "r121">;
|
||||||
|
def r122 : GR< 122, "r122">; def r123 : GR< 123, "r123">;
|
||||||
|
def r124 : GR< 124, "r124">; def r125 : GR< 125, "r125">;
|
||||||
|
def r126 : GR< 126, "r126">; def r127 : GR< 127, "r127">;
|
||||||
|
|
||||||
|
/* floating-point registers */
|
||||||
|
def F0 : FP< 0, "f0">; def F1 : FP< 1, "f1">;
|
||||||
|
def F2 : FP< 2, "f2">; def F3 : FP< 3, "f3">;
|
||||||
|
def F4 : FP< 4, "f4">; def F5 : FP< 5, "f5">;
|
||||||
|
def F6 : FP< 6, "f6">; def F7 : FP< 7, "f7">;
|
||||||
|
def F8 : FP< 8, "f8">; def F9 : FP< 9, "f9">;
|
||||||
|
def F10 : FP< 10, "f10">; def F11 : FP< 11, "f11">;
|
||||||
|
def F12 : FP< 12, "f12">; def F13 : FP< 13, "f13">;
|
||||||
|
def F14 : FP< 14, "f14">; def F15 : FP< 15, "f15">;
|
||||||
|
def F16 : FP< 16, "f16">; def F17 : FP< 17, "f17">;
|
||||||
|
def F18 : FP< 18, "f18">; def F19 : FP< 19, "f19">;
|
||||||
|
def F20 : FP< 20, "f20">; def F21 : FP< 21, "f21">;
|
||||||
|
def F22 : FP< 22, "f22">; def F23 : FP< 23, "f23">;
|
||||||
|
def F24 : FP< 24, "f24">; def F25 : FP< 25, "f25">;
|
||||||
|
def F26 : FP< 26, "f26">; def F27 : FP< 27, "f27">;
|
||||||
|
def F28 : FP< 28, "f28">; def F29 : FP< 29, "f29">;
|
||||||
|
def F30 : FP< 30, "f30">; def F31 : FP< 31, "f31">;
|
||||||
|
def F32 : FP< 32, "f32">; def F33 : FP< 33, "f33">;
|
||||||
|
def F34 : FP< 34, "f34">; def F35 : FP< 35, "f35">;
|
||||||
|
def F36 : FP< 36, "f36">; def F37 : FP< 37, "f37">;
|
||||||
|
def F38 : FP< 38, "f38">; def F39 : FP< 39, "f39">;
|
||||||
|
def F40 : FP< 40, "f40">; def F41 : FP< 41, "f41">;
|
||||||
|
def F42 : FP< 42, "f42">; def F43 : FP< 43, "f43">;
|
||||||
|
def F44 : FP< 44, "f44">; def F45 : FP< 45, "f45">;
|
||||||
|
def F46 : FP< 46, "f46">; def F47 : FP< 47, "f47">;
|
||||||
|
def F48 : FP< 48, "f48">; def F49 : FP< 49, "f49">;
|
||||||
|
def F50 : FP< 50, "f50">; def F51 : FP< 51, "f51">;
|
||||||
|
def F52 : FP< 52, "f52">; def F53 : FP< 53, "f53">;
|
||||||
|
def F54 : FP< 54, "f54">; def F55 : FP< 55, "f55">;
|
||||||
|
def F56 : FP< 56, "f56">; def F57 : FP< 57, "f57">;
|
||||||
|
def F58 : FP< 58, "f58">; def F59 : FP< 59, "f59">;
|
||||||
|
def F60 : FP< 60, "f60">; def F61 : FP< 61, "f61">;
|
||||||
|
def F62 : FP< 62, "f62">; def F63 : FP< 63, "f63">;
|
||||||
|
def F64 : FP< 64, "f64">; def F65 : FP< 65, "f65">;
|
||||||
|
def F66 : FP< 66, "f66">; def F67 : FP< 67, "f67">;
|
||||||
|
def F68 : FP< 68, "f68">; def F69 : FP< 69, "f69">;
|
||||||
|
def F70 : FP< 70, "f70">; def F71 : FP< 71, "f71">;
|
||||||
|
def F72 : FP< 72, "f72">; def F73 : FP< 73, "f73">;
|
||||||
|
def F74 : FP< 74, "f74">; def F75 : FP< 75, "f75">;
|
||||||
|
def F76 : FP< 76, "f76">; def F77 : FP< 77, "f77">;
|
||||||
|
def F78 : FP< 78, "f78">; def F79 : FP< 79, "f79">;
|
||||||
|
def F80 : FP< 80, "f80">; def F81 : FP< 81, "f81">;
|
||||||
|
def F82 : FP< 82, "f82">; def F83 : FP< 83, "f83">;
|
||||||
|
def F84 : FP< 84, "f84">; def F85 : FP< 85, "f85">;
|
||||||
|
def F86 : FP< 86, "f86">; def F87 : FP< 87, "f87">;
|
||||||
|
def F88 : FP< 88, "f88">; def F89 : FP< 89, "f89">;
|
||||||
|
def F90 : FP< 90, "f90">; def F91 : FP< 91, "f91">;
|
||||||
|
def F92 : FP< 92, "f92">; def F93 : FP< 93, "f93">;
|
||||||
|
def F94 : FP< 94, "f94">; def F95 : FP< 95, "f95">;
|
||||||
|
def F96 : FP< 96, "f96">; def F97 : FP< 97, "f97">;
|
||||||
|
def F98 : FP< 98, "f98">; def F99 : FP< 99, "f99">;
|
||||||
|
def F100 : FP< 100, "f100">; def F101 : FP< 101, "f101">;
|
||||||
|
def F102 : FP< 102, "f102">; def F103 : FP< 103, "f103">;
|
||||||
|
def F104 : FP< 104, "f104">; def F105 : FP< 105, "f105">;
|
||||||
|
def F106 : FP< 106, "f106">; def F107 : FP< 107, "f107">;
|
||||||
|
def F108 : FP< 108, "f108">; def F109 : FP< 109, "f109">;
|
||||||
|
def F110 : FP< 110, "f110">; def F111 : FP< 111, "f111">;
|
||||||
|
def F112 : FP< 112, "f112">; def F113 : FP< 113, "f113">;
|
||||||
|
def F114 : FP< 114, "f114">; def F115 : FP< 115, "f115">;
|
||||||
|
def F116 : FP< 116, "f116">; def F117 : FP< 117, "f117">;
|
||||||
|
def F118 : FP< 118, "f118">; def F119 : FP< 119, "f119">;
|
||||||
|
def F120 : FP< 120, "f120">; def F121 : FP< 121, "f121">;
|
||||||
|
def F122 : FP< 122, "f122">; def F123 : FP< 123, "f123">;
|
||||||
|
def F124 : FP< 124, "f124">; def F125 : FP< 125, "f125">;
|
||||||
|
def F126 : FP< 126, "f126">; def F127 : FP< 127, "f127">;
|
||||||
|
|
||||||
|
/* predicate registers */
|
||||||
|
def p0 : PR< 0, "p0">; def p1 : PR< 1, "p1">;
|
||||||
|
def p2 : PR< 2, "p2">; def p3 : PR< 3, "p3">;
|
||||||
|
def p4 : PR< 4, "p4">; def p5 : PR< 5, "p5">;
|
||||||
|
def p6 : PR< 6, "p6">; def p7 : PR< 7, "p7">;
|
||||||
|
def p8 : PR< 8, "p8">; def p9 : PR< 9, "p9">;
|
||||||
|
def p10 : PR< 10, "p10">; def p11 : PR< 11, "p11">;
|
||||||
|
def p12 : PR< 12, "p12">; def p13 : PR< 13, "p13">;
|
||||||
|
def p14 : PR< 14, "p14">; def p15 : PR< 15, "p15">;
|
||||||
|
def p16 : PR< 16, "p16">; def p17 : PR< 17, "p17">;
|
||||||
|
def p18 : PR< 18, "p18">; def p19 : PR< 19, "p19">;
|
||||||
|
def p20 : PR< 20, "p20">; def p21 : PR< 21, "p21">;
|
||||||
|
def p22 : PR< 22, "p22">; def p23 : PR< 23, "p23">;
|
||||||
|
def p24 : PR< 24, "p24">; def p25 : PR< 25, "p25">;
|
||||||
|
def p26 : PR< 26, "p26">; def p27 : PR< 27, "p27">;
|
||||||
|
def p28 : PR< 28, "p28">; def p29 : PR< 29, "p29">;
|
||||||
|
def p30 : PR< 30, "p30">; def p31 : PR< 31, "p31">;
|
||||||
|
def p32 : PR< 32, "p32">; def p33 : PR< 33, "p33">;
|
||||||
|
def p34 : PR< 34, "p34">; def p35 : PR< 35, "p35">;
|
||||||
|
def p36 : PR< 36, "p36">; def p37 : PR< 37, "p37">;
|
||||||
|
def p38 : PR< 38, "p38">; def p39 : PR< 39, "p39">;
|
||||||
|
def p40 : PR< 40, "p40">; def p41 : PR< 41, "p41">;
|
||||||
|
def p42 : PR< 42, "p42">; def p43 : PR< 43, "p43">;
|
||||||
|
def p44 : PR< 44, "p44">; def p45 : PR< 45, "p45">;
|
||||||
|
def p46 : PR< 46, "p46">; def p47 : PR< 47, "p47">;
|
||||||
|
def p48 : PR< 48, "p48">; def p49 : PR< 49, "p49">;
|
||||||
|
def p50 : PR< 50, "p50">; def p51 : PR< 51, "p51">;
|
||||||
|
def p52 : PR< 52, "p52">; def p53 : PR< 53, "p53">;
|
||||||
|
def p54 : PR< 54, "p54">; def p55 : PR< 55, "p55">;
|
||||||
|
def p56 : PR< 56, "p56">; def p57 : PR< 57, "p57">;
|
||||||
|
def p58 : PR< 58, "p58">; def p59 : PR< 59, "p59">;
|
||||||
|
def p60 : PR< 60, "p60">; def p61 : PR< 61, "p61">;
|
||||||
|
def p62 : PR< 62, "p62">; def p63 : PR< 63, "p63">;
|
||||||
|
|
||||||
|
// XXX : this is temporary, we'll eventually have the output registers
|
||||||
|
// in the general purpose register class too?
|
||||||
|
def out0 : GR<0, "out0">; def out1 : GR<1, "out1">;
|
||||||
|
def out2 : GR<2, "out2">; def out3 : GR<3, "out3">;
|
||||||
|
def out4 : GR<4, "out4">; def out5 : GR<5, "out5">;
|
||||||
|
def out6 : GR<6, "out6">; def out7 : GR<7, "out7">;
|
||||||
|
|
||||||
|
// application (special) registers:
|
||||||
|
|
||||||
|
// " previous function state" application register
|
||||||
|
def AR_PFS : GR<0, "ar.pfs">;
|
||||||
|
|
||||||
|
// "return pointer" (this is really branch register b0)
|
||||||
|
def rp : GR<0, "rp">;
|
||||||
|
// branch reg 6
|
||||||
|
def B6 : GR<0, "b6">;
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Register Class Definitions... now that we have all of the pieces, define the
|
||||||
|
// top-level register classes. The order specified in the register list is
|
||||||
|
// implicitly defined to be the register allocation order.
|
||||||
|
//
|
||||||
|
|
||||||
|
// these are the scratch (+stacked) general registers
|
||||||
|
// ZERO (r0), GP (r1), SP (r12), ThreadP (r13) are not here...
|
||||||
|
// FIXME/XXX we also reserve a frame pointer (r15)
|
||||||
|
// FIXME/XXX we also reserve r2 for spilling/filling predicates
|
||||||
|
// in IA64RegisterInfo.cpp
|
||||||
|
// FIXME/XXX we also reserve r22 for calculating addresses
|
||||||
|
// in IA64RegisterInfo.cpp
|
||||||
|
|
||||||
|
def GR : RegisterClass<i64, 64,
|
||||||
|
[/*r2,*/ r3,
|
||||||
|
r8, r9, r10, r11, r14, /*r15, */
|
||||||
|
r16, r17, r18, r19, r20, r21, /*r22,*/ r23,
|
||||||
|
r24, r25, r26, r27, r28, r29, r30, r31,
|
||||||
|
r32, r33, r34, r35, r36, r37, r38, r39,
|
||||||
|
r40, r41, r42, r43, r44, r45, r46, r47,
|
||||||
|
r48, r49, r50, r51, r52, r53, r54, r55,
|
||||||
|
r56, r57, r58, r59, r60, r61, r62, r63,
|
||||||
|
r64, r65, r66, r67, r68, r69, r70, r71,
|
||||||
|
r72, r73, r74, r75, r76, r77, r78, r79,
|
||||||
|
r80, r81, r82, r83, r84, r85, r86, r87,
|
||||||
|
r88, r89, r90, r91, r92, r93, r94, r95,
|
||||||
|
r96, r97, r98, r99, r100, r101, r102, r103,
|
||||||
|
r104, r105, r106, r107, r108, r109, r110, r111,
|
||||||
|
r112, r113, r114, r115, r116, r117, r118, r119,
|
||||||
|
r120, r121, r122, r123, r124, r125, r126, r127]>;
|
||||||
|
|
||||||
|
// these are the scratch (+stacked) FP registers
|
||||||
|
// ZERO (F0) and ONE (F1) are not here
|
||||||
|
def FP : RegisterClass<f64, 64,
|
||||||
|
[F6, F7,
|
||||||
|
F8, F9, F10, F11, F12, F13, F14, F15,
|
||||||
|
F32, F33, F34, F35, F36, F37, F38, F39,
|
||||||
|
F40, F41, F42, F43, F44, F45, F46, F47,
|
||||||
|
F48, F49, F50, F51, F52, F53, F54, F55,
|
||||||
|
F56, F57, F58, F59, F60, F61, F62, F63,
|
||||||
|
F64, F65, F66, F67, F68, F69, F70, F71,
|
||||||
|
F72, F73, F74, F75, F76, F77, F78, F79,
|
||||||
|
F80, F81, F82, F83, F84, F85, F86, F87,
|
||||||
|
F88, F89, F90, F91, F92, F93, F94, F95,
|
||||||
|
F96, F97, F98, F99, F100, F101, F102, F103,
|
||||||
|
F104, F105, F106, F107, F108, F109, F110, F111,
|
||||||
|
F112, F113, F114, F115, F116, F117, F118, F119,
|
||||||
|
F120, F121, F122, F123, F124, F125, F126, F127]>;
|
||||||
|
|
||||||
|
// these are the predicate registers, p0 (1/TRUE) is not here
|
||||||
|
def PR : RegisterClass<i1, 64,
|
||||||
|
|
||||||
|
// for now, let's be wimps and only have the scratch predicate regs
|
||||||
|
[p6, p7, p8, p9, p10, p11, p12, p13, p14, p15]> {
|
||||||
|
let Size = 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
[p1, p2, p3, p4, p5, p6, p7,
|
||||||
|
p8, p9, p10, p11, p12, p13, p14, p15,
|
||||||
|
p16, p17, p18, p19, p20, p21, p22, p23,
|
||||||
|
p24, p25, p26, p27, p28, p29, p30, p31,
|
||||||
|
p32, p33, p34, p35, p36, p37, p38, p39,
|
||||||
|
p40, p41, p42, p43, p44, p45, p46, p47,
|
||||||
|
p48, p49, p50, p51, p52, p53, p54, p55,
|
||||||
|
p56, p57, p58, p59, p60, p61, p62, p63]>;
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
134
lib/Target/IA64/IA64TargetMachine.cpp
Normal file
134
lib/Target/IA64/IA64TargetMachine.cpp
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
//===-- IA64TargetMachine.cpp - Define TargetMachine for IA64 -------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duraid Madina and is distributed under the
|
||||||
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file defines the IA64 specific subclass of TargetMachine.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "IA64TargetMachine.h"
|
||||||
|
#include "IA64.h"
|
||||||
|
#include "llvm/Module.h"
|
||||||
|
#include "llvm/PassManager.h"
|
||||||
|
#include "llvm/CodeGen/IntrinsicLowering.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
|
#include "llvm/CodeGen/Passes.h"
|
||||||
|
#include "llvm/Target/TargetOptions.h"
|
||||||
|
#include "llvm/Target/TargetMachineRegistry.h"
|
||||||
|
#include "llvm/Transforms/Scalar.h"
|
||||||
|
#include "llvm/Support/CommandLine.h"
|
||||||
|
#include "llvm/ADT/Statistic.h"
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
/// IA64TargetMachineModule - Note that this is used on hosts that cannot link
|
||||||
|
/// in a library unless there are references into the library. In particular,
|
||||||
|
/// it seems that it is not possible to get things to work on Win32 without
|
||||||
|
/// this. Though it is unused, do not remove it.
|
||||||
|
extern "C" int IA64TargetMachineModule;
|
||||||
|
int IA64TargetMachineModule = 0;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
cl::opt<bool> DisableOutput("disable-ia64-llc-output", cl::Hidden,
|
||||||
|
cl::desc("Disable the IA64 asm printer, for use "
|
||||||
|
"when profiling the code generator."));
|
||||||
|
|
||||||
|
// Register the target.
|
||||||
|
RegisterTarget<IA64TargetMachine> X("ia64", " IA-64 (Itanium)");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned IA64TargetMachine::compileTimeMatchQuality() {
|
||||||
|
#if defined(__ia64__) || defined(__IA64__)
|
||||||
|
return 50;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned IA64TargetMachine::getModuleMatchQuality(const Module &M) {
|
||||||
|
// we match [iI][aA]*64
|
||||||
|
bool seenIA64=false;
|
||||||
|
std::string TT = M.getTargetTriple();
|
||||||
|
|
||||||
|
if (TT.size() >= 4) {
|
||||||
|
if( (TT[0]=='i' || TT[0]=='I') &&
|
||||||
|
(TT[1]=='a' || TT[1]=='A') ) {
|
||||||
|
for(unsigned int i=2; i<(TT.size()-1); i++)
|
||||||
|
if(TT[i]=='6' && TT[i+1]=='4')
|
||||||
|
seenIA64=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(seenIA64)
|
||||||
|
return 50; // strong match
|
||||||
|
}
|
||||||
|
|
||||||
|
return compileTimeMatchQuality()/2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// IA64TargetMachine ctor - Create an LP64 architecture model
|
||||||
|
///
|
||||||
|
IA64TargetMachine::IA64TargetMachine(const Module &M, IntrinsicLowering *IL)
|
||||||
|
: TargetMachine("IA64", IL, true),
|
||||||
|
FrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0) { // FIXME? check this stuff
|
||||||
|
}
|
||||||
|
|
||||||
|
// addPassesToEmitAssembly - We currently use all of the same passes as the JIT
|
||||||
|
// does to emit statically compiled machine code.
|
||||||
|
bool IA64TargetMachine::addPassesToEmitAssembly(PassManager &PM,
|
||||||
|
std::ostream &Out) {
|
||||||
|
// FIXME: Implement efficient support for garbage collection intrinsics.
|
||||||
|
PM.add(createLowerGCPass());
|
||||||
|
|
||||||
|
// FIXME: Implement the invoke/unwind instructions!
|
||||||
|
PM.add(createLowerInvokePass());
|
||||||
|
|
||||||
|
// FIXME: Implement the switch instruction in the instruction selector!
|
||||||
|
PM.add(createLowerSwitchPass());
|
||||||
|
|
||||||
|
// Make sure that no unreachable blocks are instruction selected.
|
||||||
|
PM.add(createUnreachableBlockEliminationPass());
|
||||||
|
|
||||||
|
PM.add(createIA64PatternInstructionSelector(*this));
|
||||||
|
|
||||||
|
/* XXX not yet. ;)
|
||||||
|
// Run optional SSA-based machine code optimizations next...
|
||||||
|
if (!NoSSAPeephole)
|
||||||
|
PM.add(createIA64SSAPeepholeOptimizerPass());
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Print the instruction selected machine code...
|
||||||
|
if (PrintMachineCode)
|
||||||
|
PM.add(createMachineFunctionPrinterPass(&std::cerr));
|
||||||
|
|
||||||
|
// Perform register allocation to convert to a concrete IA64 representation
|
||||||
|
PM.add(createRegisterAllocator());
|
||||||
|
|
||||||
|
if (PrintMachineCode)
|
||||||
|
PM.add(createMachineFunctionPrinterPass(&std::cerr));
|
||||||
|
|
||||||
|
if (PrintMachineCode)
|
||||||
|
PM.add(createMachineFunctionPrinterPass(&std::cerr));
|
||||||
|
|
||||||
|
// Insert prolog/epilog code. Eliminate abstract frame index references...
|
||||||
|
PM.add(createPrologEpilogCodeInserter());
|
||||||
|
|
||||||
|
/* XXX no, not just yet */
|
||||||
|
// PM.add(createIA64PeepholeOptimizerPass());
|
||||||
|
|
||||||
|
if (PrintMachineCode) // Print the register-allocated code
|
||||||
|
PM.add(createIA64CodePrinterPass(std::cerr, *this));
|
||||||
|
|
||||||
|
if (!DisableOutput)
|
||||||
|
PM.add(createIA64CodePrinterPass(Out, *this));
|
||||||
|
|
||||||
|
// Delete machine code for this function
|
||||||
|
PM.add(createMachineCodeDeleter());
|
||||||
|
|
||||||
|
return false; // success!
|
||||||
|
}
|
||||||
|
|
48
lib/Target/IA64/IA64TargetMachine.h
Normal file
48
lib/Target/IA64/IA64TargetMachine.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//===-- IA64TargetMachine.h - Define TargetMachine for IA64 ---*- C++ -*---===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file was developed by Duraid Madina and is distributed under the
|
||||||
|
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file declares the IA64 specific subclass of TargetMachine.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef IA64TARGETMACHINE_H
|
||||||
|
#define IA64TARGETMACHINE_H
|
||||||
|
|
||||||
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
|
#include "llvm/PassManager.h"
|
||||||
|
#include "IA64InstrInfo.h"
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class IntrinsicLowering;
|
||||||
|
|
||||||
|
class IA64TargetMachine : public TargetMachine {
|
||||||
|
IA64InstrInfo InstrInfo;
|
||||||
|
TargetFrameInfo FrameInfo;
|
||||||
|
//IA64JITInfo JITInfo;
|
||||||
|
public:
|
||||||
|
IA64TargetMachine(const Module &M, IntrinsicLowering *IL);
|
||||||
|
|
||||||
|
virtual const IA64InstrInfo *getInstrInfo() const { return &InstrInfo; }
|
||||||
|
virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
|
||||||
|
virtual const MRegisterInfo *getRegisterInfo() const {
|
||||||
|
return &InstrInfo.getRegisterInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
|
||||||
|
|
||||||
|
static unsigned getModuleMatchQuality(const Module &M);
|
||||||
|
static unsigned compileTimeMatchQuality(void);
|
||||||
|
|
||||||
|
};
|
||||||
|
} // End llvm namespace
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
17
lib/Target/IA64/Makefile
Normal file
17
lib/Target/IA64/Makefile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
##===- lib/Target/IA64/Makefile -----------------------------*- Makefile -*-===##
|
||||||
|
# The LLVM Compiler Infrastructure
|
||||||
|
#
|
||||||
|
# This file was developed by Duraid Madina and is distributed under the
|
||||||
|
# University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||||
|
#
|
||||||
|
##===----------------------------------------------------------------------===##
|
||||||
|
LEVEL = ../../..
|
||||||
|
LIBRARYNAME = LLVMIA64
|
||||||
|
TARGET = IA64
|
||||||
|
# Make sure that tblgen is run, first thing.
|
||||||
|
BUILT_SOURCES = IA64GenRegisterInfo.h.inc IA64GenRegisterNames.inc \
|
||||||
|
IA64GenRegisterInfo.inc IA64GenInstrNames.inc \
|
||||||
|
IA64GenInstrInfo.inc IA64GenAsmWriter.inc
|
||||||
|
|
||||||
|
include $(LEVEL)/Makefile.common
|
||||||
|
|
98
lib/Target/IA64/README
Normal file
98
lib/Target/IA64/README
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
*** README for the LLVM IA64 Backend "Version 0.01" - March 18, 2004
|
||||||
|
*** Quote for this version:
|
||||||
|
|
||||||
|
"Kaori and Hitomi are naughty!!"
|
||||||
|
|
||||||
|
|
||||||
|
Congratulations, you have found:
|
||||||
|
|
||||||
|
****************************************************************
|
||||||
|
* @@@ @@@ @@@ @@@ @@@@@@@@@@ *
|
||||||
|
* @@@ @@@ @@@ @@@ @@@@@@@@@@@ *
|
||||||
|
* @@! @@! @@! @@@ @@! @@! @@! *
|
||||||
|
* !@! !@! !@! @!@ !@! !@! !@! *
|
||||||
|
* @!! @!! @!@ !@! @!! !!@ @!@ *
|
||||||
|
* !!! !!! !@! !!! !@! ! !@! *
|
||||||
|
* !!: !!: :!: !!: !!: !!: *
|
||||||
|
* :!: :!: ::!!:! :!: :!: *
|
||||||
|
* :: :::: :: :::: :::: ::: :: *
|
||||||
|
* : :: : : : :: : : : : : *
|
||||||
|
* *
|
||||||
|
* *
|
||||||
|
* @@@@@@ @@@ @@@ @@@ @@@@@@ @@@@@@ @@@ *
|
||||||
|
* @@@@@@@@ @@@@ @@@ @@@ @@@@@@@@ @@@@@@@ @@@@ *
|
||||||
|
* @@! @@@ @@!@!@@@ @@! @@! @@@ !@@ @@!@! *
|
||||||
|
* !@! @!@ !@!!@!@! !@! !@! @!@ !@! !@!!@! *
|
||||||
|
* @!@ !@! @!@ !!@! !!@ @!@!@!@! !!@@!@! @!! @!! *
|
||||||
|
* !@! !!! !@! !!! !!! !!!@!!!! @!!@!!!! !!! !@! *
|
||||||
|
* !!: !!! !!: !!! !!: !!: !!! !:! !:! :!!:!:!!: *
|
||||||
|
* :!: !:! :!: !:! :!: :!: !:! :!: !:! !:::!!::: *
|
||||||
|
* ::::: :: :: :: :: :: ::: :::: ::: ::: *
|
||||||
|
* : : : :: : : : : : :: : : ::: *
|
||||||
|
* *
|
||||||
|
****************************************************************
|
||||||
|
* Bow down, bow down, before the power of IA64! Or be crushed, *
|
||||||
|
* be crushed, by its jolly registers of doom!! *
|
||||||
|
****************************************************************
|
||||||
|
|
||||||
|
DEVELOPMENT PLAN:
|
||||||
|
|
||||||
|
_ you are 2005 maybe 2005 2006 2006 and
|
||||||
|
/ here | | | beyond
|
||||||
|
v v v v |
|
||||||
|
v
|
||||||
|
CLEAN UP ADD INSTRUCTION ADD PLAY WITH
|
||||||
|
INSTRUCTION --> SCHEDULING AND --> JIT --> DYNAMIC --> FUTURE WORK
|
||||||
|
SELECTION BUNDLING SUPPORT REOPTIMIZATION
|
||||||
|
|
||||||
|
DISCLAIMER AND PROMISE:
|
||||||
|
|
||||||
|
As of the time of this release, you are probably better off using Intel C/C++
|
||||||
|
or GCC. The performance of the code emitted right now is, in a word,
|
||||||
|
terrible. Check back in a few months - the story will be different then,
|
||||||
|
I guarantee it.
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
|
||||||
|
- clean up and thoroughly test the isel patterns.
|
||||||
|
- fix up floating point
|
||||||
|
(nb http://gcc.gnu.org/wiki?pagename=ia64%20floating%20point )
|
||||||
|
- bundling!
|
||||||
|
(we will avoid the mess that is:
|
||||||
|
http://gcc.gnu.org/ml/gcc/2003-12/msg00832.html )
|
||||||
|
- instruction scheduling (yep)
|
||||||
|
- write truly inspirational documentation
|
||||||
|
- if-conversion (predicate database/knowledge? etc etc)
|
||||||
|
- counted loop support
|
||||||
|
- make integer + FP mul/div more clever (we have fixed pseudocode atm)
|
||||||
|
- track and use comparison complements
|
||||||
|
|
||||||
|
INFO:
|
||||||
|
|
||||||
|
- we are strictly LP64 here, no support for ILP32 on HP-UX. Linux users
|
||||||
|
don't need to worry about this.
|
||||||
|
- i have instruction scheduling/bundling pseudocode, that really works
|
||||||
|
(has been tested, albeit at the perl-script level).
|
||||||
|
so, before you go write your own, send me an email!
|
||||||
|
|
||||||
|
KNOWN DEFECTS AT THE CURRENT TIME:
|
||||||
|
|
||||||
|
- no varargs
|
||||||
|
- alloca doesn't work (indeed, stack frame layout is bogus)
|
||||||
|
- no support for big-endian environments
|
||||||
|
- (not really the backend, but...) the CFE has some issues on IA64.
|
||||||
|
these will probably be fixed soon.
|
||||||
|
|
||||||
|
ACKNOWLEDGEMENTS:
|
||||||
|
|
||||||
|
- Chris Lattner (x100)
|
||||||
|
- Other LLVM developers ("hey, that looks familiar")
|
||||||
|
|
||||||
|
CONTACT:
|
||||||
|
|
||||||
|
- You can email me at duraid@octopus.com.au. If you find a small bug,
|
||||||
|
just email me. If you find a big bug, please file a bug report
|
||||||
|
in bugzilla! http://llvm.cs.uiuc.edu is your one stop shop for all
|
||||||
|
things LLVM.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user