diff --git a/lib/Target/MSP430/MSP430AsmPrinter.cpp b/lib/Target/MSP430/MSP430AsmPrinter.cpp index e8004a7d1b4..6f1c8ebfd08 100644 --- a/lib/Target/MSP430/MSP430AsmPrinter.cpp +++ b/lib/Target/MSP430/MSP430AsmPrinter.cpp @@ -47,7 +47,10 @@ namespace { return "MSP430 Assembly Printer"; } - void printOperand(const MachineInstr *MI, int OpNum); + void printOperand(const MachineInstr *MI, int OpNum, + const char* Modifier = 0); + void printSrcMemOperand(const MachineInstr *MI, int OpNum, + const char* Modifier = 0); bool printInstruction(const MachineInstr *MI); // autogenerated. void printMachineInstruction(const MachineInstr * MI); bool runOnMachineFunction(MachineFunction &F); @@ -119,7 +122,8 @@ void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) { assert(0 && "Should not happen"); } -void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum) { +void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, + const char* Modifier) { const MachineOperand &MO = MI->getOperand(OpNum); switch (MO.getType()) { case MachineOperand::MO_Register: @@ -129,7 +133,9 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum) { assert(0 && "not implemented"); break; case MachineOperand::MO_Immediate: - O << "#" << MO.getImm(); + if (!Modifier || strcmp(Modifier, "nohash")) + O << '#'; + O << MO.getImm(); break; case MachineOperand::MO_MachineBasicBlock: printBasicBlockLabel(MO.getMBB()); @@ -138,3 +144,21 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum) { assert(0 && "Not implemented yet!"); } } + +void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, + const char* Modifier) { + const MachineOperand &Disp = MI->getOperand(OpNum); + assert(Disp.isImm() && "Displacement can be only immediate!"); + + // Special case: 0(Reg) -> @Reg + if (Disp.getImm() == 0) { + O << "@"; + printOperand(MI, OpNum + 1); + } else { + printOperand(MI, OpNum, "nohash"); + O << '('; + printOperand(MI, OpNum + 1); + O << ')'; + } +} + diff --git a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp index 0ad8752e88f..3b28668f550 100644 --- a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp +++ b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp @@ -57,6 +57,7 @@ namespace { private: SDNode *Select(SDValue Op); + bool SelectAddr(SDValue Op, SDValue Addr, SDValue &Disp, SDValue &Base); #ifndef NDEBUG unsigned Indent; @@ -71,6 +72,38 @@ FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM) { return new MSP430DAGToDAGISel(TM); } +bool MSP430DAGToDAGISel::SelectAddr(SDValue Op, SDValue Addr, + SDValue &Disp, SDValue &Base) { + // We don't support frame index stuff yet. + if (isa(Addr)) + return false; + + // Operand is a result from ADD with constant operand which fits into i16. + if (Addr.getOpcode() == ISD::ADD) { + if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1))) { + uint64_t CVal = CN->getZExtValue(); + // Offset should fit into 16 bits. + if (((CVal << 48) >> 48) == CVal) { + // We don't support frame index stuff yet. + if (isa(Addr.getOperand(0))) + return false; + + Base = Addr.getOperand(0); + Disp = CurDAG->getTargetConstant(CVal, MVT::i16); + + return true; + } + } + } + + Base = Addr; + Disp = CurDAG->getTargetConstant(0, MVT::i16); + + return true; +} + + + /// InstructionSelect - This callback is invoked by /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. void MSP430DAGToDAGISel::InstructionSelect() { diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index e7149e541ec..bd0db9bed42 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -53,6 +53,12 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) : // shifts of the whole bitwidth 1 bit per step. setShiftAmountType(MVT::i8); + setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); + setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand); + setOperationAction(ISD::SRA, MVT::i16, Custom); setOperationAction(ISD::RET, MVT::Other, Custom); } diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td index 44e3925531f..4a261e415c6 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.td +++ b/lib/Target/MSP430/MSP430InstrInfo.td @@ -32,15 +32,35 @@ def MSP430retflag : SDNode<"MSP430ISD::RET_FLAG", SDTNone, def MSP430rra : SDNode<"MSP430ISD::RRA", SDTIntUnaryOp, []>; //===----------------------------------------------------------------------===// -// Pseudo Instructions +// MSP430 Operand Definitions. //===----------------------------------------------------------------------===// +// Address operand +def memsrc : Operand { + let PrintMethod = "printSrcMemOperand"; + let MIOperandInfo = (ops i16imm, GR16); +} + + +//===----------------------------------------------------------------------===// +// MSP430 Complex Pattern Definitions. +//===----------------------------------------------------------------------===// + +def addr : ComplexPattern; + +//===----------------------------------------------------------------------===// +// Pattern Fragments +def zextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (zextloadi8 node:$ptr))>; +def extloadi16i8 : PatFrag<(ops node:$ptr), (i16 ( extloadi8 node:$ptr))>; + +//===----------------------------------------------------------------------===// +// Pseudo Instructions + let neverHasSideEffects = 1 in def NOP : Pseudo<(outs), (ins), "nop", []>; //===----------------------------------------------------------------------===// // Real Instructions -//===----------------------------------------------------------------------===// // FIXME: Provide proper encoding! let isReturn = 1, isTerminator = 1 in { @@ -52,25 +72,40 @@ let isReturn = 1, isTerminator = 1 in { // FIXME: Provide proper encoding! let neverHasSideEffects = 1 in { -def MOV16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "mov.w\t{$src, $dst|$dst, $src}", - []>; def MOV8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src), "mov.b\t{$src, $dst|$dst, $src}", []>; +def MOV16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src), + "mov.w\t{$src, $dst|$dst, $src}", + []>; } // FIXME: Provide proper encoding! let isReMaterializable = 1, isAsCheapAsAMove = 1 in { -def MOV16ri : Pseudo<(outs GR16:$dst), (ins i16imm:$src), - "mov.w\t{$src, $dst|$dst, $src}", - [(set GR16:$dst, imm:$src)]>; def MOV8ri : Pseudo<(outs GR8:$dst), (ins i8imm:$src), "mov.b\t{$src, $dst|$dst, $src}", [(set GR8:$dst, imm:$src)]>; - +def MOV16ri : Pseudo<(outs GR16:$dst), (ins i16imm:$src), + "mov.w\t{$src, $dst|$dst, $src}", + [(set GR16:$dst, imm:$src)]>; } +let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { +def MOV8rm : Pseudo<(outs GR8:$dst), (ins memsrc:$src), + "mov.b\t{$src, $dst|$dst, $src}", + [(set GR8:$dst, (load addr:$src))]>; +def MOV16rm : Pseudo<(outs GR16:$dst), (ins memsrc:$src), + "mov.w\t{$src, $dst|$dst, $src}", + [(set GR16:$dst, (load addr:$src))]>; +} + +def MOVZX16rr8 : Pseudo<(outs GR16:$dst), (ins GR8:$src), + "mov.b\t{$src, $dst|$dst, $src}", + [(set GR16:$dst, (zext GR8:$src))]>; +def MOVZX16rm8 : Pseudo<(outs GR16:$dst), (ins memsrc:$src), + "mov.b\t{$src, $dst|$dst, $src}", + [(set GR16:$dst, (zextloadi16i8 addr:$src))]>; + //===----------------------------------------------------------------------===// // Arithmetic Instructions @@ -232,3 +267,9 @@ def OR8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), [(set GR8:$dst, (or GR8:$src1, imm:$src2))]>; } // isTwoAddress = 1 + +//===----------------------------------------------------------------------===// +// Non-Instruction Patterns + +// extload +def : Pat<(extloadi16i8 addr:$src), (MOVZX16rm8 addr:$src)>;