mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-21 18:29:46 +00:00
implementation of a Target{RegInfo, InstrInfo, Machine, etc} now has a separate header and a separate implementation file. This means that instead of a massive SparcInternals.h that forces a recompilation of the whole target whenever a minor detail is changed, you should only recompile a few files. Note that SparcInternals.h is still around; its contents should be minimized. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@10500 91177308-0d34-0410-b5e6-96231b3b80d8
202 lines
9.1 KiB
C++
202 lines
9.1 KiB
C++
//===-- SparcInstrInfo.h - Define TargetInstrInfo for Sparc -----*- 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 class contains information about individual instructions.
|
|
// Most information is stored in the SparcMachineInstrDesc array above.
|
|
// Other information is computed on demand, and most such functions
|
|
// default to member functions in base class TargetInstrInfo.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SPARC_INSTRINFO_H
|
|
#define SPARC_INSTRINFO_H
|
|
|
|
#include "llvm/Target/TargetInstrInfo.h"
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
|
#include "SparcInternals.h"
|
|
|
|
namespace llvm {
|
|
|
|
struct SparcInstrInfo : public TargetInstrInfo {
|
|
SparcInstrInfo();
|
|
|
|
// All immediate constants are in position 1 except the
|
|
// store instructions and SETxx.
|
|
//
|
|
virtual int getImmedConstantPos(MachineOpCode opCode) const {
|
|
bool ignore;
|
|
if (this->maxImmedConstant(opCode, ignore) != 0) {
|
|
// 1st store opcode
|
|
assert(! this->isStore((MachineOpCode) V9::STBr - 1));
|
|
// last store opcode
|
|
assert(! this->isStore((MachineOpCode) V9::STXFSRi + 1));
|
|
|
|
if (opCode == V9::SETSW || opCode == V9::SETUW ||
|
|
opCode == V9::SETX || opCode == V9::SETHI)
|
|
return 0;
|
|
if (opCode >= V9::STBr && opCode <= V9::STXFSRi)
|
|
return 2;
|
|
return 1;
|
|
}
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
/// createNOPinstr - returns the target's implementation of NOP, which is
|
|
/// usually a pseudo-instruction, implemented by a degenerate version of
|
|
/// another instruction, e.g. X86: xchg ax, ax; SparcV9: sethi 0, g0
|
|
///
|
|
MachineInstr* createNOPinstr() const {
|
|
return BuildMI(V9::SETHI, 2).addZImm(0).addReg(SparcIntRegClass::g0);
|
|
}
|
|
|
|
/// isNOPinstr - not having a special NOP opcode, we need to know if a given
|
|
/// instruction is interpreted as an `official' NOP instr, i.e., there may be
|
|
/// more than one way to `do nothing' but only one canonical way to slack off.
|
|
///
|
|
bool isNOPinstr(const MachineInstr &MI) const {
|
|
// Make sure the instruction is EXACTLY `sethi g0, 0'
|
|
if (MI.getOpcode() == V9::SETHI && MI.getNumOperands() == 2) {
|
|
const MachineOperand &op0 = MI.getOperand(0), &op1 = MI.getOperand(1);
|
|
if (op0.isImmediate() && op0.getImmedValue() == 0 &&
|
|
op1.isMachineRegister() &&
|
|
op1.getMachineRegNum() == SparcIntRegClass::g0)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
virtual bool hasResultInterlock(MachineOpCode opCode) const
|
|
{
|
|
// All UltraSPARC instructions have interlocks (note that delay slots
|
|
// are not considered here).
|
|
// However, instructions that use the result of an FCMP produce a
|
|
// 9-cycle stall if they are issued less than 3 cycles after the FCMP.
|
|
// Force the compiler to insert a software interlock (i.e., gap of
|
|
// 2 other groups, including NOPs if necessary).
|
|
return (opCode == V9::FCMPS || opCode == V9::FCMPD || opCode == V9::FCMPQ);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// Queries about representation of LLVM quantities (e.g., constants)
|
|
//-------------------------------------------------------------------------
|
|
|
|
virtual bool ConstantMayNotFitInImmedField(const Constant* CV,
|
|
const Instruction* I) const;
|
|
|
|
//-------------------------------------------------------------------------
|
|
// Code generation support for creating individual machine instructions
|
|
//-------------------------------------------------------------------------
|
|
|
|
// Get certain common op codes for the current target. This and all the
|
|
// Create* methods below should be moved to a machine code generation class
|
|
//
|
|
virtual MachineOpCode getNOPOpCode() const { return V9::NOP; }
|
|
|
|
// Get the value of an integral constant in the form that must
|
|
// be put into the machine register. The specified constant is interpreted
|
|
// as (i.e., converted if necessary to) the specified destination type. The
|
|
// result is always returned as an uint64_t, since the representation of
|
|
// int64_t and uint64_t are identical. The argument can be any known const.
|
|
//
|
|
// isValidConstant is set to true if a valid constant was found.
|
|
//
|
|
virtual uint64_t ConvertConstantToIntType(const TargetMachine &target,
|
|
const Value *V,
|
|
const Type *destType,
|
|
bool &isValidConstant) const;
|
|
|
|
// Create an instruction sequence to put the constant `val' into
|
|
// the virtual register `dest'. `val' may be a Constant or a
|
|
// GlobalValue, viz., the constant address of a global variable or function.
|
|
// The generated instructions are returned in `mvec'.
|
|
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
|
// Any stack space required is allocated via mcff.
|
|
//
|
|
virtual void CreateCodeToLoadConst(const TargetMachine& target,
|
|
Function* F,
|
|
Value* val,
|
|
Instruction* dest,
|
|
std::vector<MachineInstr*>& mvec,
|
|
MachineCodeForInstruction& mcfi) const;
|
|
|
|
// Create an instruction sequence to copy an integer value `val'
|
|
// to a floating point value `dest' by copying to memory and back.
|
|
// val must be an integral type. dest must be a Float or Double.
|
|
// The generated instructions are returned in `mvec'.
|
|
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
|
// Any stack space required is allocated via mcff.
|
|
//
|
|
virtual void CreateCodeToCopyIntToFloat(const TargetMachine& target,
|
|
Function* F,
|
|
Value* val,
|
|
Instruction* dest,
|
|
std::vector<MachineInstr*>& mvec,
|
|
MachineCodeForInstruction& mcfi) const;
|
|
|
|
// Similarly, create an instruction sequence to copy an FP value
|
|
// `val' to an integer value `dest' by copying to memory and back.
|
|
// The generated instructions are returned in `mvec'.
|
|
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
|
// Any stack space required is allocated via mcff.
|
|
//
|
|
virtual void CreateCodeToCopyFloatToInt(const TargetMachine& target,
|
|
Function* F,
|
|
Value* val,
|
|
Instruction* dest,
|
|
std::vector<MachineInstr*>& mvec,
|
|
MachineCodeForInstruction& mcfi) const;
|
|
|
|
// Create instruction(s) to copy src to dest, for arbitrary types
|
|
// The generated instructions are returned in `mvec'.
|
|
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
|
// Any stack space required is allocated via mcff.
|
|
//
|
|
virtual void CreateCopyInstructionsByType(const TargetMachine& target,
|
|
Function* F,
|
|
Value* src,
|
|
Instruction* dest,
|
|
std::vector<MachineInstr*>& mvec,
|
|
MachineCodeForInstruction& mcfi) const;
|
|
|
|
// Create instruction sequence to produce a sign-extended register value
|
|
// from an arbitrary sized value (sized in bits, not bytes).
|
|
// The generated instructions are appended to `mvec'.
|
|
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
|
// Any stack space required is allocated via mcff.
|
|
//
|
|
virtual void CreateSignExtensionInstructions(const TargetMachine& target,
|
|
Function* F,
|
|
Value* srcVal,
|
|
Value* destVal,
|
|
unsigned int numLowBits,
|
|
std::vector<MachineInstr*>& mvec,
|
|
MachineCodeForInstruction& mcfi) const;
|
|
|
|
// Create instruction sequence to produce a zero-extended register value
|
|
// from an arbitrary sized value (sized in bits, not bytes).
|
|
// The generated instructions are appended to `mvec'.
|
|
// Any temp. registers (TmpInstruction) created are recorded in mcfi.
|
|
// Any stack space required is allocated via mcff.
|
|
//
|
|
virtual void CreateZeroExtensionInstructions(const TargetMachine& target,
|
|
Function* F,
|
|
Value* srcVal,
|
|
Value* destVal,
|
|
unsigned int numLowBits,
|
|
std::vector<MachineInstr*>& mvec,
|
|
MachineCodeForInstruction& mcfi) const;
|
|
};
|
|
|
|
} // End llvm namespace
|
|
|
|
#endif
|