#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
std::string Basename;
switch(opcode) {
default: assert (0 && "do not know intrinsic name");
+ // Arithmetic Right shift for integer types.
case PIC16ISD::SRA_I8: Basename = "sra.i8"; break;
case RTLIB::SRA_I16: Basename = "sra.i16"; break;
case RTLIB::SRA_I32: Basename = "sra.i32"; break;
+ // Left shift for integer types.
case PIC16ISD::SLL_I8: Basename = "sll.i8"; break;
case RTLIB::SHL_I16: Basename = "sll.i16"; break;
case RTLIB::SHL_I32: Basename = "sll.i32"; break;
+ // Logical Right Shift for integer types.
case PIC16ISD::SRL_I8: Basename = "srl.i8"; break;
case RTLIB::SRL_I16: Basename = "srl.i16"; break;
case RTLIB::SRL_I32: Basename = "srl.i32"; break;
+ // Multiply for integer types.
case PIC16ISD::MUL_I8: Basename = "mul.i8"; break;
case RTLIB::MUL_I16: Basename = "mul.i16"; break;
case RTLIB::MUL_I32: Basename = "mul.i32"; break;
+
+ // Signed division for integers.
+ case RTLIB::SDIV_I16: Basename = "sdiv.i16"; break;
+ case RTLIB::SDIV_I32: Basename = "sdiv.i32"; break;
+
+ // Unsigned division for integers.
+ case RTLIB::UDIV_I16: Basename = "udiv.i16"; break;
+ case RTLIB::UDIV_I32: Basename = "udiv.i32"; break;
+
+ // Signed Modulas for integers.
+ case RTLIB::SREM_I16: Basename = "srem.i16"; break;
+ case RTLIB::SREM_I32: Basename = "srem.i32"; break;
+
+ // Unsigned Modulas for integers.
+ case RTLIB::UREM_I16: Basename = "urem.i16"; break;
+ case RTLIB::UREM_I32: Basename = "urem.i32"; break;
+
+ //////////////////////
+ // LIBCALLS FOR FLOATS
+ //////////////////////
+
+ // Float to signed integrals
+ case RTLIB::FPTOSINT_F32_I8: Basename = "f32_to_si32"; break;
+ case RTLIB::FPTOSINT_F32_I16: Basename = "f32_to_si32"; break;
+ case RTLIB::FPTOSINT_F32_I32: Basename = "f32_to_si32"; break;
+
+ // Signed integrals to float. char and int are first sign extended to i32
+ // before being converted to float, so an I8_F32 or I16_F32 isn't required.
+ case RTLIB::SINTTOFP_I32_F32: Basename = "si32_to_f32"; break;
+
+ // Float to Unsigned conversions.
+ // Signed conversion can be used for unsigned conversion as well.
+ // In signed and unsigned versions only the interpretation of the
+ // MSB is different. Bit representation remains the same.
+ case RTLIB::FPTOUINT_F32_I8: Basename = "f32_to_si32"; break;
+ case RTLIB::FPTOUINT_F32_I16: Basename = "f32_to_si32"; break;
+ case RTLIB::FPTOUINT_F32_I32: Basename = "f32_to_si32"; break;
+
+ // Unsigned to Float conversions. char and int are first zero extended
+ // before being converted to float.
+ case RTLIB::UINTTOFP_I32_F32: Basename = "ui32_to_f32"; break;
+
+ // Floating point add, sub, mul, div.
+ case RTLIB::ADD_F32: Basename = "add.f32"; break;
+ case RTLIB::SUB_F32: Basename = "sub.f32"; break;
+ case RTLIB::MUL_F32: Basename = "mul.f32"; break;
+ case RTLIB::DIV_F32: Basename = "div.f32"; break;
+
+ // Floating point comparison
+ case RTLIB::O_F32: Basename = "unordered.f32"; break;
+ case RTLIB::UO_F32: Basename = "unordered.f32"; break;
+ case RTLIB::OLE_F32: Basename = "le.f32"; break;
+ case RTLIB::OGE_F32: Basename = "ge.f32"; break;
+ case RTLIB::OLT_F32: Basename = "lt.f32"; break;
+ case RTLIB::OGT_F32: Basename = "gt.f32"; break;
+ case RTLIB::OEQ_F32: Basename = "eq.f32"; break;
+ case RTLIB::UNE_F32: Basename = "neq.f32"; break;
}
std::string prefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
// PIC16TargetLowering Constructor.
PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
: TargetLowering(TM), TmpSize(0) {
-
+
Subtarget = &TM.getSubtarget<PIC16Subtarget>();
addRegisterClass(MVT::i8, PIC16::GPRRegisterClass);
setLibcallName(RTLIB::MUL_I16, getIntrinsicName(RTLIB::MUL_I16));
setLibcallName(RTLIB::MUL_I32, getIntrinsicName(RTLIB::MUL_I32));
+ // Signed division lib call names
+ setLibcallName(RTLIB::SDIV_I16, getIntrinsicName(RTLIB::SDIV_I16));
+ setLibcallName(RTLIB::SDIV_I32, getIntrinsicName(RTLIB::SDIV_I32));
+
+ // Unsigned division lib call names
+ setLibcallName(RTLIB::UDIV_I16, getIntrinsicName(RTLIB::UDIV_I16));
+ setLibcallName(RTLIB::UDIV_I32, getIntrinsicName(RTLIB::UDIV_I32));
+
+ // Signed remainder lib call names
+ setLibcallName(RTLIB::SREM_I16, getIntrinsicName(RTLIB::SREM_I16));
+ setLibcallName(RTLIB::SREM_I32, getIntrinsicName(RTLIB::SREM_I32));
+
+ // Unsigned remainder lib call names
+ setLibcallName(RTLIB::UREM_I16, getIntrinsicName(RTLIB::UREM_I16));
+ setLibcallName(RTLIB::UREM_I32, getIntrinsicName(RTLIB::UREM_I32));
+
+ // Floating point to signed int conversions.
+ setLibcallName(RTLIB::FPTOSINT_F32_I8,
+ getIntrinsicName(RTLIB::FPTOSINT_F32_I8));
+ setLibcallName(RTLIB::FPTOSINT_F32_I16,
+ getIntrinsicName(RTLIB::FPTOSINT_F32_I16));
+ setLibcallName(RTLIB::FPTOSINT_F32_I32,
+ getIntrinsicName(RTLIB::FPTOSINT_F32_I32));
+
+ // Signed int to floats.
+ setLibcallName(RTLIB::SINTTOFP_I32_F32,
+ getIntrinsicName(RTLIB::SINTTOFP_I32_F32));
+
+ // Floating points to unsigned ints.
+ setLibcallName(RTLIB::FPTOUINT_F32_I8,
+ getIntrinsicName(RTLIB::FPTOUINT_F32_I8));
+ setLibcallName(RTLIB::FPTOUINT_F32_I16,
+ getIntrinsicName(RTLIB::FPTOUINT_F32_I16));
+ setLibcallName(RTLIB::FPTOUINT_F32_I32,
+ getIntrinsicName(RTLIB::FPTOUINT_F32_I32));
+
+ // Unsigned int to floats.
+ setLibcallName(RTLIB::UINTTOFP_I32_F32,
+ getIntrinsicName(RTLIB::UINTTOFP_I32_F32));
+
+ // Floating point add, sub, mul ,div.
+ setLibcallName(RTLIB::ADD_F32, getIntrinsicName(RTLIB::ADD_F32));
+ setLibcallName(RTLIB::SUB_F32, getIntrinsicName(RTLIB::SUB_F32));
+ setLibcallName(RTLIB::MUL_F32, getIntrinsicName(RTLIB::MUL_F32));
+ setLibcallName(RTLIB::DIV_F32, getIntrinsicName(RTLIB::DIV_F32));
+
+ // Floationg point comparison
+ setLibcallName(RTLIB::UO_F32, getIntrinsicName(RTLIB::UO_F32));
+ setLibcallName(RTLIB::OLE_F32, getIntrinsicName(RTLIB::OLE_F32));
+ setLibcallName(RTLIB::OGE_F32, getIntrinsicName(RTLIB::OGE_F32));
+ setLibcallName(RTLIB::OLT_F32, getIntrinsicName(RTLIB::OLT_F32));
+ setLibcallName(RTLIB::OGT_F32, getIntrinsicName(RTLIB::OGT_F32));
+ setLibcallName(RTLIB::OEQ_F32, getIntrinsicName(RTLIB::OEQ_F32));
+ setLibcallName(RTLIB::UNE_F32, getIntrinsicName(RTLIB::UNE_F32));
+
+ // Return value comparisons of floating point calls.
+ setCmpLibcallCC(RTLIB::OEQ_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::UNE_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::OLT_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::OLE_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::OGE_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::OGT_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::UO_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::O_F32, ISD::SETEQ);
+
setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
setOperationAction(ISD::ExternalSymbol, MVT::i16, Custom);
setOperationAction(ISD::ADDC, MVT::i8, Custom);
setOperationAction(ISD::SUBE, MVT::i8, Custom);
setOperationAction(ISD::SUBC, MVT::i8, Custom);
+ setOperationAction(ISD::SUB, MVT::i8, Custom);
setOperationAction(ISD::ADD, MVT::i8, Custom);
setOperationAction(ISD::ADD, MVT::i16, Custom);
setOperationAction(ISD::CALL, MVT::i16, Custom);
setOperationAction(ISD::RET, MVT::Other, Custom);
- setOperationAction(ISD::MUL, MVT::i8, Custom);
- setOperationAction(ISD::MUL, MVT::i16, Expand);
- setOperationAction(ISD::MUL, MVT::i32, Expand);
+ setOperationAction(ISD::MUL, MVT::i8, Custom);
setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand);
- setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand);
- setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand);
- setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand);
- setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
setOperationAction(ISD::MULHU, MVT::i8, Expand);
- setOperationAction(ISD::MULHU, MVT::i16, Expand);
- setOperationAction(ISD::MULHU, MVT::i32, Expand);
setOperationAction(ISD::MULHS, MVT::i8, Expand);
- setOperationAction(ISD::MULHS, MVT::i16, Expand);
- setOperationAction(ISD::MULHS, MVT::i32, Expand);
setOperationAction(ISD::SRA, MVT::i8, Custom);
- setOperationAction(ISD::SRA, MVT::i16, Expand);
- setOperationAction(ISD::SRA, MVT::i32, Expand);
setOperationAction(ISD::SHL, MVT::i8, Custom);
- setOperationAction(ISD::SHL, MVT::i16, Expand);
- setOperationAction(ISD::SHL, MVT::i32, Expand);
setOperationAction(ISD::SRL, MVT::i8, Custom);
- setOperationAction(ISD::SRL, MVT::i16, Expand);
- setOperationAction(ISD::SRL, MVT::i32, Expand);
+
+ setOperationAction(ISD::ROTL, MVT::i8, Expand);
+ setOperationAction(ISD::ROTR, MVT::i8, Expand);
+
+ setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
// PIC16 does not support shift parts
- setOperationAction(ISD::SRA_PARTS, MVT::i8, Expand);
- setOperationAction(ISD::SRA_PARTS, MVT::i16, Expand);
- setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
+ setOperationAction(ISD::SRA_PARTS, MVT::i8, Expand);
setOperationAction(ISD::SHL_PARTS, MVT::i8, Expand);
- setOperationAction(ISD::SHL_PARTS, MVT::i16, Expand);
- setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRL_PARTS, MVT::i8, Expand);
- setOperationAction(ISD::SRL_PARTS, MVT::i16, Expand);
- setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
// PIC16 does not have a SETCC, expand it to SELECT_CC.
TargetLowering::ArgListEntry Entry;
for (unsigned i = 0; i != NumOps; ++i) {
Entry.Node = Ops[i];
- Entry.Ty = Entry.Node.getValueType().getTypeForMVT();
+ Entry.Ty = Entry.Node.getValueType().getTypeForMVT(*DAG.getContext());
Entry.isSExt = isSigned;
Entry.isZExt = !isSigned;
Args.push_back(Entry);
}
SDValue Callee = DAG.getExternalSymbol(getPIC16LibcallName(Call), MVT::i8);
- const Type *RetTy = RetVT.getTypeForMVT();
+ const Type *RetTy = RetVT.getTypeForMVT(*DAG.getContext());
std::pair<SDValue,SDValue> CallInfo =
LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false,
- false, CallingConv::C, false, Callee, Args, DAG, dl);
+ false, 0, CallingConv::C, false, Callee, Args, DAG, dl);
return CallInfo.first;
}
FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(SDValue(N,0));
// FIXME there isn't really debug info here
DebugLoc dl = FR->getDebugLoc();
- int Index = FR->getIndex();
// Expand FrameIndex like GlobalAddress and ExternalSymbol
// Also use Offset field for lo and hi parts. The default
// offset is zero.
- SDValue Offset = DAG.getConstant(0, MVT::i8);
- SDValue FI = DAG.getTargetFrameIndex(Index, MVT::i8);
- SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, FI, Offset);
- SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, FI, Offset);
+
+ SDValue ES;
+ int FrameOffset;
+ SDValue FI = SDValue(N,0);
+ LegalizeFrameIndex(FI, DAG, ES, FrameOffset);
+ SDValue Offset = DAG.getConstant(FrameOffset, MVT::i8);
+ SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, ES, Offset);
+ SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, ES, Offset);
return DAG.getNode(ISD::BUILD_PAIR, dl, N->getValueType(0), Lo, Hi);
}
if (Ptr.getOpcode() == ISD::ADD) {
SDValue OperLeft = Ptr.getOperand(0);
SDValue OperRight = Ptr.getOperand(1);
- if (OperLeft.getOpcode() == ISD::Constant) {
+ if ((OperLeft.getOpcode() == ISD::Constant) &&
+ (dyn_cast<ConstantSDNode>(OperLeft)->getZExtValue() < 32 )) {
Offset = dyn_cast<ConstantSDNode>(OperLeft)->getZExtValue();
Ptr = OperRight;
- } else if (OperRight.getOpcode() == ISD::Constant) {
+ } else if ((OperRight.getOpcode() == ISD::Constant) &&
+ (dyn_cast<ConstantSDNode>(OperRight)->getZExtValue() < 32 )){
Offset = dyn_cast<ConstantSDNode>(OperRight)->getZExtValue();
Ptr = OperLeft;
}
// Expansion of FrameIndex has Lo/Hi parts
if (isDirectAddress(Ptr)) {
SDValue TFI = Ptr.getOperand(0).getOperand(0);
+ int FrameOffset;
if (TFI.getOpcode() == ISD::TargetFrameIndex) {
- int FrameOffset;
LegalizeFrameIndex(TFI, DAG, Lo, FrameOffset);
Hi = DAG.getConstant(1, MVT::i8);
Offset += FrameOffset;
return;
+ } else if (TFI.getOpcode() == ISD::TargetExternalSymbol) {
+ // FrameIndex has already been expanded.
+ // Now just make use of its expansion
+ Lo = TFI;
+ Hi = DAG.getConstant(1, MVT::i8);
+ SDValue FOffset = Ptr.getOperand(0).getOperand(1);
+ assert (FOffset.getOpcode() == ISD::Constant &&
+ "Invalid operand of PIC16ISD::Lo");
+ Offset += dyn_cast<ConstantSDNode>(FOffset)->getZExtValue();
+ return;
}
}
// i.e. without any extension
MVT MemVT = LD->getMemoryVT();
unsigned MemBytes = MemVT.getSizeInBits() / 8;
+ // if MVT::i1 is extended to MVT::i8 then MemBytes will be zero
+ // So set it to one
+ if (MemBytes == 0) MemBytes = 1;
+
unsigned ExtdBytes = VT.getSizeInBits() / 8;
Offset = DAG.getConstant(LoadOffset, MVT::i8);
Tys = DAG.getVTList(MVT::i8, MVT::Other);
// For MemBytes generate PIC16Load with proper offset
- for (iter=0; iter<MemBytes; ++iter) {
+ for (iter=0; iter < MemBytes; ++iter) {
// Add the pointer offset if any
Offset = DAG.getConstant(iter + LoadOffset, MVT::i8);
Load = DAG.getNode(PIC16ISD::PIC16Load, dl, Tys, Chain, PtrLo, PtrHi,
for (iter=MemBytes; iter<ExtdBytes; ++iter) {
PICLoads.push_back(SRA);
}
- } else if (ISD::isZEXTLoad(N)) {
+ } else if (ISD::isZEXTLoad(N) || ISD::isEXTLoad(N)) {
+ //} else if (ISD::isZEXTLoad(N)) {
// ZeroExtendedLoad -- For all ExtdBytes use constant 0
SDValue ConstZero = DAG.getConstant(0, MVT::i8);
for (iter=MemBytes; iter<ExtdBytes; ++iter) {
// return should have odd number of operands
if ((Op.getNumOperands() % 2) == 0 ) {
- assert(0 && "Do not know how to return this many arguments!");
- abort();
+ llvm_unreachable("Do not know how to return this many arguments!");
}
// Number of values to return
// Generate new call with all the operands legal
return DAG.getCall(TheCall->getCallingConv(), dl,
TheCall->isVarArg(), TheCall->isTailCall(),
- TheCall->isInreg(), VTs, &Ops[0], Ops.size());
+ TheCall->isInreg(), VTs, &Ops[0], Ops.size(),
+ TheCall->getNumFixedArgs());
}
void PIC16TargetLowering::
static PIC16CC::CondCodes IntCCToPIC16CC(ISD::CondCode CC) {
switch (CC) {
- default: assert(0 && "Unknown condition code!");
+ default: llvm_unreachable("Unknown condition code!");
case ISD::SETNE: return PIC16CC::NE;
case ISD::SETEQ: return PIC16CC::EQ;
case ISD::SETGT: return PIC16CC::GT;
case ISD::SETLT: return PIC16CC::LT;
case ISD::SETLE: return PIC16CC::LE;
case ISD::SETULT: return PIC16CC::ULT;
- case ISD::SETULE: return PIC16CC::LE;
- case ISD::SETUGE: return PIC16CC::GE;
+ case ISD::SETULE: return PIC16CC::ULE;
+ case ISD::SETUGE: return PIC16CC::UGE;
case ISD::SETUGT: return PIC16CC::UGT;
}
}