1193323Sed//===-- MSP430ISelDAGToDAG.cpp - A dag to dag inst selector for MSP430 ----===// 2193323Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6193323Sed// 7193323Sed//===----------------------------------------------------------------------===// 8193323Sed// 9193323Sed// This file defines an instruction selector for the MSP430 target. 10193323Sed// 11193323Sed//===----------------------------------------------------------------------===// 12193323Sed 13193323Sed#include "MSP430.h" 14193323Sed#include "MSP430TargetMachine.h" 15193323Sed#include "llvm/CodeGen/MachineFrameInfo.h" 16193323Sed#include "llvm/CodeGen/MachineFunction.h" 17193323Sed#include "llvm/CodeGen/MachineInstrBuilder.h" 18193323Sed#include "llvm/CodeGen/MachineRegisterInfo.h" 19193323Sed#include "llvm/CodeGen/SelectionDAG.h" 20193323Sed#include "llvm/CodeGen/SelectionDAGISel.h" 21327952Sdim#include "llvm/CodeGen/TargetLowering.h" 22341825Sdim#include "llvm/Config/llvm-config.h" 23249423Sdim#include "llvm/IR/CallingConv.h" 24249423Sdim#include "llvm/IR/Constants.h" 25249423Sdim#include "llvm/IR/DerivedTypes.h" 26249423Sdim#include "llvm/IR/Function.h" 27249423Sdim#include "llvm/IR/Intrinsics.h" 28193323Sed#include "llvm/Support/Debug.h" 29198090Srdivacky#include "llvm/Support/ErrorHandling.h" 30198090Srdivacky#include "llvm/Support/raw_ostream.h" 31193323Sedusing namespace llvm; 32193323Sed 33276479Sdim#define DEBUG_TYPE "msp430-isel" 34276479Sdim 35199481Srdivackynamespace { 36199481Srdivacky struct MSP430ISelAddressMode { 37199481Srdivacky enum { 38199481Srdivacky RegBase, 39199481Srdivacky FrameIndexBase 40360784Sdim } BaseType = RegBase; 41199481Srdivacky 42199481Srdivacky struct { // This is really a union, discriminated by BaseType! 43199481Srdivacky SDValue Reg; 44360784Sdim int FrameIndex = 0; 45199481Srdivacky } Base; 46199481Srdivacky 47360784Sdim int16_t Disp = 0; 48360784Sdim const GlobalValue *GV = nullptr; 49360784Sdim const Constant *CP = nullptr; 50360784Sdim const BlockAddress *BlockAddr = nullptr; 51360784Sdim const char *ES = nullptr; 52360784Sdim int JT = -1; 53360784Sdim unsigned Align = 0; // CP alignment. 54199481Srdivacky 55360784Sdim MSP430ISelAddressMode() = default; 56199481Srdivacky 57199481Srdivacky bool hasSymbolicDisplacement() const { 58276479Sdim return GV != nullptr || CP != nullptr || ES != nullptr || JT != -1; 59199481Srdivacky } 60199481Srdivacky 61321369Sdim#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 62321369Sdim LLVM_DUMP_METHOD void dump() { 63199481Srdivacky errs() << "MSP430ISelAddressMode " << this << '\n'; 64276479Sdim if (BaseType == RegBase && Base.Reg.getNode() != nullptr) { 65199481Srdivacky errs() << "Base.Reg "; 66199481Srdivacky Base.Reg.getNode()->dump(); 67200581Srdivacky } else if (BaseType == FrameIndexBase) { 68199481Srdivacky errs() << " Base.FrameIndex " << Base.FrameIndex << '\n'; 69199481Srdivacky } 70199481Srdivacky errs() << " Disp " << Disp << '\n'; 71199481Srdivacky if (GV) { 72199481Srdivacky errs() << "GV "; 73199481Srdivacky GV->dump(); 74199481Srdivacky } else if (CP) { 75199481Srdivacky errs() << " CP "; 76199481Srdivacky CP->dump(); 77199481Srdivacky errs() << " Align" << Align << '\n'; 78199481Srdivacky } else if (ES) { 79199481Srdivacky errs() << "ES "; 80199481Srdivacky errs() << ES << '\n'; 81199481Srdivacky } else if (JT != -1) 82199481Srdivacky errs() << " JT" << JT << " Align" << Align << '\n'; 83199481Srdivacky } 84321369Sdim#endif 85199481Srdivacky }; 86199481Srdivacky} 87199481Srdivacky 88193323Sed/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine 89193323Sed/// instructions for SelectionDAG operations. 90193323Sed/// 91193323Sednamespace { 92193323Sed class MSP430DAGToDAGISel : public SelectionDAGISel { 93193323Sed public: 94193323Sed MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel) 95288943Sdim : SelectionDAGISel(TM, OptLevel) {} 96193323Sed 97344779Sdim private: 98314564Sdim StringRef getPassName() const override { 99193323Sed return "MSP430 DAG->DAG Pattern Instruction Selection"; 100193323Sed } 101193323Sed 102199481Srdivacky bool MatchAddress(SDValue N, MSP430ISelAddressMode &AM); 103199481Srdivacky bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM); 104199481Srdivacky bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM); 105199481Srdivacky 106288943Sdim bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, 107276479Sdim std::vector<SDValue> &OutOps) override; 108198090Srdivacky 109193323Sed // Include the pieces autogenerated from the target description. 110193323Sed #include "MSP430GenDAGISel.inc" 111193323Sed 112344779Sdim // Main method to transform nodes into machine nodes. 113309124Sdim void Select(SDNode *N) override; 114344779Sdim 115309124Sdim bool tryIndexedLoad(SDNode *Op); 116309124Sdim bool tryIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2, unsigned Opc8, 117309124Sdim unsigned Opc16); 118199481Srdivacky 119218893Sdim bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Disp); 120193323Sed }; 121193323Sed} // end anonymous namespace 122193323Sed 123193323Sed/// createMSP430ISelDag - This pass converts a legalized DAG into a 124193323Sed/// MSP430-specific DAG, ready for instruction scheduling. 125193323Sed/// 126193323SedFunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM, 127193323Sed CodeGenOpt::Level OptLevel) { 128193323Sed return new MSP430DAGToDAGISel(TM, OptLevel); 129193323Sed} 130193323Sed 131199481Srdivacky 132199481Srdivacky/// MatchWrapper - Try to match MSP430ISD::Wrapper node into an addressing mode. 133199481Srdivacky/// These wrap things that will resolve down into a symbol reference. If no 134199481Srdivacky/// match is possible, this returns true, otherwise it returns false. 135199481Srdivackybool MSP430DAGToDAGISel::MatchWrapper(SDValue N, MSP430ISelAddressMode &AM) { 136199481Srdivacky // If the addressing mode already has a symbol as the displacement, we can 137199481Srdivacky // never match another symbol. 138199481Srdivacky if (AM.hasSymbolicDisplacement()) 139193323Sed return true; 140199481Srdivacky 141199481Srdivacky SDValue N0 = N.getOperand(0); 142199481Srdivacky 143199481Srdivacky if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) { 144199481Srdivacky AM.GV = G->getGlobal(); 145199481Srdivacky AM.Disp += G->getOffset(); 146199481Srdivacky //AM.SymbolFlags = G->getTargetFlags(); 147199481Srdivacky } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) { 148199481Srdivacky AM.CP = CP->getConstVal(); 149199481Srdivacky AM.Align = CP->getAlignment(); 150199481Srdivacky AM.Disp += CP->getOffset(); 151199481Srdivacky //AM.SymbolFlags = CP->getTargetFlags(); 152199481Srdivacky } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) { 153199481Srdivacky AM.ES = S->getSymbol(); 154199481Srdivacky //AM.SymbolFlags = S->getTargetFlags(); 155199481Srdivacky } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) { 156199481Srdivacky AM.JT = J->getIndex(); 157199481Srdivacky //AM.SymbolFlags = J->getTargetFlags(); 158199481Srdivacky } else { 159199481Srdivacky AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress(); 160199481Srdivacky //AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags(); 161193323Sed } 162199481Srdivacky return false; 163199481Srdivacky} 164193323Sed 165199481Srdivacky/// MatchAddressBase - Helper for MatchAddress. Add the specified node to the 166199481Srdivacky/// specified addressing mode without any further recursion. 167199481Srdivackybool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) { 168199481Srdivacky // Is the base register already occupied? 169199481Srdivacky if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) { 170199481Srdivacky // If so, we cannot select it. 171199481Srdivacky return true; 172199481Srdivacky } 173193323Sed 174199481Srdivacky // Default, generate it as a register. 175199481Srdivacky AM.BaseType = MSP430ISelAddressMode::RegBase; 176199481Srdivacky AM.Base.Reg = N; 177199481Srdivacky return false; 178199481Srdivacky} 179199481Srdivacky 180199481Srdivackybool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) { 181341825Sdim LLVM_DEBUG(errs() << "MatchAddress: "; AM.dump()); 182199481Srdivacky 183199481Srdivacky switch (N.getOpcode()) { 184199481Srdivacky default: break; 185199481Srdivacky case ISD::Constant: { 186199481Srdivacky uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue(); 187199481Srdivacky AM.Disp += Val; 188199481Srdivacky return false; 189199481Srdivacky } 190199481Srdivacky 191199481Srdivacky case MSP430ISD::Wrapper: 192199481Srdivacky if (!MatchWrapper(N, AM)) 193199481Srdivacky return false; 194199481Srdivacky break; 195199481Srdivacky 196199481Srdivacky case ISD::FrameIndex: 197199481Srdivacky if (AM.BaseType == MSP430ISelAddressMode::RegBase 198276479Sdim && AM.Base.Reg.getNode() == nullptr) { 199199481Srdivacky AM.BaseType = MSP430ISelAddressMode::FrameIndexBase; 200199481Srdivacky AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex(); 201199481Srdivacky return false; 202193323Sed } 203193323Sed break; 204199481Srdivacky 205199481Srdivacky case ISD::ADD: { 206199481Srdivacky MSP430ISelAddressMode Backup = AM; 207199481Srdivacky if (!MatchAddress(N.getNode()->getOperand(0), AM) && 208199481Srdivacky !MatchAddress(N.getNode()->getOperand(1), AM)) 209199481Srdivacky return false; 210199481Srdivacky AM = Backup; 211199481Srdivacky if (!MatchAddress(N.getNode()->getOperand(1), AM) && 212199481Srdivacky !MatchAddress(N.getNode()->getOperand(0), AM)) 213199481Srdivacky return false; 214199481Srdivacky AM = Backup; 215199481Srdivacky 216199481Srdivacky break; 217199481Srdivacky } 218199481Srdivacky 219199481Srdivacky case ISD::OR: 220199481Srdivacky // Handle "X | C" as "X + C" iff X is known to have C bits clear. 221199481Srdivacky if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) { 222199481Srdivacky MSP430ISelAddressMode Backup = AM; 223199481Srdivacky uint64_t Offset = CN->getSExtValue(); 224199481Srdivacky // Start with the LHS as an addr mode. 225199481Srdivacky if (!MatchAddress(N.getOperand(0), AM) && 226199481Srdivacky // Address could not have picked a GV address for the displacement. 227276479Sdim AM.GV == nullptr && 228199481Srdivacky // Check to see if the LHS & C is zero. 229199481Srdivacky CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) { 230199481Srdivacky AM.Disp += Offset; 231199481Srdivacky return false; 232199481Srdivacky } 233199481Srdivacky AM = Backup; 234193323Sed } 235193323Sed break; 236199481Srdivacky } 237193323Sed 238199481Srdivacky return MatchAddressBase(N, AM); 239199481Srdivacky} 240193323Sed 241199481Srdivacky/// SelectAddr - returns true if it is able pattern match an addressing mode. 242199481Srdivacky/// It returns the operands which make up the maximal addressing mode it can 243199481Srdivacky/// match by reference. 244218893Sdimbool MSP430DAGToDAGISel::SelectAddr(SDValue N, 245199481Srdivacky SDValue &Base, SDValue &Disp) { 246199481Srdivacky MSP430ISelAddressMode AM; 247199481Srdivacky 248199481Srdivacky if (MatchAddress(N, AM)) 249199481Srdivacky return false; 250199481Srdivacky 251344779Sdim if (AM.BaseType == MSP430ISelAddressMode::RegBase) 252199481Srdivacky if (!AM.Base.Reg.getNode()) 253344779Sdim AM.Base.Reg = CurDAG->getRegister(MSP430::SR, MVT::i16); 254199481Srdivacky 255288943Sdim Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase) 256288943Sdim ? CurDAG->getTargetFrameIndex( 257288943Sdim AM.Base.FrameIndex, 258288943Sdim getTargetLowering()->getPointerTy(CurDAG->getDataLayout())) 259288943Sdim : AM.Base.Reg; 260199481Srdivacky 261199481Srdivacky if (AM.GV) 262261991Sdim Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(N), 263210299Sed MVT::i16, AM.Disp, 264199481Srdivacky 0/*AM.SymbolFlags*/); 265199481Srdivacky else if (AM.CP) 266199481Srdivacky Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16, 267199481Srdivacky AM.Align, AM.Disp, 0/*AM.SymbolFlags*/); 268199481Srdivacky else if (AM.ES) 269199481Srdivacky Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0/*AM.SymbolFlags*/); 270199481Srdivacky else if (AM.JT != -1) 271199481Srdivacky Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/); 272199481Srdivacky else if (AM.BlockAddr) 273243830Sdim Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, 0, 274243830Sdim 0/*AM.SymbolFlags*/); 275199481Srdivacky else 276288943Sdim Disp = CurDAG->getTargetConstant(AM.Disp, SDLoc(N), MVT::i16); 277199481Srdivacky 278193323Sed return true; 279193323Sed} 280193323Sed 281198090Srdivackybool MSP430DAGToDAGISel:: 282288943SdimSelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, 283198090Srdivacky std::vector<SDValue> &OutOps) { 284198090Srdivacky SDValue Op0, Op1; 285288943Sdim switch (ConstraintID) { 286198090Srdivacky default: return true; 287288943Sdim case InlineAsm::Constraint_m: // memory 288218893Sdim if (!SelectAddr(Op, Op0, Op1)) 289198090Srdivacky return true; 290198090Srdivacky break; 291198090Srdivacky } 292193323Sed 293198090Srdivacky OutOps.push_back(Op0); 294198090Srdivacky OutOps.push_back(Op1); 295198090Srdivacky return false; 296198090Srdivacky} 297198090Srdivacky 298199481Srdivackystatic bool isValidIndexedLoad(const LoadSDNode *LD) { 299199481Srdivacky ISD::MemIndexedMode AM = LD->getAddressingMode(); 300199481Srdivacky if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD) 301199481Srdivacky return false; 302199481Srdivacky 303199481Srdivacky EVT VT = LD->getMemoryVT(); 304199481Srdivacky 305199481Srdivacky switch (VT.getSimpleVT().SimpleTy) { 306199481Srdivacky case MVT::i8: 307199481Srdivacky // Sanity check 308199481Srdivacky if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 1) 309199481Srdivacky return false; 310199481Srdivacky 311199481Srdivacky break; 312199481Srdivacky case MVT::i16: 313199481Srdivacky // Sanity check 314199481Srdivacky if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 2) 315199481Srdivacky return false; 316199481Srdivacky 317199481Srdivacky break; 318199481Srdivacky default: 319199481Srdivacky return false; 320199481Srdivacky } 321199481Srdivacky 322199481Srdivacky return true; 323199481Srdivacky} 324199481Srdivacky 325309124Sdimbool MSP430DAGToDAGISel::tryIndexedLoad(SDNode *N) { 326202375Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N); 327199481Srdivacky if (!isValidIndexedLoad(LD)) 328309124Sdim return false; 329199481Srdivacky 330199481Srdivacky MVT VT = LD->getMemoryVT().getSimpleVT(); 331199481Srdivacky 332199481Srdivacky unsigned Opcode = 0; 333199481Srdivacky switch (VT.SimpleTy) { 334199481Srdivacky case MVT::i8: 335344779Sdim Opcode = MSP430::MOV8rp; 336199481Srdivacky break; 337199481Srdivacky case MVT::i16: 338344779Sdim Opcode = MSP430::MOV16rp; 339199481Srdivacky break; 340199481Srdivacky default: 341309124Sdim return false; 342199481Srdivacky } 343199481Srdivacky 344309124Sdim ReplaceNode(N, 345309124Sdim CurDAG->getMachineNode(Opcode, SDLoc(N), VT, MVT::i16, MVT::Other, 346309124Sdim LD->getBasePtr(), LD->getChain())); 347309124Sdim return true; 348199481Srdivacky} 349199481Srdivacky 350309124Sdimbool MSP430DAGToDAGISel::tryIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2, 351309124Sdim unsigned Opc8, unsigned Opc16) { 352199481Srdivacky if (N1.getOpcode() == ISD::LOAD && 353199481Srdivacky N1.hasOneUse() && 354207618Srdivacky IsLegalToFold(N1, Op, Op, OptLevel)) { 355199481Srdivacky LoadSDNode *LD = cast<LoadSDNode>(N1); 356199481Srdivacky if (!isValidIndexedLoad(LD)) 357309124Sdim return false; 358199481Srdivacky 359199481Srdivacky MVT VT = LD->getMemoryVT().getSimpleVT(); 360199481Srdivacky unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8); 361344779Sdim MachineMemOperand *MemRef = cast<MemSDNode>(N1)->getMemOperand(); 362199481Srdivacky SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() }; 363199481Srdivacky SDNode *ResNode = 364276479Sdim CurDAG->SelectNodeTo(Op, Opc, VT, MVT::i16, MVT::Other, Ops0); 365344779Sdim CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {MemRef}); 366199481Srdivacky // Transfer chain. 367199481Srdivacky ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 2)); 368199481Srdivacky // Transfer writeback. 369199481Srdivacky ReplaceUses(SDValue(N1.getNode(), 1), SDValue(ResNode, 1)); 370309124Sdim return true; 371199481Srdivacky } 372199481Srdivacky 373309124Sdim return false; 374199481Srdivacky} 375199481Srdivacky 376199481Srdivacky 377309124Sdimvoid MSP430DAGToDAGISel::Select(SDNode *Node) { 378261991Sdim SDLoc dl(Node); 379193323Sed 380193323Sed // If we have a custom node, we already have selected! 381193323Sed if (Node->isMachineOpcode()) { 382341825Sdim LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); 383255804Sdim Node->setNodeId(-1); 384309124Sdim return; 385193323Sed } 386193323Sed 387193323Sed // Few custom selection stuff. 388193323Sed switch (Node->getOpcode()) { 389193323Sed default: break; 390193323Sed case ISD::FrameIndex: { 391202375Srdivacky assert(Node->getValueType(0) == MVT::i16); 392193323Sed int FI = cast<FrameIndexSDNode>(Node)->getIndex(); 393193323Sed SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16); 394309124Sdim if (Node->hasOneUse()) { 395321369Sdim CurDAG->SelectNodeTo(Node, MSP430::ADDframe, MVT::i16, TFI, 396309124Sdim CurDAG->getTargetConstant(0, dl, MVT::i16)); 397309124Sdim return; 398309124Sdim } 399309124Sdim ReplaceNode(Node, CurDAG->getMachineNode( 400321369Sdim MSP430::ADDframe, dl, MVT::i16, TFI, 401309124Sdim CurDAG->getTargetConstant(0, dl, MVT::i16))); 402309124Sdim return; 403193323Sed } 404199481Srdivacky case ISD::LOAD: 405309124Sdim if (tryIndexedLoad(Node)) 406309124Sdim return; 407199481Srdivacky // Other cases are autogenerated. 408199481Srdivacky break; 409199481Srdivacky case ISD::ADD: 410309124Sdim if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1), 411344779Sdim MSP430::ADD8rp, MSP430::ADD16rp)) 412309124Sdim return; 413309124Sdim else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0), 414344779Sdim MSP430::ADD8rp, MSP430::ADD16rp)) 415309124Sdim return; 416199481Srdivacky 417199481Srdivacky // Other cases are autogenerated. 418199481Srdivacky break; 419199481Srdivacky case ISD::SUB: 420309124Sdim if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1), 421344779Sdim MSP430::SUB8rp, MSP430::SUB16rp)) 422309124Sdim return; 423199481Srdivacky 424199481Srdivacky // Other cases are autogenerated. 425199481Srdivacky break; 426199481Srdivacky case ISD::AND: 427309124Sdim if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1), 428344779Sdim MSP430::AND8rp, MSP430::AND16rp)) 429309124Sdim return; 430309124Sdim else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0), 431344779Sdim MSP430::AND8rp, MSP430::AND16rp)) 432309124Sdim return; 433199481Srdivacky 434199481Srdivacky // Other cases are autogenerated. 435199481Srdivacky break; 436199481Srdivacky case ISD::OR: 437309124Sdim if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1), 438344779Sdim MSP430::BIS8rp, MSP430::BIS16rp)) 439309124Sdim return; 440309124Sdim else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0), 441344779Sdim MSP430::BIS8rp, MSP430::BIS16rp)) 442309124Sdim return; 443199481Srdivacky 444199481Srdivacky // Other cases are autogenerated. 445199481Srdivacky break; 446199481Srdivacky case ISD::XOR: 447309124Sdim if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1), 448344779Sdim MSP430::XOR8rp, MSP430::XOR16rp)) 449309124Sdim return; 450309124Sdim else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0), 451344779Sdim MSP430::XOR8rp, MSP430::XOR16rp)) 452309124Sdim return; 453199481Srdivacky 454199481Srdivacky // Other cases are autogenerated. 455199481Srdivacky break; 456193323Sed } 457193323Sed 458193323Sed // Select the default instruction 459309124Sdim SelectCode(Node); 460193323Sed} 461