mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-19 19:29:31 +00:00
used in the SparcV9 backend really have anything to do with TargetInstrInfo, so we're converting them into regular old global functions and moving their declarations to SparcV9InstrSelectionSupport.h. (They're mostly used as helper functions for SparcV9InstrSelection.) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15277 91177308-0d34-0410-b5e6-96231b3b80d8
322 lines
12 KiB
C++
322 lines
12 KiB
C++
//===-- SparcV9InstrSelectionSupport.h --------------------------*- 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// More instruction selection support routines for the SparcV9 target.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SPARCV9INSTRSELECTIONSUPPORT_H
|
|
#define SPARCV9INSTRSELECTIONSUPPORT_H
|
|
|
|
#include "llvm/DerivedTypes.h"
|
|
#include "SparcV9Internals.h"
|
|
|
|
namespace llvm {
|
|
|
|
// Choose load instruction opcode based on type of value
|
|
inline MachineOpCode
|
|
ChooseLoadInstruction(const Type *DestTy)
|
|
{
|
|
switch (DestTy->getTypeID()) {
|
|
case Type::BoolTyID:
|
|
case Type::UByteTyID: return V9::LDUBr;
|
|
case Type::SByteTyID: return V9::LDSBr;
|
|
case Type::UShortTyID: return V9::LDUHr;
|
|
case Type::ShortTyID: return V9::LDSHr;
|
|
case Type::UIntTyID: return V9::LDUWr;
|
|
case Type::IntTyID: return V9::LDSWr;
|
|
case Type::PointerTyID:
|
|
case Type::ULongTyID:
|
|
case Type::LongTyID: return V9::LDXr;
|
|
case Type::FloatTyID: return V9::LDFr;
|
|
case Type::DoubleTyID: return V9::LDDFr;
|
|
default: assert(0 && "Invalid type for Load instruction");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Choose store instruction opcode based on type of value
|
|
inline MachineOpCode
|
|
ChooseStoreInstruction(const Type *DestTy)
|
|
{
|
|
switch (DestTy->getTypeID()) {
|
|
case Type::BoolTyID:
|
|
case Type::UByteTyID:
|
|
case Type::SByteTyID: return V9::STBr;
|
|
case Type::UShortTyID:
|
|
case Type::ShortTyID: return V9::STHr;
|
|
case Type::UIntTyID:
|
|
case Type::IntTyID: return V9::STWr;
|
|
case Type::PointerTyID:
|
|
case Type::ULongTyID:
|
|
case Type::LongTyID: return V9::STXr;
|
|
case Type::FloatTyID: return V9::STFr;
|
|
case Type::DoubleTyID: return V9::STDFr;
|
|
default: assert(0 && "Invalid type for Store instruction");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
inline MachineOpCode
|
|
ChooseAddInstructionByType(const Type* resultType)
|
|
{
|
|
MachineOpCode opCode = V9::INVALID_OPCODE;
|
|
|
|
if (resultType->isIntegral() ||
|
|
isa<PointerType>(resultType) ||
|
|
isa<FunctionType>(resultType) ||
|
|
resultType == Type::LabelTy)
|
|
{
|
|
opCode = V9::ADDr;
|
|
}
|
|
else
|
|
switch(resultType->getTypeID())
|
|
{
|
|
case Type::FloatTyID: opCode = V9::FADDS; break;
|
|
case Type::DoubleTyID: opCode = V9::FADDD; break;
|
|
default: assert(0 && "Invalid type for ADD instruction"); break;
|
|
}
|
|
|
|
return opCode;
|
|
}
|
|
|
|
|
|
// Because the SparcV9 instruction selector likes to re-write operands to
|
|
// instructions, making them change from a Value* (virtual register) to a
|
|
// Constant* (making an immediate field), we need to change the opcode from a
|
|
// register-based instruction to an immediate-based instruction, hence this
|
|
// mapping.
|
|
static unsigned
|
|
convertOpcodeFromRegToImm(unsigned Opcode) {
|
|
switch (Opcode) {
|
|
/* arithmetic */
|
|
case V9::ADDr: return V9::ADDi;
|
|
case V9::ADDccr: return V9::ADDcci;
|
|
case V9::ADDCr: return V9::ADDCi;
|
|
case V9::ADDCccr: return V9::ADDCcci;
|
|
case V9::SUBr: return V9::SUBi;
|
|
case V9::SUBccr: return V9::SUBcci;
|
|
case V9::SUBCr: return V9::SUBCi;
|
|
case V9::SUBCccr: return V9::SUBCcci;
|
|
case V9::MULXr: return V9::MULXi;
|
|
case V9::SDIVXr: return V9::SDIVXi;
|
|
case V9::UDIVXr: return V9::UDIVXi;
|
|
|
|
/* logical */
|
|
case V9::ANDr: return V9::ANDi;
|
|
case V9::ANDccr: return V9::ANDcci;
|
|
case V9::ANDNr: return V9::ANDNi;
|
|
case V9::ANDNccr: return V9::ANDNcci;
|
|
case V9::ORr: return V9::ORi;
|
|
case V9::ORccr: return V9::ORcci;
|
|
case V9::ORNr: return V9::ORNi;
|
|
case V9::ORNccr: return V9::ORNcci;
|
|
case V9::XORr: return V9::XORi;
|
|
case V9::XORccr: return V9::XORcci;
|
|
case V9::XNORr: return V9::XNORi;
|
|
case V9::XNORccr: return V9::XNORcci;
|
|
|
|
/* shift */
|
|
case V9::SLLr5: return V9::SLLi5;
|
|
case V9::SRLr5: return V9::SRLi5;
|
|
case V9::SRAr5: return V9::SRAi5;
|
|
case V9::SLLXr6: return V9::SLLXi6;
|
|
case V9::SRLXr6: return V9::SRLXi6;
|
|
case V9::SRAXr6: return V9::SRAXi6;
|
|
|
|
/* Conditional move on int comparison with zero */
|
|
case V9::MOVRZr: return V9::MOVRZi;
|
|
case V9::MOVRLEZr: return V9::MOVRLEZi;
|
|
case V9::MOVRLZr: return V9::MOVRLZi;
|
|
case V9::MOVRNZr: return V9::MOVRNZi;
|
|
case V9::MOVRGZr: return V9::MOVRGZi;
|
|
case V9::MOVRGEZr: return V9::MOVRGEZi;
|
|
|
|
|
|
/* Conditional move on int condition code */
|
|
case V9::MOVAr: return V9::MOVAi;
|
|
case V9::MOVNr: return V9::MOVNi;
|
|
case V9::MOVNEr: return V9::MOVNEi;
|
|
case V9::MOVEr: return V9::MOVEi;
|
|
case V9::MOVGr: return V9::MOVGi;
|
|
case V9::MOVLEr: return V9::MOVLEi;
|
|
case V9::MOVGEr: return V9::MOVGEi;
|
|
case V9::MOVLr: return V9::MOVLi;
|
|
case V9::MOVGUr: return V9::MOVGUi;
|
|
case V9::MOVLEUr: return V9::MOVLEUi;
|
|
case V9::MOVCCr: return V9::MOVCCi;
|
|
case V9::MOVCSr: return V9::MOVCSi;
|
|
case V9::MOVPOSr: return V9::MOVPOSi;
|
|
case V9::MOVNEGr: return V9::MOVNEGi;
|
|
case V9::MOVVCr: return V9::MOVVCi;
|
|
case V9::MOVVSr: return V9::MOVVSi;
|
|
|
|
/* Conditional move of int reg on fp condition code */
|
|
case V9::MOVFAr: return V9::MOVFAi;
|
|
case V9::MOVFNr: return V9::MOVFNi;
|
|
case V9::MOVFUr: return V9::MOVFUi;
|
|
case V9::MOVFGr: return V9::MOVFGi;
|
|
case V9::MOVFUGr: return V9::MOVFUGi;
|
|
case V9::MOVFLr: return V9::MOVFLi;
|
|
case V9::MOVFULr: return V9::MOVFULi;
|
|
case V9::MOVFLGr: return V9::MOVFLGi;
|
|
case V9::MOVFNEr: return V9::MOVFNEi;
|
|
case V9::MOVFEr: return V9::MOVFEi;
|
|
case V9::MOVFUEr: return V9::MOVFUEi;
|
|
case V9::MOVFGEr: return V9::MOVFGEi;
|
|
case V9::MOVFUGEr: return V9::MOVFUGEi;
|
|
case V9::MOVFLEr: return V9::MOVFLEi;
|
|
case V9::MOVFULEr: return V9::MOVFULEi;
|
|
case V9::MOVFOr: return V9::MOVFOi;
|
|
|
|
/* load */
|
|
case V9::LDSBr: return V9::LDSBi;
|
|
case V9::LDSHr: return V9::LDSHi;
|
|
case V9::LDSWr: return V9::LDSWi;
|
|
case V9::LDUBr: return V9::LDUBi;
|
|
case V9::LDUHr: return V9::LDUHi;
|
|
case V9::LDUWr: return V9::LDUWi;
|
|
case V9::LDXr: return V9::LDXi;
|
|
case V9::LDFr: return V9::LDFi;
|
|
case V9::LDDFr: return V9::LDDFi;
|
|
case V9::LDQFr: return V9::LDQFi;
|
|
case V9::LDFSRr: return V9::LDFSRi;
|
|
case V9::LDXFSRr: return V9::LDXFSRi;
|
|
|
|
/* store */
|
|
case V9::STBr: return V9::STBi;
|
|
case V9::STHr: return V9::STHi;
|
|
case V9::STWr: return V9::STWi;
|
|
case V9::STXr: return V9::STXi;
|
|
case V9::STFr: return V9::STFi;
|
|
case V9::STDFr: return V9::STDFi;
|
|
case V9::STFSRr: return V9::STFSRi;
|
|
case V9::STXFSRr: return V9::STXFSRi;
|
|
|
|
/* jump & return */
|
|
case V9::JMPLCALLr: return V9::JMPLCALLi;
|
|
case V9::JMPLRETr: return V9::JMPLRETi;
|
|
|
|
/* save and restore */
|
|
case V9::SAVEr: return V9::SAVEi;
|
|
case V9::RESTOREr: return V9::RESTOREi;
|
|
|
|
default:
|
|
// It's already in correct format
|
|
// Or, it's just not handled yet, but an assert() would break LLC
|
|
#if 0
|
|
std::cerr << "Unhandled opcode in convertOpcodeFromRegToImm(): " << Opcode
|
|
<< "\n";
|
|
#endif
|
|
return Opcode;
|
|
}
|
|
}
|
|
|
|
MachineOperand::MachineOperandType
|
|
ChooseRegOrImmed(Value* val, MachineOpCode opCode,
|
|
const TargetMachine& targetMachine, bool canUseImmed,
|
|
unsigned& getMachineRegNum, int64_t& getImmedValue);
|
|
|
|
/// ConvertConstantToIntType - 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.
|
|
///
|
|
uint64_t ConvertConstantToIntType (const TargetMachine &target,
|
|
const Value *V, const Type *destType, bool &isValidConstant);
|
|
|
|
/// ConstantMayNotFitInImmedField - Test if this constant may not fit in the
|
|
/// immediate field of the machine instructions (probably) generated for this
|
|
/// instruction.
|
|
///
|
|
bool ConstantMayNotFitInImmedField (const Constant *CV, const Instruction *I);
|
|
|
|
/// CreateCodeToLoadConst - 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.
|
|
///
|
|
void CreateCodeToLoadConst (const TargetMachine &target, Function *F,
|
|
Value *val, Instruction *dest, std::vector<MachineInstr*> &mvec,
|
|
MachineCodeForInstruction &mcfi);
|
|
|
|
/// CreateSignExtensionInstructions - 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.
|
|
///
|
|
void CreateSignExtensionInstructions (const TargetMachine &target,
|
|
Function *F, Value *srcVal, Value *destVal, unsigned int numLowBits,
|
|
std::vector<MachineInstr*> &mvec, MachineCodeForInstruction &mcfi);
|
|
|
|
/// CreateZeroExtensionInstructions - 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.
|
|
///
|
|
void CreateZeroExtensionInstructions (const TargetMachine &target,
|
|
Function *F, Value *srcVal, Value *destVal, unsigned int numLowBits,
|
|
std::vector<MachineInstr*> &mvec, MachineCodeForInstruction &mcfi);
|
|
|
|
/// CreateCodeToCopyIntToFloat - 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.
|
|
///
|
|
void CreateCodeToCopyIntToFloat (const TargetMachine &target,
|
|
Function *F, Value *val, Instruction *dest, std::vector<MachineInstr*> &mvec,
|
|
MachineCodeForInstruction &mcfi);
|
|
|
|
/// CreateCodeToCopyFloatToInt - 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.
|
|
///
|
|
void CreateCodeToCopyFloatToInt (const TargetMachine &target, Function *F,
|
|
Value *val, Instruction *dest, std::vector<MachineInstr*> &mvec,
|
|
MachineCodeForInstruction &mcfi);
|
|
|
|
/// CreateCopyInstructionsByType - 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.
|
|
///
|
|
void CreateCopyInstructionsByType (const TargetMachine &target,
|
|
Function *F, Value *src, Instruction *dest, std::vector<MachineInstr*> &mvec,
|
|
MachineCodeForInstruction &mcfi);
|
|
|
|
/// CreateSignExtensionInstructions - 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.
|
|
///
|
|
void CreateSignExtensionInstructions (const TargetMachine &target,
|
|
Function *F, Value *srcVal, Value *destVal, unsigned int numLowBits,
|
|
std::vector<MachineInstr*> &mvec, MachineCodeForInstruction &mcfi);
|
|
|
|
/// CreateZeroExtensionInstructions - 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.
|
|
///
|
|
void CreateZeroExtensionInstructions (const TargetMachine &target,
|
|
Function *F, Value *srcVal, Value *destVal, unsigned int numLowBits,
|
|
std::vector<MachineInstr*> &mvec, MachineCodeForInstruction &mcfi);
|
|
|
|
} // End llvm namespace
|
|
|
|
#endif
|