diff options
Diffstat (limited to 'lib/Target/MSP430/MSP430ISelLowering.cpp')
-rw-r--r-- | lib/Target/MSP430/MSP430ISelLowering.cpp | 127 |
1 files changed, 84 insertions, 43 deletions
diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index f5b2bda5d1e4..3e706134afc5 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -95,6 +95,8 @@ MSP430TargetLowering::MSP430TargetLowering(const TargetMachine &TM, setOperationAction(ISD::SIGN_EXTEND, MVT::i16, Custom); setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i8, Expand); setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i16, Expand); + setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); setOperationAction(ISD::CTTZ, MVT::i8, Expand); setOperationAction(ISD::CTTZ, MVT::i16, Expand); @@ -217,8 +219,6 @@ MSP430TargetLowering::MSP430TargetLowering(const TargetMachine &TM, // { RTLIB::NEG_F64, "__mspabi_negd", ISD::SETCC_INVALID }, // { RTLIB::NEG_F32, "__mspabi_negf", ISD::SETCC_INVALID }, - // TODO: SLL/SRA/SRL are in libgcc, RLL isn't - // Universal Integer Operations - EABI Table 9 { RTLIB::SDIV_I16, "__mspabi_divi", ISD::SETCC_INVALID }, { RTLIB::SDIV_I32, "__mspabi_divli", ISD::SETCC_INVALID }, @@ -233,6 +233,13 @@ MSP430TargetLowering::MSP430TargetLowering(const TargetMachine &TM, { RTLIB::UREM_I32, "__mspabi_remul", ISD::SETCC_INVALID }, { RTLIB::UREM_I64, "__mspabi_remull", ISD::SETCC_INVALID }, + // Bitwise Operations - EABI Table 10 + // TODO: __mspabi_[srli/srai/slli] ARE implemented in libgcc + { RTLIB::SRL_I32, "__mspabi_srll", ISD::SETCC_INVALID }, + { RTLIB::SRA_I32, "__mspabi_sral", ISD::SETCC_INVALID }, + { RTLIB::SHL_I32, "__mspabi_slll", ISD::SETCC_INVALID }, + // __mspabi_[srlll/srall/sllll/rlli/rlll] are NOT implemented in libgcc + }; for (const auto &LC : LibraryCalls) { @@ -940,30 +947,40 @@ SDValue MSP430TargetLowering::LowerShifts(SDValue Op, // Expand non-constant shifts to loops: if (!isa<ConstantSDNode>(N->getOperand(1))) - switch (Opc) { - default: llvm_unreachable("Invalid shift opcode!"); - case ISD::SHL: - return DAG.getNode(MSP430ISD::SHL, dl, - VT, N->getOperand(0), N->getOperand(1)); - case ISD::SRA: - return DAG.getNode(MSP430ISD::SRA, dl, - VT, N->getOperand(0), N->getOperand(1)); - case ISD::SRL: - return DAG.getNode(MSP430ISD::SRL, dl, - VT, N->getOperand(0), N->getOperand(1)); - } + return Op; uint64_t ShiftAmount = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue(); // Expand the stuff into sequence of shifts. - // FIXME: for some shift amounts this might be done better! - // E.g.: foo >> (8 + N) => sxt(swpb(foo)) >> N SDValue Victim = N->getOperand(0); + if (ShiftAmount >= 8) { + assert(VT == MVT::i16 && "Can not shift i8 by 8 and more"); + switch(Opc) { + default: + llvm_unreachable("Unknown shift"); + case ISD::SHL: + // foo << (8 + N) => swpb(zext(foo)) << N + Victim = DAG.getZeroExtendInReg(Victim, dl, MVT::i8); + Victim = DAG.getNode(ISD::BSWAP, dl, VT, Victim); + break; + case ISD::SRA: + case ISD::SRL: + // foo >> (8 + N) => sxt(swpb(foo)) >> N + Victim = DAG.getNode(ISD::BSWAP, dl, VT, Victim); + Victim = (Opc == ISD::SRA) + ? DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, VT, Victim, + DAG.getValueType(MVT::i8)) + : DAG.getZeroExtendInReg(Victim, dl, MVT::i8); + break; + } + ShiftAmount -= 8; + } + if (Opc == ISD::SRL && ShiftAmount) { // Emit a special goodness here: // srl A, 1 => clrc; rrc A - Victim = DAG.getNode(MSP430ISD::RRC, dl, VT, Victim); + Victim = DAG.getNode(MSP430ISD::RRCL, dl, VT, Victim); ShiftAmount -= 1; } @@ -1342,15 +1359,14 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const { case MSP430ISD::RRA: return "MSP430ISD::RRA"; case MSP430ISD::RLA: return "MSP430ISD::RLA"; case MSP430ISD::RRC: return "MSP430ISD::RRC"; + case MSP430ISD::RRCL: return "MSP430ISD::RRCL"; case MSP430ISD::CALL: return "MSP430ISD::CALL"; case MSP430ISD::Wrapper: return "MSP430ISD::Wrapper"; case MSP430ISD::BR_CC: return "MSP430ISD::BR_CC"; case MSP430ISD::CMP: return "MSP430ISD::CMP"; case MSP430ISD::SETCC: return "MSP430ISD::SETCC"; case MSP430ISD::SELECT_CC: return "MSP430ISD::SELECT_CC"; - case MSP430ISD::SHL: return "MSP430ISD::SHL"; - case MSP430ISD::SRA: return "MSP430ISD::SRA"; - case MSP430ISD::SRL: return "MSP430ISD::SRL"; + case MSP430ISD::DADD: return "MSP430ISD::DADD"; } return nullptr; } @@ -1397,33 +1413,49 @@ MSP430TargetLowering::EmitShiftInstr(MachineInstr &MI, const TargetInstrInfo &TII = *F->getSubtarget().getInstrInfo(); unsigned Opc; + bool ClearCarry = false; const TargetRegisterClass * RC; switch (MI.getOpcode()) { default: llvm_unreachable("Invalid shift opcode!"); case MSP430::Shl8: - Opc = MSP430::SHL8r1; - RC = &MSP430::GR8RegClass; - break; + Opc = MSP430::ADD8rr; + RC = &MSP430::GR8RegClass; + break; case MSP430::Shl16: - Opc = MSP430::SHL16r1; - RC = &MSP430::GR16RegClass; - break; + Opc = MSP430::ADD16rr; + RC = &MSP430::GR16RegClass; + break; case MSP430::Sra8: - Opc = MSP430::SAR8r1; - RC = &MSP430::GR8RegClass; - break; + Opc = MSP430::RRA8r; + RC = &MSP430::GR8RegClass; + break; case MSP430::Sra16: - Opc = MSP430::SAR16r1; - RC = &MSP430::GR16RegClass; - break; + Opc = MSP430::RRA16r; + RC = &MSP430::GR16RegClass; + break; case MSP430::Srl8: - Opc = MSP430::SAR8r1c; - RC = &MSP430::GR8RegClass; - break; + ClearCarry = true; + Opc = MSP430::RRC8r; + RC = &MSP430::GR8RegClass; + break; case MSP430::Srl16: - Opc = MSP430::SAR16r1c; - RC = &MSP430::GR16RegClass; - break; + ClearCarry = true; + Opc = MSP430::RRC16r; + RC = &MSP430::GR16RegClass; + break; + case MSP430::Rrcl8: + case MSP430::Rrcl16: { + BuildMI(*BB, MI, dl, TII.get(MSP430::BIC16rc), MSP430::SR) + .addReg(MSP430::SR).addImm(1); + unsigned SrcReg = MI.getOperand(1).getReg(); + unsigned DstReg = MI.getOperand(0).getReg(); + unsigned RrcOpc = MI.getOpcode() == MSP430::Rrcl16 + ? MSP430::RRC16r : MSP430::RRC8r; + BuildMI(*BB, MI, dl, TII.get(RrcOpc), DstReg) + .addReg(SrcReg); + MI.eraseFromParent(); // The pseudo instruction is gone now. + return BB; + } } const BasicBlock *LLVM_BB = BB->getBasicBlock(); @@ -1476,8 +1508,16 @@ MSP430TargetLowering::EmitShiftInstr(MachineInstr &MI, BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftAmtReg) .addReg(ShiftAmtSrcReg).addMBB(BB) .addReg(ShiftAmtReg2).addMBB(LoopBB); - BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2) - .addReg(ShiftReg); + if (ClearCarry) + BuildMI(LoopBB, dl, TII.get(MSP430::BIC16rc), MSP430::SR) + .addReg(MSP430::SR).addImm(1); + if (Opc == MSP430::ADD8rr || Opc == MSP430::ADD16rr) + BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2) + .addReg(ShiftReg) + .addReg(ShiftReg); + else + BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2) + .addReg(ShiftReg); BuildMI(LoopBB, dl, TII.get(MSP430::SUB8ri), ShiftAmtReg2) .addReg(ShiftAmtReg).addImm(1); BuildMI(LoopBB, dl, TII.get(MSP430::JCC)) @@ -1499,9 +1539,10 @@ MSP430TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const { unsigned Opc = MI.getOpcode(); - if (Opc == MSP430::Shl8 || Opc == MSP430::Shl16 || - Opc == MSP430::Sra8 || Opc == MSP430::Sra16 || - Opc == MSP430::Srl8 || Opc == MSP430::Srl16) + if (Opc == MSP430::Shl8 || Opc == MSP430::Shl16 || + Opc == MSP430::Sra8 || Opc == MSP430::Sra16 || + Opc == MSP430::Srl8 || Opc == MSP430::Srl16 || + Opc == MSP430::Rrcl8 || Opc == MSP430::Rrcl16) return EmitShiftInstr(MI, BB); const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo(); |