Header files for the target architecture description and for instruction

selection, and instances of these for the SPARC.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Vikram S. Adve 2001-07-21 12:39:03 +00:00
parent c4651a91c0
commit 23ee550765
5 changed files with 1362 additions and 0 deletions

View File

@ -0,0 +1,339 @@
/* $Id$ -*-c++-*-
****************************************************************************
* File:
* InstrForest.h
*
* Purpose:
* Convert SSA graph to instruction trees for instruction selection.
*
* Strategy:
* The basic idea is that we would like to group instructions into a single
* tree if one or more of them might be potentially combined into a single
* complex instruction in the target machine.
* Since this grouping is completely machine-independent, it is as
* aggressive as possible. In particular, we group two instructions
* O and I if:
* (1) Instruction O computes an operand of instruction I, and
* (2) O and I are part of the same basic block, and
* (3) O has only a single use, viz., I.
*
* History:
* 6/28/01 - Vikram Adve - Created
***************************************************************************/
#ifndef LLVM_CODEGEN_INSTRFOREST_H
#define LLVM_CODEGEN_INSTRFOREST_H
/*
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
C
C The following types and macros are visible to the C code generated
C by BURG.
*/
extern "C" {
//-------------------------------------------------------------------------
// Data types needed by BURG and implemented by us
//-------------------------------------------------------------------------
typedef int OpLabel;
typedef int StateLabel;
typedef struct BasicTreeNode_struct {
BasicTreeNode_struct* leftChild;
BasicTreeNode_struct* rightChild;
BasicTreeNode_struct* parent;
OpLabel opLabel;
StateLabel state;
void* treeNodePtr; /* points to the C++ tree node object
* that "contains" this node */
} BasicTreeNode;
//-------------------------------------------------------------------------
// Declarations of data and functions created by BURG
//-------------------------------------------------------------------------
# ifdef __STDC__
# define ARGS(x) x
# else
# define ARGS(x) ()
# endif
extern short* burm_nts[];
extern StateLabel burm_label ARGS((BasicTreeNode* p));
extern StateLabel burm_state ARGS((OpLabel op,
StateLabel leftState,
StateLabel rightState));
extern StateLabel burm_rule ARGS((StateLabel state,
int goalNT));
extern BasicTreeNode** burm_kids ARGS((BasicTreeNode* p,
int eruleno,
BasicTreeNode* kids[]));
extern void printcover ARGS((BasicTreeNode*, int, int));
extern void printtree ARGS((BasicTreeNode*));
extern int treecost ARGS((BasicTreeNode*, int, int));
extern void printMatches ARGS((BasicTreeNode*));
}
/* end extern "C" */
/*CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC*/
#ifdef __cplusplus
//************************** System Include Files **************************/
#include <bool.h>
#include <hash_map>
#include <hash_set>
//*************************** User Include Files ***************************/
#include "llvm/Support/Unique.h"
#include "llvm/Instruction.h"
//************************* Opaque Declarations ****************************/
class Value;
class Instruction;
class ConstPoolVal;
class BasicBlock;
class Method;
class InstrTreeNode;
class InstrForest;
//************************ Exported Constants ******************************/
//--------------------------------------------------------------------------
// OpLabel values for special-case nodes created for instruction selection.
// All op-labels not defined here are identical to the instruction
// opcode returned by Instruction::getInstType()
//--------------------------------------------------------------------------
const int InvalidOp = -1;
const int VRegListOp = 97;
const int VRegNodeOp = 98;
const int ConstantNodeOp= 99;
const int LabelNodeOp = 100;
const int RetValueOp = 100 + Instruction::Ret;
const int BrCondOp = 100 + Instruction::Br;
const int SetCCOp = 100 + Instruction::SetEQ;
const int AllocaN = 100 + Instruction::Alloca; // 121
const int LoadIdx = 100 + Instruction::Load; // 122
const int GetElemPtrIdx= 100 + Instruction::GetElementPtr; // 124
const int ToBoolTy = 100 + Instruction::Cast; // 126
const int ToUByteTy = ToBoolTy + 1;
const int ToSByteTy = ToBoolTy + 2;
const int ToUShortTy = ToBoolTy + 3;
const int ToShortTy = ToBoolTy + 4;
const int ToUIntTy = ToBoolTy + 5;
const int ToIntTy = ToBoolTy + 6;
const int ToULongTy = ToBoolTy + 7;
const int ToLongTy = ToBoolTy + 8;
const int ToFloatTy = ToBoolTy + 9;
const int ToDoubleTy = ToBoolTy + 10;
const int ToArrayTy = ToBoolTy + 11;
const int ToPointerTy = ToBoolTy + 12;
//************************ Exported Data Types *****************************/
struct ptrHashFunc {
inline size_t operator()(const void* const& p) const
{
// Copied from body of hash<unsigned long>::operator().
// I cannot figure out how to invoke that without an object
return (size_t) ((const unsigned long) p);
}
};
//------------------------------------------------------------------------
// class InstrTreeNode
//
// A single tree node in the instruction tree used for
// instruction selection via BURG.
//------------------------------------------------------------------------
inline InstrTreeNode*
MainTreeNode(BasicTreeNode* node) {
return (InstrTreeNode*) node->treeNodePtr;
}
class InstrTreeNode: public Unique {
public:
enum InstrTreeNodeType { NTInstructionNode,
NTVRegListNode,
NTVRegNode,
NTConstNode,
NTLabelNode };
protected:
BasicTreeNode basicNode;
InstrTreeNodeType treeNodeType;
Value* val;
public:
/*ctor*/ InstrTreeNode (InstrTreeNodeType nodeType,
Value* _val);
/*dtor*/ virtual ~InstrTreeNode ();
BasicTreeNode* getBasicNode () { return &basicNode; }
InstrTreeNodeType getNodeType () const { return treeNodeType; }
Value* getValue () const { return val; }
inline OpLabel getOpLabel () const { return basicNode.opLabel; }
inline InstrTreeNode* leftChild () const {
return (InstrTreeNode*)
(basicNode.leftChild? basicNode.leftChild->treeNodePtr : NULL);
}
// If right child is a list node, recursively get its *left* child
inline InstrTreeNode* rightChild () const {
return (InstrTreeNode*)
(basicNode.rightChild
? (MainTreeNode(basicNode.rightChild)->getOpLabel() == VRegListOp
? MainTreeNode(basicNode.rightChild)->leftChild()
: MainTreeNode(basicNode.rightChild))
: NULL);
}
inline InstrTreeNode* parent () const {
return (InstrTreeNode*)
(basicNode.parent? basicNode.parent->treeNodePtr : NULL);
}
void dump (int dumpChildren,
int indent) const;
protected:
virtual void dumpNode (int indent) const = 0;
friend class InstrForest;
};
class InstructionNode: public InstrTreeNode {
public:
/*ctor*/ InstructionNode (Instruction* _instr);
Instruction* getInstruction () const { return (Instruction*) val; }
void reverseBinaryArgumentOrder();
protected:
virtual void dumpNode (int indent) const;
};
class VRegListNode: public InstrTreeNode {
public:
/*ctor*/ VRegListNode ();
protected:
virtual void dumpNode (int indent) const;
};
class VRegNode: public InstrTreeNode {
public:
/*ctor*/ VRegNode (Value* _val);
protected:
virtual void dumpNode (int indent) const;
};
class ConstantNode: public InstrTreeNode {
public:
/*ctor*/ ConstantNode (ConstPoolVal* constVal);
ConstPoolVal* getConstVal () const { return (ConstPoolVal*) val;}
protected:
virtual void dumpNode ( int indent) const;
};
class LabelNode: public InstrTreeNode {
public:
/*ctor*/ LabelNode (BasicBlock* _bblock);
BasicBlock* getBasicBlock () const { return (BasicBlock*) val;}
protected:
virtual void dumpNode (int indent) const;
};
//------------------------------------------------------------------------
// class InstrForest
//
// A forest of instruction trees, usually for a single method.
//
// Methods:
// buildTreesForMethod() Builds the forest of trees for a method
// getTreeNodeForInstr() Returns the tree node for an Instruction
// getRootSet() Returns a set of root nodes for all the trees
//
//------------------------------------------------------------------------
class InstrForest :
public Unique,
private hash_map<const Instruction*, InstructionNode*, ptrHashFunc > {
private:
hash_set<InstructionNode*, ptrHashFunc > treeRoots;
public:
/*ctor*/ InstrForest () {}
/*dtor*/ ~InstrForest () {}
void buildTreesForMethod (Method *method);
inline InstructionNode*
getTreeNodeForInstr(Instruction* instr)
{
return (*this)[instr];
}
inline const hash_set<InstructionNode*, ptrHashFunc>&
getRootSet() const {
return treeRoots;
}
void dump () const;
private:
//
// Private methods for buidling the instruction forest
//
void setLeftChild (InstrTreeNode* parent,
InstrTreeNode* child);
void setRightChild (InstrTreeNode* parent,
InstrTreeNode* child);
void setParent (InstrTreeNode* child,
InstrTreeNode* parent);
void noteTreeNodeForInstr (Instruction* instr,
InstructionNode* treeNode);
InstructionNode* buildTreeForInstruction(Instruction* instr);
};
//---------------------------------------------------------------------------
#endif /* #ifdef __cplusplus */
#endif /* #ifndef INSTRFOREST_H */

View File

@ -0,0 +1,121 @@
// $Id$ -*-c++-*-
//***************************************************************************
// File:
// InstrSelection.h
//
// Purpose:
//
// History:
// 7/02/01 - Vikram Adve - Created
//***************************************************************************
#ifndef LLVM_CODEGEN_INSTR_SELECTION_H
#define LLVM_CODEGEN_INSTR_SELECTION_H
//************************** System Include Files **************************/
//*************************** User Include Files ***************************/
#include "llvm/Instruction.h"
//************************* Opaque Declarations ****************************/
class CompileContext;
class Instruction;
class Method;
class InstrForest;
class MachineInstruction;
class TmpInstruction;
//************************ Exported Constants ******************************/
const int DEBUG_INSTR_TREES = 2;
const int DEBUG_BURG_TREES = 5;
//****************** External Function Prototypes **************************/
//---------------------------------------------------------------------------
// GLOBAL data and an external function that must be implemented
// for each architecture.
//---------------------------------------------------------------------------
const unsigned MAX_INSTR_PER_VMINSTR = 8;
extern unsigned GetInstructionsByRule (InstructionNode* subtreeRoot,
int ruleForNode,
short* nts,
CompileContext& ccontext,
MachineInstr** minstrVec);
extern bool ThisIsAChainRule (int eruleno);
//************************ Exported Data Types *****************************/
//---------------------------------------------------------------------------
// Function: SelectInstructionsForMethod
//
// Purpose:
// Entry point for instruction selection using BURG.
// Returns true if instruction selection failed, false otherwise.
// Implemented in machine-specific instruction selection file.
//---------------------------------------------------------------------------
bool SelectInstructionsForMethod (Method* method,
CompileContext& ccontext);
// Debugging function to print the generated instructions
void PrintMachineInstructions (Method* method,
CompileContext& ccontext);
//---------------------------------------------------------------------------
// Function: FoldGetElemChain
//
// Purpose:
// Fold a chain of GetElementPtr instructions into an equivalent
// (Pointer, IndexVector) pair. Returns the pointer Value, and
// stores the resulting IndexVector in argument chainIdxVec.
//---------------------------------------------------------------------------
Value* FoldGetElemChain (const InstructionNode* getElemInstrNode,
vector<ConstPoolVal*>& chainIdxVec);
//---------------------------------------------------------------------------
// class TmpInstruction
//
// This class represents temporary intermediate values
// used within the machine code for a VM instruction
//---------------------------------------------------------------------------
class TmpInstruction : public Instruction {
TmpInstruction (const TmpInstruction &CI) : Instruction(CI.getType(), CI.getOpcode()) {
Operands.reserve(2);
Operands.push_back(Use(Operands[0], this));
Operands.push_back(Use(Operands[1], this));
}
public:
TmpInstruction(OtherOps Opcode, Value *S1, Value* S2, const string &Name = "")
: Instruction(S1->getType(), Opcode, Name)
{
assert(Opcode == UserOp1 && "Tmp instruction opcode invalid!");
Operands.reserve(S2? 2 : 1);
Operands.push_back(Use(S1, this));
if (S2)
Operands.push_back(Use(S2, this));
}
virtual Instruction *clone() const { return new TmpInstruction(*this); }
virtual const char *getOpcodeName() const {
return "userOp1";
}
};
//**************************************************************************/
#endif

View File

@ -0,0 +1,370 @@
// $Id$ -*-c++-*-
//***************************************************************************
// File:
// MachineInstr.h
//
// Purpose:
//
//
// Strategy:
//
// History:
// 7/2/01 - Vikram Adve - Created
//**************************************************************************/
#ifndef LLVM_CODEGEN_MACHINEINSTR_H
#define LLVM_CODEGEN_MACHINEINSTR_H
//************************** System Include Files **************************/
#include <string>
#include <vector>
//*************************** User Include Files ***************************/
#include "llvm/Tools/DataTypes.h"
#include "llvm/Instruction.h"
#include "llvm/Support/Unique.h"
#include "llvm/Codegen/TargetMachine.h"
//************************* Opaque Declarations ****************************/
class Value;
class InstrTreeNode;
class InstructionNode;
class MachineInstr;
class MachineInstrInfo;
class MachineOperand;
//************************ Exported Data Types *****************************/
//---------------------------------------------------------------------------
// class MachineOperand
//
// Purpose:
// Representation of each machine instruction operand.
// This class is designed so that you can allocate a vector of operands
// first and initialize each one later.
//
// E.g, for this VM instruction:
// ptr = alloca type, numElements
// we generate 2 machine instructions on the SPARC:
//
// mul Constant, Numelements -> Reg
// add %sp, Reg -> Ptr
//
// Each instruction has 3 operands, listed above. Of those:
// - Reg, NumElements, and Ptr are of operand type MO_Register.
// - Constant is of operand type MO_SignExtendedImmed on the SPARC.
//
// For the register operands, the virtual register type is as follows:
//
// - Reg will be of virtual register type MO_MInstrVirtualReg. The field
// MachineInstr* minstr will point to the instruction that computes reg.
//
// - %sp will be of virtual register type MO_MachineReg.
// The field regNum identifies the machine register.
//
// - NumElements will be of virtual register type MO_VirtualReg.
// The field Value* value identifies the value.
//
// - Ptr will also be of virtual register type MO_VirtualReg.
// Again, the field Value* value identifies the value.
//
//---------------------------------------------------------------------------
class MachineOperand {
public:
friend ostream& operator<<(ostream& os, const MachineOperand& mop);
public:
enum MachineOperandType {
MO_Register,
MO_CCRegister,
MO_SignExtendedImmed,
MO_UnextendedImmed,
MO_PCRelativeDisp,
};
enum VirtualRegisterType {
MO_VirtualReg, // virtual register for *value
MO_MachineReg // pre-assigned machine register `regNum'
};
MachineOperandType machineOperandType;
VirtualRegisterType vregType;
Value* value; // BasicBlockVal for a label operand.
// ConstantVal for a non-address immediate.
// Virtual register for a register operand.
unsigned int regNum; // register number for an explicit register
int64_t immedVal; // constant value for an explicit constant
/*ctor*/ MachineOperand ();
/*ctor*/ MachineOperand (MachineOperandType operandType,
Value* _val);
/*copy ctor*/ MachineOperand (const MachineOperand&);
/*dtor*/ ~MachineOperand () {}
// These functions are provided so that a vector of operands can be
// statically allocated and individual ones can be initialized later.
//
void Initialize (MachineOperandType operandType,
Value* _val);
void InitializeConst (MachineOperandType operandType,
int64_t intValue);
void InitializeReg (unsigned int regNum);
};
inline
MachineOperand::MachineOperand()
: machineOperandType(MO_Register),
vregType(MO_VirtualReg),
value(NULL),
regNum(0),
immedVal(0)
{}
inline
MachineOperand::MachineOperand(MachineOperandType operandType,
Value* _val)
: machineOperandType(operandType),
vregType(MO_VirtualReg),
value(_val),
regNum(0),
immedVal(0)
{}
inline
MachineOperand::MachineOperand(const MachineOperand& mo)
: machineOperandType(mo.machineOperandType),
vregType(mo.vregType),
value(mo.value),
regNum(mo.regNum),
immedVal(mo.immedVal)
{
}
inline void
MachineOperand::Initialize(MachineOperandType operandType,
Value* _val)
{
machineOperandType = operandType;
value = _val;
}
inline void
MachineOperand::InitializeConst(MachineOperandType operandType,
int64_t intValue)
{
machineOperandType = operandType;
value = NULL;
immedVal = intValue;
}
inline void
MachineOperand::InitializeReg(unsigned int _regNum)
{
machineOperandType = MO_Register;
vregType = MO_MachineReg;
value = NULL;
regNum = _regNum;
}
//---------------------------------------------------------------------------
// class MachineInstr
//
// Purpose:
// Representation of each machine instruction.
//
// MachineOpCode must be an enum, defined separately for each target.
// E.g., It is defined in SparcInstructionSelection.h for the SPARC.
// The array MachineInstrInfo TargetMachineInstrInfo[] objects
// (indexed by opCode) provides information about each target instruction.
//
// opCodeMask is used to record variants of an instruction.
// E.g., each branch instruction on SPARC has 2 flags (i.e., 4 variants):
// ANNUL: if 1: Annul delay slot instruction.
// PREDICT-NOT-TAKEN: if 1: predict branch not taken.
// Instead of creating 4 different opcodes for BNZ, we create a single
// opcode and set bits in opCodeMask for each of these flags.
//---------------------------------------------------------------------------
class MachineInstr : public Unique {
private:
MachineOpCode opCode;
OpCodeMask opCodeMask; // extra bits for variants of an opcode
vector<MachineOperand> operands; // operand 0 is the result
public:
/*ctor*/ MachineInstr (MachineOpCode _opCode,
OpCodeMask _opCodeMask = 0x0);
/*dtor*/ virtual ~MachineInstr ();
const MachineOpCode getOpCode () const;
unsigned int getNumOperands () const;
const MachineOperand& getOperand (unsigned int i) const;
void dump (unsigned int indent = 0);
public:
friend ostream& operator<<(ostream& os, const MachineInstr& minstr);
public:
// Access to set the operands when building the machine instruction
void SetMachineOperand(unsigned int i,
MachineOperand::MachineOperandType operandType,
Value* _val);
void SetMachineOperand(unsigned int i,
MachineOperand::MachineOperandType operandType,
int64_t intValue);
void SetMachineOperand(unsigned int i,
unsigned int regNum);
};
inline const MachineOpCode
MachineInstr::getOpCode() const
{
return opCode;
}
inline unsigned int
MachineInstr::getNumOperands() const
{
assert(operands.size() == TargetMachineInstrInfo[opCode].numOperands);
return operands.size();
}
inline const MachineOperand&
MachineInstr::getOperand(unsigned int i) const
{
return operands[i];
}
//---------------------------------------------------------------------------
// class MachineInstructionsForVMInstr
//
// Purpose:
// Representation of the sequence of machine instructions created
// for a single VM instruction. Additionally records any temporary
// "values" used as intermediate values in this sequence.
// Note that such values should be treated as pure SSA values with
// no interpretation of their operands (i.e., as a TmpInstruction object
// which actually represents such a value).
//
//---------------------------------------------------------------------------
class MachineCodeForVMInstr: public vector<MachineInstr*>
{
private:
vector<Value*> tempVec;
public:
/*ctor*/ MachineCodeForVMInstr () {}
/*ctor*/ ~MachineCodeForVMInstr ();
const vector<Value*>&
getTempValues () const { return tempVec; }
void addTempValue (Value* val)
{ tempVec.push_back(val); }
// dropAllReferences() - This function drops all references within
// temporary (hidden) instructions created in implementing the original
// VM intruction. This ensures there are no remaining "uses" within
// these hidden instructions, before the values of a method are freed.
//
// Make this inline because it has to be called from class Instruction
// and inlining it avoids a serious circurality in link order.
inline void dropAllReferences() {
for (unsigned i=0, N=tempVec.size(); i < N; i++)
if (tempVec[i]->getValueType() == Value::InstructionVal)
((Instruction*) tempVec[i])->dropAllReferences();
}
};
inline
MachineCodeForVMInstr::~MachineCodeForVMInstr()
{
// Free the Value objects created to hold intermediate values
for (unsigned i=0, N=tempVec.size(); i < N; i++)
delete tempVec[i];
// Free the MachineInstr objects allocated, if any.
for (unsigned i=0, N=this->size(); i < N; i++)
delete (*this)[i];
}
//---------------------------------------------------------------------------
// Target-independent utility routines for creating machine instructions
//---------------------------------------------------------------------------
//------------------------------------------------------------------------
// Function Set2OperandsFromInstr
// Function Set3OperandsFromInstr
//
// For the common case of 2- and 3-operand arithmetic/logical instructions,
// set the m/c instr. operands directly from the VM instruction's operands.
// Check whether the first or second operand is 0 and can use a dedicated
// "0" register.
// Check whether the second operand should use an immediate field or register.
// (First and third operands are never immediates for such instructions.)
//
// Arguments:
// canDiscardResult: Specifies that the result operand can be discarded
// by using the dedicated "0"
//
// op1position, op2position and resultPosition: Specify in which position
// in the machine instruction the 3 operands (arg1, arg2
// and result) should go.
//
// RETURN VALUE: unsigned int flags, where
// flags & 0x01 => operand 1 is constant and needs a register
// flags & 0x02 => operand 2 is constant and needs a register
//------------------------------------------------------------------------
void Set2OperandsFromInstr (MachineInstr* minstr,
InstructionNode* vmInstrNode,
const TargetMachine& targetMachine,
bool canDiscardResult = false,
int op1Position = 0,
int resultPosition = 1);
void Set3OperandsFromInstr (MachineInstr* minstr,
InstructionNode* vmInstrNode,
const TargetMachine& targetMachine,
bool canDiscardResult = false,
int op1Position = 0,
int op2Position = 1,
int resultPosition = 2);
MachineOperand::MachineOperandType
ChooseRegOrImmed(Value* val,
MachineOpCode opCode,
const TargetMachine& targetMachine,
bool canUseImmed,
MachineOperand::VirtualRegisterType& getVRegType,
unsigned int& getMachineRegNum,
int64_t& getImmedValue);
ostream& operator<<(ostream& os, const MachineInstr& minstr);
ostream& operator<<(ostream& os, const MachineOperand& mop);
//**************************************************************************/
#endif

View File

@ -0,0 +1,421 @@
// $Id$ -*-c++-*-
//***************************************************************************
// File:
// Sparc.cpp
//
// Purpose:
//
// History:
// 7/15/01 - Vikram Adve - Created
//**************************************************************************/
#ifndef LLVM_CODEGEN_SPARC_H
#define LLVM_CODEGEN_SPARC_H
//************************** System Include Files **************************/
//*************************** User Include Files ***************************/
#include "llvm/Codegen/TargetMachine.h"
#include "llvm/Codegen/MachineInstr.h"
//************************* Opaque Declarations ****************************/
//************************ Exported Constants ******************************/
// OpCodeMask definitions for the Sparc V9
//
const OpCodeMask Immed = 0x00002000; // immed or reg operand?
const OpCodeMask Annul = 0x20000000; // annul delay instr?
const OpCodeMask PredictTaken = 0x00080000; // predict branch taken?
//************************ Exported Data Types *****************************/
//---------------------------------------------------------------------------
// class UltraSparcMachine
//
// Purpose:
// Machine description.
//
//---------------------------------------------------------------------------
class UltraSparc: public TargetMachine {
public:
/*ctor*/ UltraSparc ();
/*dtor*/ virtual ~UltraSparc () {}
};
//---------------------------------------------------------------------------
// enum SparcMachineOpCode.
// const MachineInstrInfo SparcMachineInstrInfo[].
//
// Purpose:
// Description of UltraSparc machine instructions.
//
//---------------------------------------------------------------------------
enum SparcMachineOpCode {
NOP,
// Synthetic SPARC assembly opcodes for setting a register to a constant
SETSW,
SETUW,
// Add or add with carry.
// Immed bit specifies if second operand is immediate(1) or register(0)
ADD,
ADDcc,
ADDC,
ADDCcc,
// Subtract or subtract with carry.
// Immed bit specifies if second operand is immediate(1) or register(0)
SUB,
SUBcc,
SUBC,
SUBCcc,
// Integer multiply, signed divide, unsigned divide.
// Note that the deprecated 32-bit multiply and multiply-step are not used.
MULX,
SDIVX,
UDIVX,
// Floating point add, subtract, compare
FADDS,
FADDD,
FADDQ,
FSUBS,
FSUBD,
FSUBQ,
FCMPS,
FCMPD,
FCMPQ,
// NOTE: FCMPE{S,D,Q}: FP Compare With Exception are currently unused!
// Floating point multiply or divide.
FMULS,
FMULD,
FMULQ,
FSMULD,
FDMULQ,
FDIVS,
FDIVD,
FDIVQ,
// Logical operations
AND,
ANDcc,
ANDN,
ANDNcc,
OR,
ORcc,
ORN,
ORNcc,
XOR,
XORcc,
XNOR,
XNORcc,
// Shift operations
SLL,
SRL,
SRA,
SLLX,
SRLX,
SRAX,
// Convert from floating point to floating point formats
FSTOD,
FSTOQ,
FDTOS,
FDTOQ,
FQTOS,
FQTOD,
// Convert from floating point to integer formats
FSTOX,
FDTOX,
FQTOX,
FSTOI,
FDTOI,
FQTOI,
// Convert from integer to floating point formats
FXTOS,
FXTOD,
FXTOQ,
FITOS,
FITOD,
FITOQ,
// Branch on integer comparison with zero.
// Annul bit specifies if intruction in delay slot is annulled(1) or not(0).
// PredictTaken bit hints if branch should be predicted taken(1) or not(0).
BRZ,
BRLEZ,
BRLZ,
BRNZ,
BRGZ,
BRGEZ,
// Branch on integer condition code.
// Annul bit specifies if intruction in delay slot is annulled(1) or not(0).
// PredictTaken bit hints if branch should be predicted taken(1) or not(0).
BA,
BN,
BNE,
BE,
BG,
BLE,
BGE,
BL,
BGU,
BLEU,
BCC,
BCS,
BPOS,
BNEG,
BVC,
BVS,
// Branch on floating point condition code.
// Annul bit specifies if intruction in delay slot is annulled(1) or not(0).
// PredictTaken bit hints if branch should be predicted taken(1) or not(0).
FBA,
FBN,
FBU,
FBG,
FBUG,
FBL,
FBUL,
FBLG,
FBNE,
FBE,
FBUE,
FBGE,
FBUGE,
FBLE,
FBULE,
FBO,
// Load integer instructions
LDSB,
LDSH,
LDSW,
LDUB,
LDUH,
LDUW,
LDX,
// Load floating-point instructions
LD,
LDD, // use of this for integers is deprecated for Sparc V9
LDQ,
// Store integer instructions
STB,
STH,
STW,
STX,
// Store floating-point instructions
ST,
STD,
// Call, Return, and "Jump and link"
// Immed bit specifies if second operand is immediate(1) or register(0)
CALL,
JMPL,
RETURN,
// End-of-array marker
INVALID_OPCODE
};
const MachineInstrInfo SparcMachineInstrInfo[] = {
{ "NOP", 0, -1, 0, false },
// Synthetic SPARC assembly opcodes for setting a register to a constant
{ "SETSW", 2, 1, 0, true }, // max immediate constant is ignored
{ "SETUW", 2, 1, 0, false }, // max immediate constant is ignored
// Add or add with carry.
{ "ADD", 3, 2, (1 << 12) - 1, true },
{ "ADDcc", 3, 2, (1 << 12) - 1, true },
{ "ADDC", 3, 2, (1 << 12) - 1, true },
{ "ADDCcc", 3, 2, (1 << 12) - 1, true },
// Sub tract or subtract with carry.
{ "SUB", 3, 2, (1 << 12) - 1, true },
{ "SUBcc", 3, 2, (1 << 12) - 1, true },
{ "SUBC", 3, 2, (1 << 12) - 1, true },
{ "SUBCcc", 3, 2, (1 << 12) - 1, true },
// Integer multiply, signed divide, unsigned divide.
// Note that the deprecated 32-bit multiply and multiply-step are not used.
{ "MULX", 3, 2, (1 << 12) - 1, true },
{ "SDIVX", 3, 2, (1 << 12) - 1, true },
{ "UDIVX", 3, 2, (1 << 12) - 1, true },
// Floating point add, subtract, compare
{ "FADDS", 3, 2, 0, false },
{ "FADDD", 3, 2, 0, false },
{ "FADDQ", 3, 2, 0, false },
{ "FSUBS", 3, 2, 0, false },
{ "FSUBD", 3, 2, 0, false },
{ "FSUBQ", 3, 2, 0, false },
{ "FCMPS", 3, 2, 0, false },
{ "FCMPD", 3, 2, 0, false },
{ "FCMPQ", 3, 2, 0, false },
// NOTE: FCMPE{S,D,Q}: FP Compare With Exception are currently unused!
// Floating point multiply or divide.
{ "FMULS", 3, 2, 0, false },
{ "FMULD", 3, 2, 0, false },
{ "FMULQ", 3, 2, 0, false },
{ "FSMULD", 3, 2, 0, false },
{ "FDMULQ", 3, 2, 0, false },
{ "FDIVS", 3, 2, 0, false },
{ "FDIVD", 3, 2, 0, false },
{ "FDIVQ", 3, 2, 0, false },
// Logical operations
{ "AND", 3, 2, (1 << 12) - 1, true },
{ "ANDcc", 3, 2, (1 << 12) - 1, true },
{ "ANDN", 3, 2, (1 << 12) - 1, true },
{ "ANDNcc", 3, 2, (1 << 12) - 1, true },
{ "OR", 3, 2, (1 << 12) - 1, true },
{ "ORcc", 3, 2, (1 << 12) - 1, true },
{ "ORN", 3, 2, (1 << 12) - 1, true },
{ "ORNcc", 3, 2, (1 << 12) - 1, true },
{ "XOR", 3, 2, (1 << 12) - 1, true },
{ "XORcc", 3, 2, (1 << 12) - 1, true },
{ "XNOR", 3, 2, (1 << 12) - 1, true },
{ "XNORcc", 3, 2, (1 << 12) - 1, true },
// Shift operations
{ "SLL", 3, 2, (1 << 5) - 1, true },
{ "SRL", 3, 2, (1 << 5) - 1, true },
{ "SRA", 3, 2, (1 << 5) - 1, true },
{ "SLLX", 3, 2, (1 << 6) - 1, true },
{ "SRLX", 3, 2, (1 << 6) - 1, true },
{ "SRAX", 3, 2, (1 << 6) - 1, true },
// Convert from floating point to floating point formats
{ "FSTOD", 2, 1, 0, false },
{ "FSTOQ", 2, 1, 0, false },
{ "FDTOS", 2, 1, 0, false },
{ "FDTOQ", 2, 1, 0, false },
{ "FQTOS", 2, 1, 0, false },
{ "FQTOD", 2, 1, 0, false },
// Convert from floating point to integer formats
{ "FSTOX", 2, 1, 0, false },
{ "FDTOX", 2, 1, 0, false },
{ "FQTOX", 2, 1, 0, false },
{ "FSTOI", 2, 1, 0, false },
{ "FDTOI", 2, 1, 0, false },
{ "FQTOI", 2, 1, 0, false },
// Convert from integer to floating point formats
{ "FXTOS", 2, 1, 0, false },
{ "FXTOD", 2, 1, 0, false },
{ "FXTOQ", 2, 1, 0, false },
{ "FITOS", 2, 1, 0, false },
{ "FITOD", 2, 1, 0, false },
{ "FITOQ", 2, 1, 0, false },
// Branch on integer comparison with zero.
{ "BRZ", 2, -1, (1 << 15) - 1, true },
{ "BRLEZ", 2, -1, (1 << 15) - 1, true },
{ "BRLZ", 2, -1, (1 << 15) - 1, true },
{ "BRNZ", 2, -1, (1 << 15) - 1, true },
{ "BRGZ", 2, -1, (1 << 15) - 1, true },
{ "BRGEZ", 2, -1, (1 << 15) - 1, true },
// Branch on condition code.
{ "BA", 1, -1, (1 << 21) - 1, true },
{ "BN", 1, -1, (1 << 21) - 1, true },
{ "BNE", 1, -1, (1 << 21) - 1, true },
{ "BE", 1, -1, (1 << 21) - 1, true },
{ "BG", 1, -1, (1 << 21) - 1, true },
{ "BLE", 1, -1, (1 << 21) - 1, true },
{ "BGE", 1, -1, (1 << 21) - 1, true },
{ "BL", 1, -1, (1 << 21) - 1, true },
{ "BGU", 1, -1, (1 << 21) - 1, true },
{ "BLEU", 1, -1, (1 << 21) - 1, true },
{ "BCC", 1, -1, (1 << 21) - 1, true },
{ "BCS", 1, -1, (1 << 21) - 1, true },
{ "BPOS", 1, -1, (1 << 21) - 1, true },
{ "BNEG", 1, -1, (1 << 21) - 1, true },
{ "BVC", 1, -1, (1 << 21) - 1, true },
{ "BVS", 1, -1, (1 << 21) - 1, true },
// Branch on floating point condition code.
// Annul bit specifies if intruction in delay slot is annulled(1) or not(0).
// PredictTaken bit hints if branch should be predicted taken(1) or not(0).
// The first argument is the FCCn register (0 <= n <= 3).
{ "FBA", 2, -1, (1 << 18) - 1, true },
{ "FBN", 2, -1, (1 << 18) - 1, true },
{ "FBU", 2, -1, (1 << 18) - 1, true },
{ "FBG", 2, -1, (1 << 18) - 1, true },
{ "FBUG", 2, -1, (1 << 18) - 1, true },
{ "FBL", 2, -1, (1 << 18) - 1, true },
{ "FBUL", 2, -1, (1 << 18) - 1, true },
{ "FBLG", 2, -1, (1 << 18) - 1, true },
{ "FBNE", 2, -1, (1 << 18) - 1, true },
{ "FBE", 2, -1, (1 << 18) - 1, true },
{ "FBUE", 2, -1, (1 << 18) - 1, true },
{ "FBGE", 2, -1, (1 << 18) - 1, true },
{ "FBUGE", 2, -1, (1 << 18) - 1, true },
{ "FBLE", 2, -1, (1 << 18) - 1, true },
{ "FBULE", 2, -1, (1 << 18) - 1, true },
{ "FBO", 2, -1, (1 << 18) - 1, true },
// Load integer instructions
{ "LDSB", 3, 2, (1 << 12) - 1, true },
{ "LDSH", 3, 2, (1 << 12) - 1, true },
{ "LDSW", 3, 2, (1 << 12) - 1, true },
{ "LDUB", 3, 2, (1 << 12) - 1, true },
{ "LDUH", 3, 2, (1 << 12) - 1, true },
{ "LDUW", 3, 2, (1 << 12) - 1, true },
{ "LDX", 3, 2, (1 << 12) - 1, true },
// Load floating-point instructions
{ "LD", 3, 2, (1 << 12) - 1, true },
{ "LDD", 3, 2, (1 << 12) - 1, true },
{ "LDQ", 3, 2, (1 << 12) - 1, true },
// Store integer instructions
{ "STB", 3, -1, (1 << 12) - 1, true },
{ "STH", 3, -1, (1 << 12) - 1, true },
{ "STW", 3, -1, (1 << 12) - 1, true },
{ "STX", 3, -1, (1 << 12) - 1, true },
// Store floating-point instructions
{ "ST", 3, -1, (1 << 12) - 1, true },
{ "STD", 3, -1, (1 << 12) - 1, true },
// Call, Return and "Jump and link"
{ "CALL", 1, -1, (1 << 29) - 1, true },
{ "JMPL", 3, -1, (1 << 12) - 1, true },
{ "RETURN", 2, -1, 0, false },
// End-of-array marker
{ "INVALID_SPARC_OPCODE", 0, -1, 0, false }
};
/***************************************************************************/
#endif

View File

@ -0,0 +1,111 @@
// $Id$ -*-c++-*-
//***************************************************************************
// File:
// TargetMachine.h
//
// Purpose:
//
// History:
// 7/12/01 - Vikram Adve - Created
//**************************************************************************/
#ifndef LLVM_CODEGEN_TARGETMACHINE_H
#define LLVM_CODEGEN_TARGETMACHINE_H
//************************** System Include Files **************************/
//*************************** User Include Files ***************************/
#include "llvm/Support/Unique.h"
#include "llvm/Tools/DataTypes.h"
//************************* Opaque Declarations ****************************/
class Type;
class StructType;
class MachineInstrInfo;
//************************ Exported Data Types *****************************/
//---------------------------------------------------------------------------
// Data types used to define information about a single machine instruction
//---------------------------------------------------------------------------
typedef int MachineOpCode;
typedef int OpCodeMask;
// struct MachineInstrInfo:
// Predefined information about each machine instruction.
//
struct MachineInstrInfo {
string opCodeString; // Assembly language mnemonic for the opcode.
unsigned int numOperands; // Number of arguments for the instruction.
int resultPos; // Position of the result; -1 if no result
unsigned int maxImmedConst; // Largest +ve constant in IMMMED field or 0.
bool immedIsSignExtended; // Is the IMMED field sign-extended? If so,
// smallest -ve value is -(maxImmedConst+1).
// Check if the specified constant fits in the immediate field
// of this machine instruction
//
bool constantFitsInImmedField (int64_t intValue) const;
// Return the largest +ve constant that can be held in the IMMMED field
// of this machine instruction.
// isSignExtended is set to true if the value is sign-extended before use
// (this is true for all immediate fields in SPARC instructions).
// Return 0 if the instruction has no IMMED field.
//
inline uint64_t maxImmedConstant(bool& isSignExtended) const {
isSignExtended = immedIsSignExtended;
return maxImmedConst; }
};
// Global variable holding an array of the above structures.
// This needs to be defined separately for each target machine.
//
extern const MachineInstrInfo* TargetMachineInstrInfo;
//---------------------------------------------------------------------------
// class TargetMachine
//
// Purpose:
// Machine description.
//
//---------------------------------------------------------------------------
class TargetMachine: public Unique {
public:
int optSizeForSubWordData;
int intSize;
int longSize;
int floatSize;
int doubleSize;
int longDoubleSize;
int pointerSize;
int minMemOpWordSize;
int maxAtomicMemOpWordSize;
// Description of machine instructions (array indexed by machine opcode)
const MachineInstrInfo* machineInstrInfo;
// Register information. This needs to be reorganized into a single class.
int zeroRegNum; // register that gives 0 if any (-1 if none)
public:
/*ctor*/ TargetMachine () {}
/*dtor*/ virtual ~TargetMachine () {}
virtual unsigned int findOptimalStorageSize (const Type* ty) const;
virtual unsigned int* findOptimalMemberOffsets(const StructType* stype)const;
};
//**************************************************************************/
#endif