10b57cec5SDimitry Andric //===-- AVRISelLowering.cpp - AVR DAG Lowering Implementation -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines the interfaces that AVR uses to lower LLVM code into a 100b57cec5SDimitry Andric // selection DAG. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "AVRISelLowering.h" 150b57cec5SDimitry Andric 1681ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h" 175ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h" 18349cc55cSDimitry Andric #include "llvm/ADT/StringSwitch.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 250b57cec5SDimitry Andric #include "llvm/IR/Function.h" 260b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #include "AVR.h" 290b57cec5SDimitry Andric #include "AVRMachineFunctionInfo.h" 300b57cec5SDimitry Andric #include "AVRSubtarget.h" 310b57cec5SDimitry Andric #include "AVRTargetMachine.h" 320b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCTargetDesc.h" 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric namespace llvm { 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric AVRTargetLowering::AVRTargetLowering(const AVRTargetMachine &TM, 370b57cec5SDimitry Andric const AVRSubtarget &STI) 380b57cec5SDimitry Andric : TargetLowering(TM), Subtarget(STI) { 390b57cec5SDimitry Andric // Set up the register classes. 400b57cec5SDimitry Andric addRegisterClass(MVT::i8, &AVR::GPR8RegClass); 410b57cec5SDimitry Andric addRegisterClass(MVT::i16, &AVR::DREGSRegClass); 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric // Compute derived properties from the register classes. 440b57cec5SDimitry Andric computeRegisterProperties(Subtarget.getRegisterInfo()); 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric setBooleanContents(ZeroOrOneBooleanContent); 470b57cec5SDimitry Andric setBooleanVectorContents(ZeroOrOneBooleanContent); 480b57cec5SDimitry Andric setSchedulingPreference(Sched::RegPressure); 490b57cec5SDimitry Andric setStackPointerRegisterToSaveRestore(AVR::SP); 500b57cec5SDimitry Andric setSupportsUnalignedAtomics(true); 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); 530b57cec5SDimitry Andric setOperationAction(ISD::BlockAddress, MVT::i16, Custom); 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 560b57cec5SDimitry Andric setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); 570b57cec5SDimitry Andric setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i8, Expand); 580b57cec5SDimitry Andric setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i16, Expand); 590b57cec5SDimitry Andric 60bdd1243dSDimitry Andric setOperationAction(ISD::INLINEASM, MVT::Other, Custom); 61bdd1243dSDimitry Andric 620b57cec5SDimitry Andric for (MVT VT : MVT::integer_valuetypes()) { 630b57cec5SDimitry Andric for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) { 640b57cec5SDimitry Andric setLoadExtAction(N, VT, MVT::i1, Promote); 650b57cec5SDimitry Andric setLoadExtAction(N, VT, MVT::i8, Expand); 660b57cec5SDimitry Andric } 670b57cec5SDimitry Andric } 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric setTruncStoreAction(MVT::i16, MVT::i8, Expand); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric for (MVT VT : MVT::integer_valuetypes()) { 720b57cec5SDimitry Andric setOperationAction(ISD::ADDC, VT, Legal); 730b57cec5SDimitry Andric setOperationAction(ISD::SUBC, VT, Legal); 740b57cec5SDimitry Andric setOperationAction(ISD::ADDE, VT, Legal); 750b57cec5SDimitry Andric setOperationAction(ISD::SUBE, VT, Legal); 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric // sub (x, imm) gets canonicalized to add (x, -imm), so for illegal types 790b57cec5SDimitry Andric // revert into a sub since we don't have an add with immediate instruction. 800b57cec5SDimitry Andric setOperationAction(ISD::ADD, MVT::i32, Custom); 810b57cec5SDimitry Andric setOperationAction(ISD::ADD, MVT::i64, Custom); 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric // our shift instructions are only able to shift 1 bit at a time, so handle 840b57cec5SDimitry Andric // this in a custom way. 850b57cec5SDimitry Andric setOperationAction(ISD::SRA, MVT::i8, Custom); 860b57cec5SDimitry Andric setOperationAction(ISD::SHL, MVT::i8, Custom); 870b57cec5SDimitry Andric setOperationAction(ISD::SRL, MVT::i8, Custom); 880b57cec5SDimitry Andric setOperationAction(ISD::SRA, MVT::i16, Custom); 890b57cec5SDimitry Andric setOperationAction(ISD::SHL, MVT::i16, Custom); 900b57cec5SDimitry Andric setOperationAction(ISD::SRL, MVT::i16, Custom); 91bdd1243dSDimitry Andric setOperationAction(ISD::SRA, MVT::i32, Custom); 92bdd1243dSDimitry Andric setOperationAction(ISD::SHL, MVT::i32, Custom); 93bdd1243dSDimitry Andric setOperationAction(ISD::SRL, MVT::i32, Custom); 940b57cec5SDimitry Andric setOperationAction(ISD::SHL_PARTS, MVT::i16, Expand); 950b57cec5SDimitry Andric setOperationAction(ISD::SRA_PARTS, MVT::i16, Expand); 960b57cec5SDimitry Andric setOperationAction(ISD::SRL_PARTS, MVT::i16, Expand); 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric setOperationAction(ISD::ROTL, MVT::i8, Custom); 990b57cec5SDimitry Andric setOperationAction(ISD::ROTL, MVT::i16, Expand); 1000b57cec5SDimitry Andric setOperationAction(ISD::ROTR, MVT::i8, Custom); 1010b57cec5SDimitry Andric setOperationAction(ISD::ROTR, MVT::i16, Expand); 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i8, Custom); 1040b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i16, Custom); 1050b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i32, Custom); 1060b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i64, Custom); 1070b57cec5SDimitry Andric setOperationAction(ISD::BRCOND, MVT::Other, Expand); 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i8, Custom); 1100b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i16, Custom); 1110b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i32, Expand); 1120b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i64, Expand); 1130b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::i8, Custom); 1140b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::i16, Custom); 1150b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::i32, Custom); 1160b57cec5SDimitry Andric setOperationAction(ISD::SETCC, MVT::i64, Custom); 1170b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::i8, Expand); 1180b57cec5SDimitry Andric setOperationAction(ISD::SELECT, MVT::i16, Expand); 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric setOperationAction(ISD::BSWAP, MVT::i16, Expand); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric // Add support for postincrement and predecrement load/stores. 1230b57cec5SDimitry Andric setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal); 1240b57cec5SDimitry Andric setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal); 1250b57cec5SDimitry Andric setIndexedLoadAction(ISD::PRE_DEC, MVT::i8, Legal); 1260b57cec5SDimitry Andric setIndexedLoadAction(ISD::PRE_DEC, MVT::i16, Legal); 1270b57cec5SDimitry Andric setIndexedStoreAction(ISD::POST_INC, MVT::i8, Legal); 1280b57cec5SDimitry Andric setIndexedStoreAction(ISD::POST_INC, MVT::i16, Legal); 1290b57cec5SDimitry Andric setIndexedStoreAction(ISD::PRE_DEC, MVT::i8, Legal); 1300b57cec5SDimitry Andric setIndexedStoreAction(ISD::PRE_DEC, MVT::i16, Legal); 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric setOperationAction(ISD::BR_JT, MVT::Other, Expand); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric setOperationAction(ISD::VASTART, MVT::Other, Custom); 1350b57cec5SDimitry Andric setOperationAction(ISD::VAEND, MVT::Other, Expand); 1360b57cec5SDimitry Andric setOperationAction(ISD::VAARG, MVT::Other, Expand); 1370b57cec5SDimitry Andric setOperationAction(ISD::VACOPY, MVT::Other, Expand); 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric // Atomic operations which must be lowered to rtlib calls 1400b57cec5SDimitry Andric for (MVT VT : MVT::integer_valuetypes()) { 1410b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_SWAP, VT, Expand); 1420b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_CMP_SWAP, VT, Expand); 1430b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_LOAD_NAND, VT, Expand); 1440b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_LOAD_MAX, VT, Expand); 1450b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_LOAD_MIN, VT, Expand); 1460b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_LOAD_UMAX, VT, Expand); 1470b57cec5SDimitry Andric setOperationAction(ISD::ATOMIC_LOAD_UMIN, VT, Expand); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric // Division/remainder 1510b57cec5SDimitry Andric setOperationAction(ISD::UDIV, MVT::i8, Expand); 1520b57cec5SDimitry Andric setOperationAction(ISD::UDIV, MVT::i16, Expand); 1530b57cec5SDimitry Andric setOperationAction(ISD::UREM, MVT::i8, Expand); 1540b57cec5SDimitry Andric setOperationAction(ISD::UREM, MVT::i16, Expand); 1550b57cec5SDimitry Andric setOperationAction(ISD::SDIV, MVT::i8, Expand); 1560b57cec5SDimitry Andric setOperationAction(ISD::SDIV, MVT::i16, Expand); 1570b57cec5SDimitry Andric setOperationAction(ISD::SREM, MVT::i8, Expand); 1580b57cec5SDimitry Andric setOperationAction(ISD::SREM, MVT::i16, Expand); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric // Make division and modulus custom 1615ffd83dbSDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i8, Custom); 1625ffd83dbSDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i16, Custom); 1635ffd83dbSDimitry Andric setOperationAction(ISD::UDIVREM, MVT::i32, Custom); 1645ffd83dbSDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i8, Custom); 1655ffd83dbSDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i16, Custom); 1665ffd83dbSDimitry Andric setOperationAction(ISD::SDIVREM, MVT::i32, Custom); 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric // Do not use MUL. The AVR instructions are closer to SMUL_LOHI &co. 1690b57cec5SDimitry Andric setOperationAction(ISD::MUL, MVT::i8, Expand); 1700b57cec5SDimitry Andric setOperationAction(ISD::MUL, MVT::i16, Expand); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric // Expand 16 bit multiplications. 1730b57cec5SDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand); 1740b57cec5SDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand); 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric // Expand multiplications to libcalls when there is 1770b57cec5SDimitry Andric // no hardware MUL. 1780b57cec5SDimitry Andric if (!Subtarget.supportsMultiplication()) { 1790b57cec5SDimitry Andric setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand); 1800b57cec5SDimitry Andric setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric for (MVT VT : MVT::integer_valuetypes()) { 1840b57cec5SDimitry Andric setOperationAction(ISD::MULHS, VT, Expand); 1850b57cec5SDimitry Andric setOperationAction(ISD::MULHU, VT, Expand); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric for (MVT VT : MVT::integer_valuetypes()) { 1890b57cec5SDimitry Andric setOperationAction(ISD::CTPOP, VT, Expand); 1900b57cec5SDimitry Andric setOperationAction(ISD::CTLZ, VT, Expand); 1910b57cec5SDimitry Andric setOperationAction(ISD::CTTZ, VT, Expand); 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric for (MVT VT : MVT::integer_valuetypes()) { 1950b57cec5SDimitry Andric setOperationAction(ISD::SIGN_EXTEND_INREG, VT, Expand); 1960b57cec5SDimitry Andric // TODO: The generated code is pretty poor. Investigate using the 1970b57cec5SDimitry Andric // same "shift and subtract with carry" trick that we do for 1980b57cec5SDimitry Andric // extending 8-bit to 16-bit. This may require infrastructure 1990b57cec5SDimitry Andric // improvements in how we treat 16-bit "registers" to be feasible. 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric // Division and modulus rtlib functions 2030b57cec5SDimitry Andric setLibcallName(RTLIB::SDIVREM_I8, "__divmodqi4"); 2040b57cec5SDimitry Andric setLibcallName(RTLIB::SDIVREM_I16, "__divmodhi4"); 2050b57cec5SDimitry Andric setLibcallName(RTLIB::SDIVREM_I32, "__divmodsi4"); 2060b57cec5SDimitry Andric setLibcallName(RTLIB::UDIVREM_I8, "__udivmodqi4"); 2070b57cec5SDimitry Andric setLibcallName(RTLIB::UDIVREM_I16, "__udivmodhi4"); 2080b57cec5SDimitry Andric setLibcallName(RTLIB::UDIVREM_I32, "__udivmodsi4"); 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric // Several of the runtime library functions use a special calling conv 2110b57cec5SDimitry Andric setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::AVR_BUILTIN); 2120b57cec5SDimitry Andric setLibcallCallingConv(RTLIB::SDIVREM_I16, CallingConv::AVR_BUILTIN); 2130b57cec5SDimitry Andric setLibcallCallingConv(RTLIB::UDIVREM_I8, CallingConv::AVR_BUILTIN); 2140b57cec5SDimitry Andric setLibcallCallingConv(RTLIB::UDIVREM_I16, CallingConv::AVR_BUILTIN); 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric // Trigonometric rtlib functions 2170b57cec5SDimitry Andric setLibcallName(RTLIB::SIN_F32, "sin"); 2180b57cec5SDimitry Andric setLibcallName(RTLIB::COS_F32, "cos"); 2190b57cec5SDimitry Andric 2208bcb0991SDimitry Andric setMinFunctionAlignment(Align(2)); 2210b57cec5SDimitry Andric setMinimumJumpTableEntries(UINT_MAX); 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric const char *AVRTargetLowering::getTargetNodeName(unsigned Opcode) const { 2250b57cec5SDimitry Andric #define NODE(name) \ 2260b57cec5SDimitry Andric case AVRISD::name: \ 2270b57cec5SDimitry Andric return #name 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric switch (Opcode) { 2300b57cec5SDimitry Andric default: 2310b57cec5SDimitry Andric return nullptr; 23206c3fb27SDimitry Andric NODE(RET_GLUE); 23306c3fb27SDimitry Andric NODE(RETI_GLUE); 2340b57cec5SDimitry Andric NODE(CALL); 2350b57cec5SDimitry Andric NODE(WRAPPER); 2360b57cec5SDimitry Andric NODE(LSL); 237bdd1243dSDimitry Andric NODE(LSLW); 2380b57cec5SDimitry Andric NODE(LSR); 239bdd1243dSDimitry Andric NODE(LSRW); 2400b57cec5SDimitry Andric NODE(ROL); 2410b57cec5SDimitry Andric NODE(ROR); 2420b57cec5SDimitry Andric NODE(ASR); 243bdd1243dSDimitry Andric NODE(ASRW); 2440b57cec5SDimitry Andric NODE(LSLLOOP); 2450b57cec5SDimitry Andric NODE(LSRLOOP); 2465ffd83dbSDimitry Andric NODE(ROLLOOP); 2475ffd83dbSDimitry Andric NODE(RORLOOP); 2480b57cec5SDimitry Andric NODE(ASRLOOP); 2490b57cec5SDimitry Andric NODE(BRCOND); 2500b57cec5SDimitry Andric NODE(CMP); 2510b57cec5SDimitry Andric NODE(CMPC); 2520b57cec5SDimitry Andric NODE(TST); 2530b57cec5SDimitry Andric NODE(SELECT_CC); 2540b57cec5SDimitry Andric #undef NODE 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric EVT AVRTargetLowering::getSetCCResultType(const DataLayout &DL, LLVMContext &, 2590b57cec5SDimitry Andric EVT VT) const { 2600b57cec5SDimitry Andric assert(!VT.isVector() && "No AVR SetCC type for vectors!"); 2610b57cec5SDimitry Andric return MVT::i8; 2620b57cec5SDimitry Andric } 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const { 2650b57cec5SDimitry Andric unsigned Opc8; 2660b57cec5SDimitry Andric const SDNode *N = Op.getNode(); 2670b57cec5SDimitry Andric EVT VT = Op.getValueType(); 2680b57cec5SDimitry Andric SDLoc dl(N); 26906c3fb27SDimitry Andric assert(llvm::has_single_bit<uint32_t>(VT.getSizeInBits()) && 2705ffd83dbSDimitry Andric "Expected power-of-2 shift amount"); 2710b57cec5SDimitry Andric 272bdd1243dSDimitry Andric if (VT.getSizeInBits() == 32) { 273bdd1243dSDimitry Andric if (!isa<ConstantSDNode>(N->getOperand(1))) { 274bdd1243dSDimitry Andric // 32-bit shifts are converted to a loop in IR. 275bdd1243dSDimitry Andric // This should be unreachable. 276bdd1243dSDimitry Andric report_fatal_error("Expected a constant shift amount!"); 277bdd1243dSDimitry Andric } 278bdd1243dSDimitry Andric SDVTList ResTys = DAG.getVTList(MVT::i16, MVT::i16); 279bdd1243dSDimitry Andric SDValue SrcLo = 280bdd1243dSDimitry Andric DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i16, Op.getOperand(0), 281bdd1243dSDimitry Andric DAG.getConstant(0, dl, MVT::i16)); 282bdd1243dSDimitry Andric SDValue SrcHi = 283bdd1243dSDimitry Andric DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i16, Op.getOperand(0), 284bdd1243dSDimitry Andric DAG.getConstant(1, dl, MVT::i16)); 285647cbc5dSDimitry Andric uint64_t ShiftAmount = N->getConstantOperandVal(1); 286bdd1243dSDimitry Andric if (ShiftAmount == 16) { 287bdd1243dSDimitry Andric // Special case these two operations because they appear to be used by the 288bdd1243dSDimitry Andric // generic codegen parts to lower 32-bit numbers. 289bdd1243dSDimitry Andric // TODO: perhaps we can lower shift amounts bigger than 16 to a 16-bit 290bdd1243dSDimitry Andric // shift of a part of the 32-bit value? 291bdd1243dSDimitry Andric switch (Op.getOpcode()) { 292bdd1243dSDimitry Andric case ISD::SHL: { 293bdd1243dSDimitry Andric SDValue Zero = DAG.getConstant(0, dl, MVT::i16); 294bdd1243dSDimitry Andric return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i32, Zero, SrcLo); 295bdd1243dSDimitry Andric } 296bdd1243dSDimitry Andric case ISD::SRL: { 297bdd1243dSDimitry Andric SDValue Zero = DAG.getConstant(0, dl, MVT::i16); 298bdd1243dSDimitry Andric return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i32, SrcHi, Zero); 299bdd1243dSDimitry Andric } 300bdd1243dSDimitry Andric } 301bdd1243dSDimitry Andric } 302bdd1243dSDimitry Andric SDValue Cnt = DAG.getTargetConstant(ShiftAmount, dl, MVT::i8); 303bdd1243dSDimitry Andric unsigned Opc; 304bdd1243dSDimitry Andric switch (Op.getOpcode()) { 305bdd1243dSDimitry Andric default: 306bdd1243dSDimitry Andric llvm_unreachable("Invalid 32-bit shift opcode!"); 307bdd1243dSDimitry Andric case ISD::SHL: 308bdd1243dSDimitry Andric Opc = AVRISD::LSLW; 309bdd1243dSDimitry Andric break; 310bdd1243dSDimitry Andric case ISD::SRL: 311bdd1243dSDimitry Andric Opc = AVRISD::LSRW; 312bdd1243dSDimitry Andric break; 313bdd1243dSDimitry Andric case ISD::SRA: 314bdd1243dSDimitry Andric Opc = AVRISD::ASRW; 315bdd1243dSDimitry Andric break; 316bdd1243dSDimitry Andric } 317bdd1243dSDimitry Andric SDValue Result = DAG.getNode(Opc, dl, ResTys, SrcLo, SrcHi, Cnt); 318bdd1243dSDimitry Andric return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i32, Result.getValue(0), 319bdd1243dSDimitry Andric Result.getValue(1)); 320bdd1243dSDimitry Andric } 321bdd1243dSDimitry Andric 3220b57cec5SDimitry Andric // Expand non-constant shifts to loops. 3230b57cec5SDimitry Andric if (!isa<ConstantSDNode>(N->getOperand(1))) { 3240b57cec5SDimitry Andric switch (Op.getOpcode()) { 3250b57cec5SDimitry Andric default: 3260b57cec5SDimitry Andric llvm_unreachable("Invalid shift opcode!"); 3270b57cec5SDimitry Andric case ISD::SHL: 3280b57cec5SDimitry Andric return DAG.getNode(AVRISD::LSLLOOP, dl, VT, N->getOperand(0), 3290b57cec5SDimitry Andric N->getOperand(1)); 3300b57cec5SDimitry Andric case ISD::SRL: 3310b57cec5SDimitry Andric return DAG.getNode(AVRISD::LSRLOOP, dl, VT, N->getOperand(0), 3320b57cec5SDimitry Andric N->getOperand(1)); 3335ffd83dbSDimitry Andric case ISD::ROTL: { 3345ffd83dbSDimitry Andric SDValue Amt = N->getOperand(1); 3355ffd83dbSDimitry Andric EVT AmtVT = Amt.getValueType(); 3365ffd83dbSDimitry Andric Amt = DAG.getNode(ISD::AND, dl, AmtVT, Amt, 3375ffd83dbSDimitry Andric DAG.getConstant(VT.getSizeInBits() - 1, dl, AmtVT)); 3385ffd83dbSDimitry Andric return DAG.getNode(AVRISD::ROLLOOP, dl, VT, N->getOperand(0), Amt); 3395ffd83dbSDimitry Andric } 3405ffd83dbSDimitry Andric case ISD::ROTR: { 3415ffd83dbSDimitry Andric SDValue Amt = N->getOperand(1); 3425ffd83dbSDimitry Andric EVT AmtVT = Amt.getValueType(); 3435ffd83dbSDimitry Andric Amt = DAG.getNode(ISD::AND, dl, AmtVT, Amt, 3445ffd83dbSDimitry Andric DAG.getConstant(VT.getSizeInBits() - 1, dl, AmtVT)); 3455ffd83dbSDimitry Andric return DAG.getNode(AVRISD::RORLOOP, dl, VT, N->getOperand(0), Amt); 3465ffd83dbSDimitry Andric } 3470b57cec5SDimitry Andric case ISD::SRA: 3480b57cec5SDimitry Andric return DAG.getNode(AVRISD::ASRLOOP, dl, VT, N->getOperand(0), 3490b57cec5SDimitry Andric N->getOperand(1)); 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 353647cbc5dSDimitry Andric uint64_t ShiftAmount = N->getConstantOperandVal(1); 3540b57cec5SDimitry Andric SDValue Victim = N->getOperand(0); 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric switch (Op.getOpcode()) { 3570b57cec5SDimitry Andric case ISD::SRA: 3580b57cec5SDimitry Andric Opc8 = AVRISD::ASR; 3590b57cec5SDimitry Andric break; 3600b57cec5SDimitry Andric case ISD::ROTL: 3610b57cec5SDimitry Andric Opc8 = AVRISD::ROL; 3625ffd83dbSDimitry Andric ShiftAmount = ShiftAmount % VT.getSizeInBits(); 3630b57cec5SDimitry Andric break; 3640b57cec5SDimitry Andric case ISD::ROTR: 3650b57cec5SDimitry Andric Opc8 = AVRISD::ROR; 3665ffd83dbSDimitry Andric ShiftAmount = ShiftAmount % VT.getSizeInBits(); 3670b57cec5SDimitry Andric break; 3680b57cec5SDimitry Andric case ISD::SRL: 3690b57cec5SDimitry Andric Opc8 = AVRISD::LSR; 3700b57cec5SDimitry Andric break; 3710b57cec5SDimitry Andric case ISD::SHL: 3720b57cec5SDimitry Andric Opc8 = AVRISD::LSL; 3730b57cec5SDimitry Andric break; 3740b57cec5SDimitry Andric default: 3750b57cec5SDimitry Andric llvm_unreachable("Invalid shift opcode"); 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric 378fe6060f1SDimitry Andric // Optimize int8/int16 shifts. 379e8d8bef9SDimitry Andric if (VT.getSizeInBits() == 8) { 380e8d8bef9SDimitry Andric if (Op.getOpcode() == ISD::SHL && 4 <= ShiftAmount && ShiftAmount < 7) { 381e8d8bef9SDimitry Andric // Optimize LSL when 4 <= ShiftAmount <= 6. 382e8d8bef9SDimitry Andric Victim = DAG.getNode(AVRISD::SWAP, dl, VT, Victim); 383e8d8bef9SDimitry Andric Victim = 384e8d8bef9SDimitry Andric DAG.getNode(ISD::AND, dl, VT, Victim, DAG.getConstant(0xf0, dl, VT)); 385e8d8bef9SDimitry Andric ShiftAmount -= 4; 386e8d8bef9SDimitry Andric } else if (Op.getOpcode() == ISD::SRL && 4 <= ShiftAmount && 387e8d8bef9SDimitry Andric ShiftAmount < 7) { 388e8d8bef9SDimitry Andric // Optimize LSR when 4 <= ShiftAmount <= 6. 389e8d8bef9SDimitry Andric Victim = DAG.getNode(AVRISD::SWAP, dl, VT, Victim); 390e8d8bef9SDimitry Andric Victim = 391e8d8bef9SDimitry Andric DAG.getNode(ISD::AND, dl, VT, Victim, DAG.getConstant(0x0f, dl, VT)); 392e8d8bef9SDimitry Andric ShiftAmount -= 4; 393e8d8bef9SDimitry Andric } else if (Op.getOpcode() == ISD::SHL && ShiftAmount == 7) { 394e8d8bef9SDimitry Andric // Optimize LSL when ShiftAmount == 7. 395fe6060f1SDimitry Andric Victim = DAG.getNode(AVRISD::LSLBN, dl, VT, Victim, 396fe6060f1SDimitry Andric DAG.getConstant(7, dl, VT)); 397e8d8bef9SDimitry Andric ShiftAmount = 0; 398e8d8bef9SDimitry Andric } else if (Op.getOpcode() == ISD::SRL && ShiftAmount == 7) { 399e8d8bef9SDimitry Andric // Optimize LSR when ShiftAmount == 7. 400fe6060f1SDimitry Andric Victim = DAG.getNode(AVRISD::LSRBN, dl, VT, Victim, 401fe6060f1SDimitry Andric DAG.getConstant(7, dl, VT)); 402e8d8bef9SDimitry Andric ShiftAmount = 0; 40304eeddc0SDimitry Andric } else if (Op.getOpcode() == ISD::SRA && ShiftAmount == 6) { 40404eeddc0SDimitry Andric // Optimize ASR when ShiftAmount == 6. 40504eeddc0SDimitry Andric Victim = DAG.getNode(AVRISD::ASRBN, dl, VT, Victim, 40604eeddc0SDimitry Andric DAG.getConstant(6, dl, VT)); 40704eeddc0SDimitry Andric ShiftAmount = 0; 408e8d8bef9SDimitry Andric } else if (Op.getOpcode() == ISD::SRA && ShiftAmount == 7) { 409e8d8bef9SDimitry Andric // Optimize ASR when ShiftAmount == 7. 410fe6060f1SDimitry Andric Victim = DAG.getNode(AVRISD::ASRBN, dl, VT, Victim, 411fe6060f1SDimitry Andric DAG.getConstant(7, dl, VT)); 412e8d8bef9SDimitry Andric ShiftAmount = 0; 41306c3fb27SDimitry Andric } else if (Op.getOpcode() == ISD::ROTL && ShiftAmount == 3) { 41406c3fb27SDimitry Andric // Optimize left rotation 3 bits to swap then right rotation 1 bit. 41506c3fb27SDimitry Andric Victim = DAG.getNode(AVRISD::SWAP, dl, VT, Victim); 41606c3fb27SDimitry Andric Victim = 41706c3fb27SDimitry Andric DAG.getNode(AVRISD::ROR, dl, VT, Victim, DAG.getConstant(1, dl, VT)); 41806c3fb27SDimitry Andric ShiftAmount = 0; 41906c3fb27SDimitry Andric } else if (Op.getOpcode() == ISD::ROTR && ShiftAmount == 3) { 42006c3fb27SDimitry Andric // Optimize right rotation 3 bits to swap then left rotation 1 bit. 42106c3fb27SDimitry Andric Victim = DAG.getNode(AVRISD::SWAP, dl, VT, Victim); 42206c3fb27SDimitry Andric Victim = 42306c3fb27SDimitry Andric DAG.getNode(AVRISD::ROL, dl, VT, Victim, DAG.getConstant(1, dl, VT)); 42406c3fb27SDimitry Andric ShiftAmount = 0; 42506c3fb27SDimitry Andric } else if (Op.getOpcode() == ISD::ROTL && ShiftAmount == 7) { 42606c3fb27SDimitry Andric // Optimize left rotation 7 bits to right rotation 1 bit. 42706c3fb27SDimitry Andric Victim = 42806c3fb27SDimitry Andric DAG.getNode(AVRISD::ROR, dl, VT, Victim, DAG.getConstant(1, dl, VT)); 42906c3fb27SDimitry Andric ShiftAmount = 0; 43006c3fb27SDimitry Andric } else if (Op.getOpcode() == ISD::ROTR && ShiftAmount == 7) { 43106c3fb27SDimitry Andric // Optimize right rotation 7 bits to left rotation 1 bit. 43206c3fb27SDimitry Andric Victim = 43306c3fb27SDimitry Andric DAG.getNode(AVRISD::ROL, dl, VT, Victim, DAG.getConstant(1, dl, VT)); 43406c3fb27SDimitry Andric ShiftAmount = 0; 43506c3fb27SDimitry Andric } else if ((Op.getOpcode() == ISD::ROTR || Op.getOpcode() == ISD::ROTL) && 43606c3fb27SDimitry Andric ShiftAmount >= 4) { 43706c3fb27SDimitry Andric // Optimize left/right rotation with the SWAP instruction. 43806c3fb27SDimitry Andric Victim = DAG.getNode(AVRISD::SWAP, dl, VT, Victim); 43906c3fb27SDimitry Andric ShiftAmount -= 4; 440e8d8bef9SDimitry Andric } 441fe6060f1SDimitry Andric } else if (VT.getSizeInBits() == 16) { 44281ad6265SDimitry Andric if (Op.getOpcode() == ISD::SRA) 44381ad6265SDimitry Andric // Special optimization for int16 arithmetic right shift. 44481ad6265SDimitry Andric switch (ShiftAmount) { 44581ad6265SDimitry Andric case 15: 44681ad6265SDimitry Andric Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim, 44781ad6265SDimitry Andric DAG.getConstant(15, dl, VT)); 44881ad6265SDimitry Andric ShiftAmount = 0; 44981ad6265SDimitry Andric break; 45081ad6265SDimitry Andric case 14: 45181ad6265SDimitry Andric Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim, 45281ad6265SDimitry Andric DAG.getConstant(14, dl, VT)); 45381ad6265SDimitry Andric ShiftAmount = 0; 45481ad6265SDimitry Andric break; 45581ad6265SDimitry Andric case 7: 45681ad6265SDimitry Andric Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim, 45781ad6265SDimitry Andric DAG.getConstant(7, dl, VT)); 45881ad6265SDimitry Andric ShiftAmount = 0; 45981ad6265SDimitry Andric break; 46081ad6265SDimitry Andric default: 46181ad6265SDimitry Andric break; 46281ad6265SDimitry Andric } 463fe6060f1SDimitry Andric if (4 <= ShiftAmount && ShiftAmount < 8) 464fe6060f1SDimitry Andric switch (Op.getOpcode()) { 465fe6060f1SDimitry Andric case ISD::SHL: 466fe6060f1SDimitry Andric Victim = DAG.getNode(AVRISD::LSLWN, dl, VT, Victim, 467fe6060f1SDimitry Andric DAG.getConstant(4, dl, VT)); 468fe6060f1SDimitry Andric ShiftAmount -= 4; 469fe6060f1SDimitry Andric break; 470fe6060f1SDimitry Andric case ISD::SRL: 471fe6060f1SDimitry Andric Victim = DAG.getNode(AVRISD::LSRWN, dl, VT, Victim, 472fe6060f1SDimitry Andric DAG.getConstant(4, dl, VT)); 473fe6060f1SDimitry Andric ShiftAmount -= 4; 474fe6060f1SDimitry Andric break; 475fe6060f1SDimitry Andric default: 476fe6060f1SDimitry Andric break; 477fe6060f1SDimitry Andric } 478fe6060f1SDimitry Andric else if (8 <= ShiftAmount && ShiftAmount < 12) 479fe6060f1SDimitry Andric switch (Op.getOpcode()) { 480fe6060f1SDimitry Andric case ISD::SHL: 481fe6060f1SDimitry Andric Victim = DAG.getNode(AVRISD::LSLWN, dl, VT, Victim, 482fe6060f1SDimitry Andric DAG.getConstant(8, dl, VT)); 483fe6060f1SDimitry Andric ShiftAmount -= 8; 48404eeddc0SDimitry Andric // Only operate on the higher byte for remaining shift bits. 48504eeddc0SDimitry Andric Opc8 = AVRISD::LSLHI; 486fe6060f1SDimitry Andric break; 487fe6060f1SDimitry Andric case ISD::SRL: 488fe6060f1SDimitry Andric Victim = DAG.getNode(AVRISD::LSRWN, dl, VT, Victim, 489fe6060f1SDimitry Andric DAG.getConstant(8, dl, VT)); 490fe6060f1SDimitry Andric ShiftAmount -= 8; 49104eeddc0SDimitry Andric // Only operate on the lower byte for remaining shift bits. 49204eeddc0SDimitry Andric Opc8 = AVRISD::LSRLO; 493fe6060f1SDimitry Andric break; 494fe6060f1SDimitry Andric case ISD::SRA: 495fe6060f1SDimitry Andric Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim, 496fe6060f1SDimitry Andric DAG.getConstant(8, dl, VT)); 497fe6060f1SDimitry Andric ShiftAmount -= 8; 49804eeddc0SDimitry Andric // Only operate on the lower byte for remaining shift bits. 49904eeddc0SDimitry Andric Opc8 = AVRISD::ASRLO; 500fe6060f1SDimitry Andric break; 501fe6060f1SDimitry Andric default: 502fe6060f1SDimitry Andric break; 503fe6060f1SDimitry Andric } 504fe6060f1SDimitry Andric else if (12 <= ShiftAmount) 505fe6060f1SDimitry Andric switch (Op.getOpcode()) { 506fe6060f1SDimitry Andric case ISD::SHL: 507fe6060f1SDimitry Andric Victim = DAG.getNode(AVRISD::LSLWN, dl, VT, Victim, 508fe6060f1SDimitry Andric DAG.getConstant(12, dl, VT)); 509fe6060f1SDimitry Andric ShiftAmount -= 12; 51004eeddc0SDimitry Andric // Only operate on the higher byte for remaining shift bits. 51104eeddc0SDimitry Andric Opc8 = AVRISD::LSLHI; 512fe6060f1SDimitry Andric break; 513fe6060f1SDimitry Andric case ISD::SRL: 514fe6060f1SDimitry Andric Victim = DAG.getNode(AVRISD::LSRWN, dl, VT, Victim, 515fe6060f1SDimitry Andric DAG.getConstant(12, dl, VT)); 516fe6060f1SDimitry Andric ShiftAmount -= 12; 51704eeddc0SDimitry Andric // Only operate on the lower byte for remaining shift bits. 51804eeddc0SDimitry Andric Opc8 = AVRISD::LSRLO; 51904eeddc0SDimitry Andric break; 52004eeddc0SDimitry Andric case ISD::SRA: 52104eeddc0SDimitry Andric Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim, 52204eeddc0SDimitry Andric DAG.getConstant(8, dl, VT)); 52304eeddc0SDimitry Andric ShiftAmount -= 8; 52404eeddc0SDimitry Andric // Only operate on the lower byte for remaining shift bits. 52504eeddc0SDimitry Andric Opc8 = AVRISD::ASRLO; 526fe6060f1SDimitry Andric break; 527fe6060f1SDimitry Andric default: 528fe6060f1SDimitry Andric break; 529fe6060f1SDimitry Andric } 530e8d8bef9SDimitry Andric } 531e8d8bef9SDimitry Andric 5320b57cec5SDimitry Andric while (ShiftAmount--) { 5330b57cec5SDimitry Andric Victim = DAG.getNode(Opc8, dl, VT, Victim); 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric return Victim; 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerDivRem(SDValue Op, SelectionDAG &DAG) const { 5400b57cec5SDimitry Andric unsigned Opcode = Op->getOpcode(); 5410b57cec5SDimitry Andric assert((Opcode == ISD::SDIVREM || Opcode == ISD::UDIVREM) && 5420b57cec5SDimitry Andric "Invalid opcode for Div/Rem lowering"); 5430b57cec5SDimitry Andric bool IsSigned = (Opcode == ISD::SDIVREM); 5440b57cec5SDimitry Andric EVT VT = Op->getValueType(0); 5450b57cec5SDimitry Andric Type *Ty = VT.getTypeForEVT(*DAG.getContext()); 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric RTLIB::Libcall LC; 5480b57cec5SDimitry Andric switch (VT.getSimpleVT().SimpleTy) { 5490b57cec5SDimitry Andric default: 5500b57cec5SDimitry Andric llvm_unreachable("Unexpected request for libcall!"); 5510b57cec5SDimitry Andric case MVT::i8: 5520b57cec5SDimitry Andric LC = IsSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8; 5530b57cec5SDimitry Andric break; 5540b57cec5SDimitry Andric case MVT::i16: 5550b57cec5SDimitry Andric LC = IsSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16; 5560b57cec5SDimitry Andric break; 5570b57cec5SDimitry Andric case MVT::i32: 5580b57cec5SDimitry Andric LC = IsSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32; 5590b57cec5SDimitry Andric break; 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric SDValue InChain = DAG.getEntryNode(); 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric TargetLowering::ArgListTy Args; 5650b57cec5SDimitry Andric TargetLowering::ArgListEntry Entry; 5660b57cec5SDimitry Andric for (SDValue const &Value : Op->op_values()) { 5670b57cec5SDimitry Andric Entry.Node = Value; 5680b57cec5SDimitry Andric Entry.Ty = Value.getValueType().getTypeForEVT(*DAG.getContext()); 5690b57cec5SDimitry Andric Entry.IsSExt = IsSigned; 5700b57cec5SDimitry Andric Entry.IsZExt = !IsSigned; 5710b57cec5SDimitry Andric Args.push_back(Entry); 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric SDValue Callee = DAG.getExternalSymbol(getLibcallName(LC), 5750b57cec5SDimitry Andric getPointerTy(DAG.getDataLayout())); 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric Type *RetTy = (Type *)StructType::get(Ty, Ty); 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric SDLoc dl(Op); 5800b57cec5SDimitry Andric TargetLowering::CallLoweringInfo CLI(DAG); 5810b57cec5SDimitry Andric CLI.setDebugLoc(dl) 5820b57cec5SDimitry Andric .setChain(InChain) 5830b57cec5SDimitry Andric .setLibCallee(getLibcallCallingConv(LC), RetTy, Callee, std::move(Args)) 5840b57cec5SDimitry Andric .setInRegister() 5850b57cec5SDimitry Andric .setSExtResult(IsSigned) 5860b57cec5SDimitry Andric .setZExtResult(!IsSigned); 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI); 5890b57cec5SDimitry Andric return CallInfo.first; 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerGlobalAddress(SDValue Op, 5930b57cec5SDimitry Andric SelectionDAG &DAG) const { 5940b57cec5SDimitry Andric auto DL = DAG.getDataLayout(); 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); 5970b57cec5SDimitry Andric int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset(); 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric // Create the TargetGlobalAddress node, folding in the constant offset. 6000b57cec5SDimitry Andric SDValue Result = 6010b57cec5SDimitry Andric DAG.getTargetGlobalAddress(GV, SDLoc(Op), getPointerTy(DL), Offset); 6020b57cec5SDimitry Andric return DAG.getNode(AVRISD::WRAPPER, SDLoc(Op), getPointerTy(DL), Result); 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerBlockAddress(SDValue Op, 6060b57cec5SDimitry Andric SelectionDAG &DAG) const { 6070b57cec5SDimitry Andric auto DL = DAG.getDataLayout(); 6080b57cec5SDimitry Andric const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); 6090b57cec5SDimitry Andric 6100b57cec5SDimitry Andric SDValue Result = DAG.getTargetBlockAddress(BA, getPointerTy(DL)); 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric return DAG.getNode(AVRISD::WRAPPER, SDLoc(Op), getPointerTy(DL), Result); 6130b57cec5SDimitry Andric } 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric /// IntCCToAVRCC - Convert a DAG integer condition code to an AVR CC. 6160b57cec5SDimitry Andric static AVRCC::CondCodes intCCToAVRCC(ISD::CondCode CC) { 6170b57cec5SDimitry Andric switch (CC) { 6180b57cec5SDimitry Andric default: 6190b57cec5SDimitry Andric llvm_unreachable("Unknown condition code!"); 6200b57cec5SDimitry Andric case ISD::SETEQ: 6210b57cec5SDimitry Andric return AVRCC::COND_EQ; 6220b57cec5SDimitry Andric case ISD::SETNE: 6230b57cec5SDimitry Andric return AVRCC::COND_NE; 6240b57cec5SDimitry Andric case ISD::SETGE: 6250b57cec5SDimitry Andric return AVRCC::COND_GE; 6260b57cec5SDimitry Andric case ISD::SETLT: 6270b57cec5SDimitry Andric return AVRCC::COND_LT; 6280b57cec5SDimitry Andric case ISD::SETUGE: 6290b57cec5SDimitry Andric return AVRCC::COND_SH; 6300b57cec5SDimitry Andric case ISD::SETULT: 6310b57cec5SDimitry Andric return AVRCC::COND_LO; 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric } 6340b57cec5SDimitry Andric 635e8d8bef9SDimitry Andric /// Returns appropriate CP/CPI/CPC nodes code for the given 8/16-bit operands. 636e8d8bef9SDimitry Andric SDValue AVRTargetLowering::getAVRCmp(SDValue LHS, SDValue RHS, 637e8d8bef9SDimitry Andric SelectionDAG &DAG, SDLoc DL) const { 638e8d8bef9SDimitry Andric assert((LHS.getSimpleValueType() == RHS.getSimpleValueType()) && 639e8d8bef9SDimitry Andric "LHS and RHS have different types"); 640e8d8bef9SDimitry Andric assert(((LHS.getSimpleValueType() == MVT::i16) || 641349cc55cSDimitry Andric (LHS.getSimpleValueType() == MVT::i8)) && 642349cc55cSDimitry Andric "invalid comparison type"); 643e8d8bef9SDimitry Andric 644e8d8bef9SDimitry Andric SDValue Cmp; 645e8d8bef9SDimitry Andric 646fe6060f1SDimitry Andric if (LHS.getSimpleValueType() == MVT::i16 && isa<ConstantSDNode>(RHS)) { 6471db9f3b2SDimitry Andric uint64_t Imm = RHS->getAsZExtVal(); 64806c3fb27SDimitry Andric // Generate a CPI/CPC pair if RHS is a 16-bit constant. Use the zero 64906c3fb27SDimitry Andric // register for the constant RHS if its lower or higher byte is zero. 650e8d8bef9SDimitry Andric SDValue LHSlo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, LHS, 651e8d8bef9SDimitry Andric DAG.getIntPtrConstant(0, DL)); 652e8d8bef9SDimitry Andric SDValue LHShi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, LHS, 653e8d8bef9SDimitry Andric DAG.getIntPtrConstant(1, DL)); 65406c3fb27SDimitry Andric SDValue RHSlo = (Imm & 0xff) == 0 65506c3fb27SDimitry Andric ? DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8) 65606c3fb27SDimitry Andric : DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, RHS, 65706c3fb27SDimitry Andric DAG.getIntPtrConstant(0, DL)); 65806c3fb27SDimitry Andric SDValue RHShi = (Imm & 0xff00) == 0 65906c3fb27SDimitry Andric ? DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8) 66006c3fb27SDimitry Andric : DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, RHS, 66106c3fb27SDimitry Andric DAG.getIntPtrConstant(1, DL)); 66206c3fb27SDimitry Andric Cmp = DAG.getNode(AVRISD::CMP, DL, MVT::Glue, LHSlo, RHSlo); 66306c3fb27SDimitry Andric Cmp = DAG.getNode(AVRISD::CMPC, DL, MVT::Glue, LHShi, RHShi, Cmp); 66406c3fb27SDimitry Andric } else if (RHS.getSimpleValueType() == MVT::i16 && isa<ConstantSDNode>(LHS)) { 66506c3fb27SDimitry Andric // Generate a CPI/CPC pair if LHS is a 16-bit constant. Use the zero 66606c3fb27SDimitry Andric // register for the constant LHS if its lower or higher byte is zero. 6671db9f3b2SDimitry Andric uint64_t Imm = LHS->getAsZExtVal(); 66806c3fb27SDimitry Andric SDValue LHSlo = (Imm & 0xff) == 0 66906c3fb27SDimitry Andric ? DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8) 67006c3fb27SDimitry Andric : DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, LHS, 67106c3fb27SDimitry Andric DAG.getIntPtrConstant(0, DL)); 67206c3fb27SDimitry Andric SDValue LHShi = (Imm & 0xff00) == 0 67306c3fb27SDimitry Andric ? DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8) 67406c3fb27SDimitry Andric : DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, LHS, 67506c3fb27SDimitry Andric DAG.getIntPtrConstant(1, DL)); 676e8d8bef9SDimitry Andric SDValue RHSlo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, RHS, 677e8d8bef9SDimitry Andric DAG.getIntPtrConstant(0, DL)); 678e8d8bef9SDimitry Andric SDValue RHShi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, RHS, 679e8d8bef9SDimitry Andric DAG.getIntPtrConstant(1, DL)); 680e8d8bef9SDimitry Andric Cmp = DAG.getNode(AVRISD::CMP, DL, MVT::Glue, LHSlo, RHSlo); 681e8d8bef9SDimitry Andric Cmp = DAG.getNode(AVRISD::CMPC, DL, MVT::Glue, LHShi, RHShi, Cmp); 682e8d8bef9SDimitry Andric } else { 683e8d8bef9SDimitry Andric // Generate ordinary 16-bit comparison. 684e8d8bef9SDimitry Andric Cmp = DAG.getNode(AVRISD::CMP, DL, MVT::Glue, LHS, RHS); 685e8d8bef9SDimitry Andric } 686e8d8bef9SDimitry Andric 687e8d8bef9SDimitry Andric return Cmp; 688e8d8bef9SDimitry Andric } 689e8d8bef9SDimitry Andric 6900b57cec5SDimitry Andric /// Returns appropriate AVR CMP/CMPC nodes and corresponding condition code for 6910b57cec5SDimitry Andric /// the given operands. 6920b57cec5SDimitry Andric SDValue AVRTargetLowering::getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, 6930b57cec5SDimitry Andric SDValue &AVRcc, SelectionDAG &DAG, 6940b57cec5SDimitry Andric SDLoc DL) const { 6950b57cec5SDimitry Andric SDValue Cmp; 6960b57cec5SDimitry Andric EVT VT = LHS.getValueType(); 6970b57cec5SDimitry Andric bool UseTest = false; 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric switch (CC) { 7000b57cec5SDimitry Andric default: 7010b57cec5SDimitry Andric break; 7020b57cec5SDimitry Andric case ISD::SETLE: { 7030b57cec5SDimitry Andric // Swap operands and reverse the branching condition. 7040b57cec5SDimitry Andric std::swap(LHS, RHS); 7050b57cec5SDimitry Andric CC = ISD::SETGE; 7060b57cec5SDimitry Andric break; 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric case ISD::SETGT: { 7090b57cec5SDimitry Andric if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) { 7100b57cec5SDimitry Andric switch (C->getSExtValue()) { 7110b57cec5SDimitry Andric case -1: { 7120b57cec5SDimitry Andric // When doing lhs > -1 use a tst instruction on the top part of lhs 7130b57cec5SDimitry Andric // and use brpl instead of using a chain of cp/cpc. 7140b57cec5SDimitry Andric UseTest = true; 7150b57cec5SDimitry Andric AVRcc = DAG.getConstant(AVRCC::COND_PL, DL, MVT::i8); 7160b57cec5SDimitry Andric break; 7170b57cec5SDimitry Andric } 7180b57cec5SDimitry Andric case 0: { 7190b57cec5SDimitry Andric // Turn lhs > 0 into 0 < lhs since 0 can be materialized with 7200b57cec5SDimitry Andric // __zero_reg__ in lhs. 7210b57cec5SDimitry Andric RHS = LHS; 7220b57cec5SDimitry Andric LHS = DAG.getConstant(0, DL, VT); 7230b57cec5SDimitry Andric CC = ISD::SETLT; 7240b57cec5SDimitry Andric break; 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric default: { 7270b57cec5SDimitry Andric // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows 7280b57cec5SDimitry Andric // us to fold the constant into the cmp instruction. 7290b57cec5SDimitry Andric RHS = DAG.getConstant(C->getSExtValue() + 1, DL, VT); 7300b57cec5SDimitry Andric CC = ISD::SETGE; 7310b57cec5SDimitry Andric break; 7320b57cec5SDimitry Andric } 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric break; 7350b57cec5SDimitry Andric } 7360b57cec5SDimitry Andric // Swap operands and reverse the branching condition. 7370b57cec5SDimitry Andric std::swap(LHS, RHS); 7380b57cec5SDimitry Andric CC = ISD::SETLT; 7390b57cec5SDimitry Andric break; 7400b57cec5SDimitry Andric } 7410b57cec5SDimitry Andric case ISD::SETLT: { 7420b57cec5SDimitry Andric if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) { 7430b57cec5SDimitry Andric switch (C->getSExtValue()) { 7440b57cec5SDimitry Andric case 1: { 7450b57cec5SDimitry Andric // Turn lhs < 1 into 0 >= lhs since 0 can be materialized with 7460b57cec5SDimitry Andric // __zero_reg__ in lhs. 7470b57cec5SDimitry Andric RHS = LHS; 7480b57cec5SDimitry Andric LHS = DAG.getConstant(0, DL, VT); 7490b57cec5SDimitry Andric CC = ISD::SETGE; 7500b57cec5SDimitry Andric break; 7510b57cec5SDimitry Andric } 7520b57cec5SDimitry Andric case 0: { 7530b57cec5SDimitry Andric // When doing lhs < 0 use a tst instruction on the top part of lhs 7540b57cec5SDimitry Andric // and use brmi instead of using a chain of cp/cpc. 7550b57cec5SDimitry Andric UseTest = true; 7560b57cec5SDimitry Andric AVRcc = DAG.getConstant(AVRCC::COND_MI, DL, MVT::i8); 7570b57cec5SDimitry Andric break; 7580b57cec5SDimitry Andric } 7590b57cec5SDimitry Andric } 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric break; 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric case ISD::SETULE: { 7640b57cec5SDimitry Andric // Swap operands and reverse the branching condition. 7650b57cec5SDimitry Andric std::swap(LHS, RHS); 7660b57cec5SDimitry Andric CC = ISD::SETUGE; 7670b57cec5SDimitry Andric break; 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric case ISD::SETUGT: { 7700b57cec5SDimitry Andric // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows us to 7710b57cec5SDimitry Andric // fold the constant into the cmp instruction. 7720b57cec5SDimitry Andric if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) { 7730b57cec5SDimitry Andric RHS = DAG.getConstant(C->getSExtValue() + 1, DL, VT); 7740b57cec5SDimitry Andric CC = ISD::SETUGE; 7750b57cec5SDimitry Andric break; 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric // Swap operands and reverse the branching condition. 7780b57cec5SDimitry Andric std::swap(LHS, RHS); 7790b57cec5SDimitry Andric CC = ISD::SETULT; 7800b57cec5SDimitry Andric break; 7810b57cec5SDimitry Andric } 7820b57cec5SDimitry Andric } 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric // Expand 32 and 64 bit comparisons with custom CMP and CMPC nodes instead of 7850b57cec5SDimitry Andric // using the default and/or/xor expansion code which is much longer. 7860b57cec5SDimitry Andric if (VT == MVT::i32) { 7870b57cec5SDimitry Andric SDValue LHSlo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, LHS, 7880b57cec5SDimitry Andric DAG.getIntPtrConstant(0, DL)); 7890b57cec5SDimitry Andric SDValue LHShi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, LHS, 7900b57cec5SDimitry Andric DAG.getIntPtrConstant(1, DL)); 7910b57cec5SDimitry Andric SDValue RHSlo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, RHS, 7920b57cec5SDimitry Andric DAG.getIntPtrConstant(0, DL)); 7930b57cec5SDimitry Andric SDValue RHShi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, RHS, 7940b57cec5SDimitry Andric DAG.getIntPtrConstant(1, DL)); 7950b57cec5SDimitry Andric 7960b57cec5SDimitry Andric if (UseTest) { 7970b57cec5SDimitry Andric // When using tst we only care about the highest part. 7980b57cec5SDimitry Andric SDValue Top = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, LHShi, 7990b57cec5SDimitry Andric DAG.getIntPtrConstant(1, DL)); 8000b57cec5SDimitry Andric Cmp = DAG.getNode(AVRISD::TST, DL, MVT::Glue, Top); 8010b57cec5SDimitry Andric } else { 802e8d8bef9SDimitry Andric Cmp = getAVRCmp(LHSlo, RHSlo, DAG, DL); 8030b57cec5SDimitry Andric Cmp = DAG.getNode(AVRISD::CMPC, DL, MVT::Glue, LHShi, RHShi, Cmp); 8040b57cec5SDimitry Andric } 8050b57cec5SDimitry Andric } else if (VT == MVT::i64) { 8060b57cec5SDimitry Andric SDValue LHS_0 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, LHS, 8070b57cec5SDimitry Andric DAG.getIntPtrConstant(0, DL)); 8080b57cec5SDimitry Andric SDValue LHS_1 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, LHS, 8090b57cec5SDimitry Andric DAG.getIntPtrConstant(1, DL)); 8100b57cec5SDimitry Andric 8110b57cec5SDimitry Andric SDValue LHS0 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, LHS_0, 8120b57cec5SDimitry Andric DAG.getIntPtrConstant(0, DL)); 8130b57cec5SDimitry Andric SDValue LHS1 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, LHS_0, 8140b57cec5SDimitry Andric DAG.getIntPtrConstant(1, DL)); 8150b57cec5SDimitry Andric SDValue LHS2 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, LHS_1, 8160b57cec5SDimitry Andric DAG.getIntPtrConstant(0, DL)); 8170b57cec5SDimitry Andric SDValue LHS3 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, LHS_1, 8180b57cec5SDimitry Andric DAG.getIntPtrConstant(1, DL)); 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric SDValue RHS_0 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, RHS, 8210b57cec5SDimitry Andric DAG.getIntPtrConstant(0, DL)); 8220b57cec5SDimitry Andric SDValue RHS_1 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, RHS, 8230b57cec5SDimitry Andric DAG.getIntPtrConstant(1, DL)); 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric SDValue RHS0 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, RHS_0, 8260b57cec5SDimitry Andric DAG.getIntPtrConstant(0, DL)); 8270b57cec5SDimitry Andric SDValue RHS1 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, RHS_0, 8280b57cec5SDimitry Andric DAG.getIntPtrConstant(1, DL)); 8290b57cec5SDimitry Andric SDValue RHS2 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, RHS_1, 8300b57cec5SDimitry Andric DAG.getIntPtrConstant(0, DL)); 8310b57cec5SDimitry Andric SDValue RHS3 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, RHS_1, 8320b57cec5SDimitry Andric DAG.getIntPtrConstant(1, DL)); 8330b57cec5SDimitry Andric 8340b57cec5SDimitry Andric if (UseTest) { 8350b57cec5SDimitry Andric // When using tst we only care about the highest part. 8360b57cec5SDimitry Andric SDValue Top = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, LHS3, 8370b57cec5SDimitry Andric DAG.getIntPtrConstant(1, DL)); 8380b57cec5SDimitry Andric Cmp = DAG.getNode(AVRISD::TST, DL, MVT::Glue, Top); 8390b57cec5SDimitry Andric } else { 840e8d8bef9SDimitry Andric Cmp = getAVRCmp(LHS0, RHS0, DAG, DL); 8410b57cec5SDimitry Andric Cmp = DAG.getNode(AVRISD::CMPC, DL, MVT::Glue, LHS1, RHS1, Cmp); 8420b57cec5SDimitry Andric Cmp = DAG.getNode(AVRISD::CMPC, DL, MVT::Glue, LHS2, RHS2, Cmp); 8430b57cec5SDimitry Andric Cmp = DAG.getNode(AVRISD::CMPC, DL, MVT::Glue, LHS3, RHS3, Cmp); 8440b57cec5SDimitry Andric } 8450b57cec5SDimitry Andric } else if (VT == MVT::i8 || VT == MVT::i16) { 8460b57cec5SDimitry Andric if (UseTest) { 8470b57cec5SDimitry Andric // When using tst we only care about the highest part. 8480b57cec5SDimitry Andric Cmp = DAG.getNode(AVRISD::TST, DL, MVT::Glue, 8490b57cec5SDimitry Andric (VT == MVT::i8) 8500b57cec5SDimitry Andric ? LHS 8510b57cec5SDimitry Andric : DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, 8520b57cec5SDimitry Andric LHS, DAG.getIntPtrConstant(1, DL))); 8530b57cec5SDimitry Andric } else { 854e8d8bef9SDimitry Andric Cmp = getAVRCmp(LHS, RHS, DAG, DL); 8550b57cec5SDimitry Andric } 8560b57cec5SDimitry Andric } else { 8570b57cec5SDimitry Andric llvm_unreachable("Invalid comparison size"); 8580b57cec5SDimitry Andric } 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric // When using a test instruction AVRcc is already set. 8610b57cec5SDimitry Andric if (!UseTest) { 8620b57cec5SDimitry Andric AVRcc = DAG.getConstant(intCCToAVRCC(CC), DL, MVT::i8); 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric 8650b57cec5SDimitry Andric return Cmp; 8660b57cec5SDimitry Andric } 8670b57cec5SDimitry Andric 8680b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { 8690b57cec5SDimitry Andric SDValue Chain = Op.getOperand(0); 8700b57cec5SDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); 8710b57cec5SDimitry Andric SDValue LHS = Op.getOperand(2); 8720b57cec5SDimitry Andric SDValue RHS = Op.getOperand(3); 8730b57cec5SDimitry Andric SDValue Dest = Op.getOperand(4); 8740b57cec5SDimitry Andric SDLoc dl(Op); 8750b57cec5SDimitry Andric 8760b57cec5SDimitry Andric SDValue TargetCC; 8770b57cec5SDimitry Andric SDValue Cmp = getAVRCmp(LHS, RHS, CC, TargetCC, DAG, dl); 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric return DAG.getNode(AVRISD::BRCOND, dl, MVT::Other, Chain, Dest, TargetCC, 8800b57cec5SDimitry Andric Cmp); 8810b57cec5SDimitry Andric } 8820b57cec5SDimitry Andric 8830b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { 8840b57cec5SDimitry Andric SDValue LHS = Op.getOperand(0); 8850b57cec5SDimitry Andric SDValue RHS = Op.getOperand(1); 8860b57cec5SDimitry Andric SDValue TrueV = Op.getOperand(2); 8870b57cec5SDimitry Andric SDValue FalseV = Op.getOperand(3); 8880b57cec5SDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); 8890b57cec5SDimitry Andric SDLoc dl(Op); 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric SDValue TargetCC; 8920b57cec5SDimitry Andric SDValue Cmp = getAVRCmp(LHS, RHS, CC, TargetCC, DAG, dl); 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); 8950b57cec5SDimitry Andric SDValue Ops[] = {TrueV, FalseV, TargetCC, Cmp}; 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric return DAG.getNode(AVRISD::SELECT_CC, dl, VTs, Ops); 8980b57cec5SDimitry Andric } 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { 9010b57cec5SDimitry Andric SDValue LHS = Op.getOperand(0); 9020b57cec5SDimitry Andric SDValue RHS = Op.getOperand(1); 9030b57cec5SDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); 9040b57cec5SDimitry Andric SDLoc DL(Op); 9050b57cec5SDimitry Andric 9060b57cec5SDimitry Andric SDValue TargetCC; 9070b57cec5SDimitry Andric SDValue Cmp = getAVRCmp(LHS, RHS, CC, TargetCC, DAG, DL); 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric SDValue TrueV = DAG.getConstant(1, DL, Op.getValueType()); 9100b57cec5SDimitry Andric SDValue FalseV = DAG.getConstant(0, DL, Op.getValueType()); 9110b57cec5SDimitry Andric SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); 9120b57cec5SDimitry Andric SDValue Ops[] = {TrueV, FalseV, TargetCC, Cmp}; 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric return DAG.getNode(AVRISD::SELECT_CC, DL, VTs, Ops); 9150b57cec5SDimitry Andric } 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { 9180b57cec5SDimitry Andric const MachineFunction &MF = DAG.getMachineFunction(); 9190b57cec5SDimitry Andric const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>(); 9200b57cec5SDimitry Andric const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 9210b57cec5SDimitry Andric auto DL = DAG.getDataLayout(); 9220b57cec5SDimitry Andric SDLoc dl(Op); 9230b57cec5SDimitry Andric 9240b57cec5SDimitry Andric // Vastart just stores the address of the VarArgsFrameIndex slot into the 9250b57cec5SDimitry Andric // memory location argument. 9260b57cec5SDimitry Andric SDValue FI = DAG.getFrameIndex(AFI->getVarArgsFrameIndex(), getPointerTy(DL)); 9270b57cec5SDimitry Andric 9280b57cec5SDimitry Andric return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), 929e8d8bef9SDimitry Andric MachinePointerInfo(SV)); 9300b57cec5SDimitry Andric } 9310b57cec5SDimitry Andric 932bdd1243dSDimitry Andric // Modify the existing ISD::INLINEASM node to add the implicit zero register. 933bdd1243dSDimitry Andric SDValue AVRTargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const { 934bdd1243dSDimitry Andric SDValue ZeroReg = DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8); 935bdd1243dSDimitry Andric if (Op.getOperand(Op.getNumOperands() - 1) == ZeroReg || 936bdd1243dSDimitry Andric Op.getOperand(Op.getNumOperands() - 2) == ZeroReg) { 937bdd1243dSDimitry Andric // Zero register has already been added. Don't add it again. 938bdd1243dSDimitry Andric // If this isn't handled, we get called over and over again. 939bdd1243dSDimitry Andric return Op; 940bdd1243dSDimitry Andric } 941bdd1243dSDimitry Andric 942bdd1243dSDimitry Andric // Get a list of operands to the new INLINEASM node. This is mostly a copy, 943bdd1243dSDimitry Andric // with some edits. 944bdd1243dSDimitry Andric // Add the following operands at the end (but before the glue node, if it's 945bdd1243dSDimitry Andric // there): 946bdd1243dSDimitry Andric // - The flags of the implicit zero register operand. 947bdd1243dSDimitry Andric // - The implicit zero register operand itself. 948bdd1243dSDimitry Andric SDLoc dl(Op); 949bdd1243dSDimitry Andric SmallVector<SDValue, 8> Ops; 950bdd1243dSDimitry Andric SDNode *N = Op.getNode(); 951bdd1243dSDimitry Andric SDValue Glue; 952bdd1243dSDimitry Andric for (unsigned I = 0; I < N->getNumOperands(); I++) { 953bdd1243dSDimitry Andric SDValue Operand = N->getOperand(I); 954bdd1243dSDimitry Andric if (Operand.getValueType() == MVT::Glue) { 955bdd1243dSDimitry Andric // The glue operand always needs to be at the end, so we need to treat it 956bdd1243dSDimitry Andric // specially. 957bdd1243dSDimitry Andric Glue = Operand; 958bdd1243dSDimitry Andric } else { 959bdd1243dSDimitry Andric Ops.push_back(Operand); 960bdd1243dSDimitry Andric } 961bdd1243dSDimitry Andric } 9625f757f3fSDimitry Andric InlineAsm::Flag Flags(InlineAsm::Kind::RegUse, 1); 963bdd1243dSDimitry Andric Ops.push_back(DAG.getTargetConstant(Flags, dl, MVT::i32)); 964bdd1243dSDimitry Andric Ops.push_back(ZeroReg); 965bdd1243dSDimitry Andric if (Glue) { 966bdd1243dSDimitry Andric Ops.push_back(Glue); 967bdd1243dSDimitry Andric } 968bdd1243dSDimitry Andric 969bdd1243dSDimitry Andric // Replace the current INLINEASM node with a new one that has the zero 970bdd1243dSDimitry Andric // register as implicit parameter. 971bdd1243dSDimitry Andric SDValue New = DAG.getNode(N->getOpcode(), dl, N->getVTList(), Ops); 972bdd1243dSDimitry Andric DAG.ReplaceAllUsesOfValueWith(Op, New); 973bdd1243dSDimitry Andric DAG.ReplaceAllUsesOfValueWith(Op.getValue(1), New.getValue(1)); 974bdd1243dSDimitry Andric 975bdd1243dSDimitry Andric return New; 976bdd1243dSDimitry Andric } 977bdd1243dSDimitry Andric 9780b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { 9790b57cec5SDimitry Andric switch (Op.getOpcode()) { 9800b57cec5SDimitry Andric default: 9810b57cec5SDimitry Andric llvm_unreachable("Don't know how to custom lower this!"); 9820b57cec5SDimitry Andric case ISD::SHL: 9830b57cec5SDimitry Andric case ISD::SRA: 9840b57cec5SDimitry Andric case ISD::SRL: 9850b57cec5SDimitry Andric case ISD::ROTL: 9860b57cec5SDimitry Andric case ISD::ROTR: 9870b57cec5SDimitry Andric return LowerShifts(Op, DAG); 9880b57cec5SDimitry Andric case ISD::GlobalAddress: 9890b57cec5SDimitry Andric return LowerGlobalAddress(Op, DAG); 9900b57cec5SDimitry Andric case ISD::BlockAddress: 9910b57cec5SDimitry Andric return LowerBlockAddress(Op, DAG); 9920b57cec5SDimitry Andric case ISD::BR_CC: 9930b57cec5SDimitry Andric return LowerBR_CC(Op, DAG); 9940b57cec5SDimitry Andric case ISD::SELECT_CC: 9950b57cec5SDimitry Andric return LowerSELECT_CC(Op, DAG); 9960b57cec5SDimitry Andric case ISD::SETCC: 9970b57cec5SDimitry Andric return LowerSETCC(Op, DAG); 9980b57cec5SDimitry Andric case ISD::VASTART: 9990b57cec5SDimitry Andric return LowerVASTART(Op, DAG); 10000b57cec5SDimitry Andric case ISD::SDIVREM: 10010b57cec5SDimitry Andric case ISD::UDIVREM: 10020b57cec5SDimitry Andric return LowerDivRem(Op, DAG); 1003bdd1243dSDimitry Andric case ISD::INLINEASM: 1004bdd1243dSDimitry Andric return LowerINLINEASM(Op, DAG); 10050b57cec5SDimitry Andric } 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric return SDValue(); 10080b57cec5SDimitry Andric } 10090b57cec5SDimitry Andric 10100b57cec5SDimitry Andric /// Replace a node with an illegal result type 10110b57cec5SDimitry Andric /// with a new node built out of custom code. 10120b57cec5SDimitry Andric void AVRTargetLowering::ReplaceNodeResults(SDNode *N, 10130b57cec5SDimitry Andric SmallVectorImpl<SDValue> &Results, 10140b57cec5SDimitry Andric SelectionDAG &DAG) const { 10150b57cec5SDimitry Andric SDLoc DL(N); 10160b57cec5SDimitry Andric 10170b57cec5SDimitry Andric switch (N->getOpcode()) { 10180b57cec5SDimitry Andric case ISD::ADD: { 10190b57cec5SDimitry Andric // Convert add (x, imm) into sub (x, -imm). 10200b57cec5SDimitry Andric if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) { 10210b57cec5SDimitry Andric SDValue Sub = DAG.getNode( 10220b57cec5SDimitry Andric ISD::SUB, DL, N->getValueType(0), N->getOperand(0), 10230b57cec5SDimitry Andric DAG.getConstant(-C->getAPIntValue(), DL, C->getValueType(0))); 10240b57cec5SDimitry Andric Results.push_back(Sub); 10250b57cec5SDimitry Andric } 10260b57cec5SDimitry Andric break; 10270b57cec5SDimitry Andric } 10280b57cec5SDimitry Andric default: { 10290b57cec5SDimitry Andric SDValue Res = LowerOperation(SDValue(N, 0), DAG); 10300b57cec5SDimitry Andric 10310b57cec5SDimitry Andric for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I) 10320b57cec5SDimitry Andric Results.push_back(Res.getValue(I)); 10330b57cec5SDimitry Andric 10340b57cec5SDimitry Andric break; 10350b57cec5SDimitry Andric } 10360b57cec5SDimitry Andric } 10370b57cec5SDimitry Andric } 10380b57cec5SDimitry Andric 10390b57cec5SDimitry Andric /// Return true if the addressing mode represented 10400b57cec5SDimitry Andric /// by AM is legal for this target, for a load/store of the specified type. 10410b57cec5SDimitry Andric bool AVRTargetLowering::isLegalAddressingMode(const DataLayout &DL, 10420b57cec5SDimitry Andric const AddrMode &AM, Type *Ty, 1043349cc55cSDimitry Andric unsigned AS, 1044349cc55cSDimitry Andric Instruction *I) const { 10450b57cec5SDimitry Andric int64_t Offs = AM.BaseOffs; 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric // Allow absolute addresses. 10480b57cec5SDimitry Andric if (AM.BaseGV && !AM.HasBaseReg && AM.Scale == 0 && Offs == 0) { 10490b57cec5SDimitry Andric return true; 10500b57cec5SDimitry Andric } 10510b57cec5SDimitry Andric 10520b57cec5SDimitry Andric // Flash memory instructions only allow zero offsets. 10530b57cec5SDimitry Andric if (isa<PointerType>(Ty) && AS == AVR::ProgramMemory) { 10540b57cec5SDimitry Andric return false; 10550b57cec5SDimitry Andric } 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric // Allow reg+<6bit> offset. 10580b57cec5SDimitry Andric if (Offs < 0) 10590b57cec5SDimitry Andric Offs = -Offs; 106004eeddc0SDimitry Andric if (AM.BaseGV == nullptr && AM.HasBaseReg && AM.Scale == 0 && 106104eeddc0SDimitry Andric isUInt<6>(Offs)) { 10620b57cec5SDimitry Andric return true; 10630b57cec5SDimitry Andric } 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric return false; 10660b57cec5SDimitry Andric } 10670b57cec5SDimitry Andric 10680b57cec5SDimitry Andric /// Returns true by value, base pointer and 10690b57cec5SDimitry Andric /// offset pointer and addressing mode by reference if the node's address 10700b57cec5SDimitry Andric /// can be legally represented as pre-indexed load / store address. 10710b57cec5SDimitry Andric bool AVRTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base, 10720b57cec5SDimitry Andric SDValue &Offset, 10730b57cec5SDimitry Andric ISD::MemIndexedMode &AM, 10740b57cec5SDimitry Andric SelectionDAG &DAG) const { 10750b57cec5SDimitry Andric EVT VT; 10760b57cec5SDimitry Andric const SDNode *Op; 10770b57cec5SDimitry Andric SDLoc DL(N); 10780b57cec5SDimitry Andric 10790b57cec5SDimitry Andric if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) { 10800b57cec5SDimitry Andric VT = LD->getMemoryVT(); 10810b57cec5SDimitry Andric Op = LD->getBasePtr().getNode(); 10820b57cec5SDimitry Andric if (LD->getExtensionType() != ISD::NON_EXTLOAD) 10830b57cec5SDimitry Andric return false; 10840b57cec5SDimitry Andric if (AVR::isProgramMemoryAccess(LD)) { 10850b57cec5SDimitry Andric return false; 10860b57cec5SDimitry Andric } 10870b57cec5SDimitry Andric } else if (const StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) { 10880b57cec5SDimitry Andric VT = ST->getMemoryVT(); 10890b57cec5SDimitry Andric Op = ST->getBasePtr().getNode(); 10900b57cec5SDimitry Andric if (AVR::isProgramMemoryAccess(ST)) { 10910b57cec5SDimitry Andric return false; 10920b57cec5SDimitry Andric } 10930b57cec5SDimitry Andric } else { 10940b57cec5SDimitry Andric return false; 10950b57cec5SDimitry Andric } 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric if (VT != MVT::i8 && VT != MVT::i16) { 10980b57cec5SDimitry Andric return false; 10990b57cec5SDimitry Andric } 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric if (Op->getOpcode() != ISD::ADD && Op->getOpcode() != ISD::SUB) { 11020b57cec5SDimitry Andric return false; 11030b57cec5SDimitry Andric } 11040b57cec5SDimitry Andric 11050b57cec5SDimitry Andric if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Op->getOperand(1))) { 11060b57cec5SDimitry Andric int RHSC = RHS->getSExtValue(); 11070b57cec5SDimitry Andric if (Op->getOpcode() == ISD::SUB) 11080b57cec5SDimitry Andric RHSC = -RHSC; 11090b57cec5SDimitry Andric 11100b57cec5SDimitry Andric if ((VT == MVT::i16 && RHSC != -2) || (VT == MVT::i8 && RHSC != -1)) { 11110b57cec5SDimitry Andric return false; 11120b57cec5SDimitry Andric } 11130b57cec5SDimitry Andric 11140b57cec5SDimitry Andric Base = Op->getOperand(0); 11150b57cec5SDimitry Andric Offset = DAG.getConstant(RHSC, DL, MVT::i8); 11160b57cec5SDimitry Andric AM = ISD::PRE_DEC; 11170b57cec5SDimitry Andric 11180b57cec5SDimitry Andric return true; 11190b57cec5SDimitry Andric } 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andric return false; 11220b57cec5SDimitry Andric } 11230b57cec5SDimitry Andric 11240b57cec5SDimitry Andric /// Returns true by value, base pointer and 11250b57cec5SDimitry Andric /// offset pointer and addressing mode by reference if this node can be 11260b57cec5SDimitry Andric /// combined with a load / store to form a post-indexed load / store. 11270b57cec5SDimitry Andric bool AVRTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op, 11280b57cec5SDimitry Andric SDValue &Base, 11290b57cec5SDimitry Andric SDValue &Offset, 11300b57cec5SDimitry Andric ISD::MemIndexedMode &AM, 11310b57cec5SDimitry Andric SelectionDAG &DAG) const { 11320b57cec5SDimitry Andric EVT VT; 11330b57cec5SDimitry Andric SDLoc DL(N); 11340b57cec5SDimitry Andric 11350b57cec5SDimitry Andric if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) { 11360b57cec5SDimitry Andric VT = LD->getMemoryVT(); 11370b57cec5SDimitry Andric if (LD->getExtensionType() != ISD::NON_EXTLOAD) 11380b57cec5SDimitry Andric return false; 11390b57cec5SDimitry Andric } else if (const StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) { 11400b57cec5SDimitry Andric VT = ST->getMemoryVT(); 114106c3fb27SDimitry Andric // We can not store to program memory. 114206c3fb27SDimitry Andric if (AVR::isProgramMemoryAccess(ST)) 11430b57cec5SDimitry Andric return false; 114406c3fb27SDimitry Andric // Since the high byte need to be stored first, we can not emit 114506c3fb27SDimitry Andric // i16 post increment store like: 114606c3fb27SDimitry Andric // st X+, r24 114706c3fb27SDimitry Andric // st X+, r25 114806c3fb27SDimitry Andric if (VT == MVT::i16 && !Subtarget.hasLowByteFirst()) 114906c3fb27SDimitry Andric return false; 11500b57cec5SDimitry Andric } else { 11510b57cec5SDimitry Andric return false; 11520b57cec5SDimitry Andric } 11530b57cec5SDimitry Andric 11540b57cec5SDimitry Andric if (VT != MVT::i8 && VT != MVT::i16) { 11550b57cec5SDimitry Andric return false; 11560b57cec5SDimitry Andric } 11570b57cec5SDimitry Andric 11580b57cec5SDimitry Andric if (Op->getOpcode() != ISD::ADD && Op->getOpcode() != ISD::SUB) { 11590b57cec5SDimitry Andric return false; 11600b57cec5SDimitry Andric } 11610b57cec5SDimitry Andric 11620b57cec5SDimitry Andric if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Op->getOperand(1))) { 11630b57cec5SDimitry Andric int RHSC = RHS->getSExtValue(); 11640b57cec5SDimitry Andric if (Op->getOpcode() == ISD::SUB) 11650b57cec5SDimitry Andric RHSC = -RHSC; 11660b57cec5SDimitry Andric if ((VT == MVT::i16 && RHSC != 2) || (VT == MVT::i8 && RHSC != 1)) { 11670b57cec5SDimitry Andric return false; 11680b57cec5SDimitry Andric } 11690b57cec5SDimitry Andric 117006c3fb27SDimitry Andric // FIXME: We temporarily disable post increment load from program memory, 117106c3fb27SDimitry Andric // due to bug https://github.com/llvm/llvm-project/issues/59914. 117206c3fb27SDimitry Andric if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) 117306c3fb27SDimitry Andric if (AVR::isProgramMemoryAccess(LD)) 117406c3fb27SDimitry Andric return false; 117506c3fb27SDimitry Andric 11760b57cec5SDimitry Andric Base = Op->getOperand(0); 11770b57cec5SDimitry Andric Offset = DAG.getConstant(RHSC, DL, MVT::i8); 11780b57cec5SDimitry Andric AM = ISD::POST_INC; 11790b57cec5SDimitry Andric 11800b57cec5SDimitry Andric return true; 11810b57cec5SDimitry Andric } 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric return false; 11840b57cec5SDimitry Andric } 11850b57cec5SDimitry Andric 11860b57cec5SDimitry Andric bool AVRTargetLowering::isOffsetFoldingLegal( 11870b57cec5SDimitry Andric const GlobalAddressSDNode *GA) const { 11880b57cec5SDimitry Andric return true; 11890b57cec5SDimitry Andric } 11900b57cec5SDimitry Andric 11910b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 11920b57cec5SDimitry Andric // Formal Arguments Calling Convention Implementation 11930b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 11940b57cec5SDimitry Andric 11950b57cec5SDimitry Andric #include "AVRGenCallingConv.inc" 11960b57cec5SDimitry Andric 11975ffd83dbSDimitry Andric /// Registers for calling conventions, ordered in reverse as required by ABI. 11985ffd83dbSDimitry Andric /// Both arrays must be of the same length. 119981ad6265SDimitry Andric static const MCPhysReg RegList8AVR[] = { 12005ffd83dbSDimitry Andric AVR::R25, AVR::R24, AVR::R23, AVR::R22, AVR::R21, AVR::R20, 12015ffd83dbSDimitry Andric AVR::R19, AVR::R18, AVR::R17, AVR::R16, AVR::R15, AVR::R14, 12025ffd83dbSDimitry Andric AVR::R13, AVR::R12, AVR::R11, AVR::R10, AVR::R9, AVR::R8}; 120381ad6265SDimitry Andric static const MCPhysReg RegList8Tiny[] = {AVR::R25, AVR::R24, AVR::R23, 120481ad6265SDimitry Andric AVR::R22, AVR::R21, AVR::R20}; 120581ad6265SDimitry Andric static const MCPhysReg RegList16AVR[] = { 1206349cc55cSDimitry Andric AVR::R26R25, AVR::R25R24, AVR::R24R23, AVR::R23R22, AVR::R22R21, 1207349cc55cSDimitry Andric AVR::R21R20, AVR::R20R19, AVR::R19R18, AVR::R18R17, AVR::R17R16, 1208349cc55cSDimitry Andric AVR::R16R15, AVR::R15R14, AVR::R14R13, AVR::R13R12, AVR::R12R11, 1209349cc55cSDimitry Andric AVR::R11R10, AVR::R10R9, AVR::R9R8}; 121081ad6265SDimitry Andric static const MCPhysReg RegList16Tiny[] = {AVR::R26R25, AVR::R25R24, 121181ad6265SDimitry Andric AVR::R24R23, AVR::R23R22, 121281ad6265SDimitry Andric AVR::R22R21, AVR::R21R20}; 12130b57cec5SDimitry Andric 1214bdd1243dSDimitry Andric static_assert(std::size(RegList8AVR) == std::size(RegList16AVR), 121581ad6265SDimitry Andric "8-bit and 16-bit register arrays must be of equal length"); 1216bdd1243dSDimitry Andric static_assert(std::size(RegList8Tiny) == std::size(RegList16Tiny), 12175ffd83dbSDimitry Andric "8-bit and 16-bit register arrays must be of equal length"); 12180b57cec5SDimitry Andric 12190b57cec5SDimitry Andric /// Analyze incoming and outgoing function arguments. We need custom C++ code 12205ffd83dbSDimitry Andric /// to handle special constraints in the ABI. 12215ffd83dbSDimitry Andric /// In addition, all pieces of a certain argument have to be passed either 12225ffd83dbSDimitry Andric /// using registers or the stack but never mixing both. 12235ffd83dbSDimitry Andric template <typename ArgT> 122481ad6265SDimitry Andric static void analyzeArguments(TargetLowering::CallLoweringInfo *CLI, 122581ad6265SDimitry Andric const Function *F, const DataLayout *TD, 122681ad6265SDimitry Andric const SmallVectorImpl<ArgT> &Args, 122781ad6265SDimitry Andric SmallVectorImpl<CCValAssign> &ArgLocs, 122881ad6265SDimitry Andric CCState &CCInfo, bool Tiny) { 122981ad6265SDimitry Andric // Choose the proper register list for argument passing according to the ABI. 123081ad6265SDimitry Andric ArrayRef<MCPhysReg> RegList8; 123181ad6265SDimitry Andric ArrayRef<MCPhysReg> RegList16; 123281ad6265SDimitry Andric if (Tiny) { 1233*0fca6ea1SDimitry Andric RegList8 = ArrayRef(RegList8Tiny); 1234*0fca6ea1SDimitry Andric RegList16 = ArrayRef(RegList16Tiny); 123581ad6265SDimitry Andric } else { 1236*0fca6ea1SDimitry Andric RegList8 = ArrayRef(RegList8AVR); 1237*0fca6ea1SDimitry Andric RegList16 = ArrayRef(RegList16AVR); 123881ad6265SDimitry Andric } 123981ad6265SDimitry Andric 12405ffd83dbSDimitry Andric unsigned NumArgs = Args.size(); 12415ffd83dbSDimitry Andric // This is the index of the last used register, in RegList*. 12425ffd83dbSDimitry Andric // -1 means R26 (R26 is never actually used in CC). 12435ffd83dbSDimitry Andric int RegLastIdx = -1; 12445ffd83dbSDimitry Andric // Once a value is passed to the stack it will always be used 12455ffd83dbSDimitry Andric bool UseStack = false; 12465ffd83dbSDimitry Andric for (unsigned i = 0; i != NumArgs;) { 12475ffd83dbSDimitry Andric MVT VT = Args[i].VT; 12485ffd83dbSDimitry Andric // We have to count the number of bytes for each function argument, that is 12495ffd83dbSDimitry Andric // those Args with the same OrigArgIndex. This is important in case the 12505ffd83dbSDimitry Andric // function takes an aggregate type. 12515ffd83dbSDimitry Andric // Current argument will be between [i..j). 12525ffd83dbSDimitry Andric unsigned ArgIndex = Args[i].OrigArgIndex; 12535ffd83dbSDimitry Andric unsigned TotalBytes = VT.getStoreSize(); 12545ffd83dbSDimitry Andric unsigned j = i + 1; 12555ffd83dbSDimitry Andric for (; j != NumArgs; ++j) { 12565ffd83dbSDimitry Andric if (Args[j].OrigArgIndex != ArgIndex) 12575ffd83dbSDimitry Andric break; 12585ffd83dbSDimitry Andric TotalBytes += Args[j].VT.getStoreSize(); 12590b57cec5SDimitry Andric } 12605ffd83dbSDimitry Andric // Round up to even number of bytes. 12615ffd83dbSDimitry Andric TotalBytes = alignTo(TotalBytes, 2); 12625ffd83dbSDimitry Andric // Skip zero sized arguments 12635ffd83dbSDimitry Andric if (TotalBytes == 0) 12645ffd83dbSDimitry Andric continue; 12655ffd83dbSDimitry Andric // The index of the first register to be used 12665ffd83dbSDimitry Andric unsigned RegIdx = RegLastIdx + TotalBytes; 12675ffd83dbSDimitry Andric RegLastIdx = RegIdx; 12685ffd83dbSDimitry Andric // If there are not enough registers, use the stack 126981ad6265SDimitry Andric if (RegIdx >= RegList8.size()) { 12705ffd83dbSDimitry Andric UseStack = true; 12710b57cec5SDimitry Andric } 12725ffd83dbSDimitry Andric for (; i != j; ++i) { 12735ffd83dbSDimitry Andric MVT VT = Args[i].VT; 12740b57cec5SDimitry Andric 12755ffd83dbSDimitry Andric if (UseStack) { 12765ffd83dbSDimitry Andric auto evt = EVT(VT).getTypeForEVT(CCInfo.getContext()); 12775ffd83dbSDimitry Andric unsigned Offset = CCInfo.AllocateStack(TD->getTypeAllocSize(evt), 12785ffd83dbSDimitry Andric TD->getABITypeAlign(evt)); 12790b57cec5SDimitry Andric CCInfo.addLoc( 12805ffd83dbSDimitry Andric CCValAssign::getMem(i, VT, Offset, VT, CCValAssign::Full)); 12810b57cec5SDimitry Andric } else { 12825ffd83dbSDimitry Andric unsigned Reg; 12835ffd83dbSDimitry Andric if (VT == MVT::i8) { 12845ffd83dbSDimitry Andric Reg = CCInfo.AllocateReg(RegList8[RegIdx]); 12855ffd83dbSDimitry Andric } else if (VT == MVT::i16) { 12865ffd83dbSDimitry Andric Reg = CCInfo.AllocateReg(RegList16[RegIdx]); 12870b57cec5SDimitry Andric } else { 12885ffd83dbSDimitry Andric llvm_unreachable( 12895ffd83dbSDimitry Andric "calling convention can only manage i8 and i16 types"); 12905ffd83dbSDimitry Andric } 12915ffd83dbSDimitry Andric assert(Reg && "register not available in calling convention"); 12925ffd83dbSDimitry Andric CCInfo.addLoc(CCValAssign::getReg(i, VT, Reg, VT, CCValAssign::Full)); 12935ffd83dbSDimitry Andric // Registers inside a particular argument are sorted in increasing order 12945ffd83dbSDimitry Andric // (remember the array is reversed). 12955ffd83dbSDimitry Andric RegIdx -= VT.getStoreSize(); 12965ffd83dbSDimitry Andric } 12975ffd83dbSDimitry Andric } 12980b57cec5SDimitry Andric } 12990b57cec5SDimitry Andric } 13000b57cec5SDimitry Andric 13015ffd83dbSDimitry Andric /// Count the total number of bytes needed to pass or return these arguments. 13025ffd83dbSDimitry Andric template <typename ArgT> 1303349cc55cSDimitry Andric static unsigned 1304349cc55cSDimitry Andric getTotalArgumentsSizeInBytes(const SmallVectorImpl<ArgT> &Args) { 13055ffd83dbSDimitry Andric unsigned TotalBytes = 0; 13065ffd83dbSDimitry Andric 13075ffd83dbSDimitry Andric for (const ArgT &Arg : Args) { 13085ffd83dbSDimitry Andric TotalBytes += Arg.VT.getStoreSize(); 13090b57cec5SDimitry Andric } 13105ffd83dbSDimitry Andric return TotalBytes; 13110b57cec5SDimitry Andric } 13125ffd83dbSDimitry Andric 13135ffd83dbSDimitry Andric /// Analyze incoming and outgoing value of returning from a function. 13145ffd83dbSDimitry Andric /// The algorithm is similar to analyzeArguments, but there can only be 13155ffd83dbSDimitry Andric /// one value, possibly an aggregate, and it is limited to 8 bytes. 13165ffd83dbSDimitry Andric template <typename ArgT> 13175ffd83dbSDimitry Andric static void analyzeReturnValues(const SmallVectorImpl<ArgT> &Args, 131881ad6265SDimitry Andric CCState &CCInfo, bool Tiny) { 13195ffd83dbSDimitry Andric unsigned NumArgs = Args.size(); 13205ffd83dbSDimitry Andric unsigned TotalBytes = getTotalArgumentsSizeInBytes(Args); 13215ffd83dbSDimitry Andric // CanLowerReturn() guarantees this assertion. 1322bdd1243dSDimitry Andric if (Tiny) 1323bdd1243dSDimitry Andric assert(TotalBytes <= 4 && 1324bdd1243dSDimitry Andric "return values greater than 4 bytes cannot be lowered on AVRTiny"); 1325bdd1243dSDimitry Andric else 1326349cc55cSDimitry Andric assert(TotalBytes <= 8 && 1327bdd1243dSDimitry Andric "return values greater than 8 bytes cannot be lowered on AVR"); 13285ffd83dbSDimitry Andric 132981ad6265SDimitry Andric // Choose the proper register list for argument passing according to the ABI. 133081ad6265SDimitry Andric ArrayRef<MCPhysReg> RegList8; 133181ad6265SDimitry Andric ArrayRef<MCPhysReg> RegList16; 133281ad6265SDimitry Andric if (Tiny) { 1333*0fca6ea1SDimitry Andric RegList8 = ArrayRef(RegList8Tiny); 1334*0fca6ea1SDimitry Andric RegList16 = ArrayRef(RegList16Tiny); 133581ad6265SDimitry Andric } else { 1336*0fca6ea1SDimitry Andric RegList8 = ArrayRef(RegList8AVR); 1337*0fca6ea1SDimitry Andric RegList16 = ArrayRef(RegList16AVR); 133881ad6265SDimitry Andric } 133981ad6265SDimitry Andric 13405ffd83dbSDimitry Andric // GCC-ABI says that the size is rounded up to the next even number, 13415ffd83dbSDimitry Andric // but actually once it is more than 4 it will always round up to 8. 13425ffd83dbSDimitry Andric if (TotalBytes > 4) { 13435ffd83dbSDimitry Andric TotalBytes = 8; 13445ffd83dbSDimitry Andric } else { 13455ffd83dbSDimitry Andric TotalBytes = alignTo(TotalBytes, 2); 13465ffd83dbSDimitry Andric } 13475ffd83dbSDimitry Andric 13485ffd83dbSDimitry Andric // The index of the first register to use. 13495ffd83dbSDimitry Andric int RegIdx = TotalBytes - 1; 13505ffd83dbSDimitry Andric for (unsigned i = 0; i != NumArgs; ++i) { 13515ffd83dbSDimitry Andric MVT VT = Args[i].VT; 13525ffd83dbSDimitry Andric unsigned Reg; 13535ffd83dbSDimitry Andric if (VT == MVT::i8) { 13545ffd83dbSDimitry Andric Reg = CCInfo.AllocateReg(RegList8[RegIdx]); 13555ffd83dbSDimitry Andric } else if (VT == MVT::i16) { 13565ffd83dbSDimitry Andric Reg = CCInfo.AllocateReg(RegList16[RegIdx]); 13575ffd83dbSDimitry Andric } else { 13585ffd83dbSDimitry Andric llvm_unreachable("calling convention can only manage i8 and i16 types"); 13595ffd83dbSDimitry Andric } 13605ffd83dbSDimitry Andric assert(Reg && "register not available in calling convention"); 13615ffd83dbSDimitry Andric CCInfo.addLoc(CCValAssign::getReg(i, VT, Reg, VT, CCValAssign::Full)); 13625ffd83dbSDimitry Andric // Registers sort in increasing order 13635ffd83dbSDimitry Andric RegIdx -= VT.getStoreSize(); 13640b57cec5SDimitry Andric } 13650b57cec5SDimitry Andric } 13660b57cec5SDimitry Andric 13670b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerFormalArguments( 13680b57cec5SDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool isVarArg, 13695ffd83dbSDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl, 13705ffd83dbSDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 13710b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 13720b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 13730b57cec5SDimitry Andric auto DL = DAG.getDataLayout(); 13740b57cec5SDimitry Andric 13750b57cec5SDimitry Andric // Assign locations to all of the incoming arguments. 13760b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 13770b57cec5SDimitry Andric CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, 13780b57cec5SDimitry Andric *DAG.getContext()); 13790b57cec5SDimitry Andric 13805ffd83dbSDimitry Andric // Variadic functions do not need all the analysis below. 13815ffd83dbSDimitry Andric if (isVarArg) { 13825ffd83dbSDimitry Andric CCInfo.AnalyzeFormalArguments(Ins, ArgCC_AVR_Vararg); 13835ffd83dbSDimitry Andric } else { 138481ad6265SDimitry Andric analyzeArguments(nullptr, &MF.getFunction(), &DL, Ins, ArgLocs, CCInfo, 138581ad6265SDimitry Andric Subtarget.hasTinyEncoding()); 13865ffd83dbSDimitry Andric } 13870b57cec5SDimitry Andric 13880b57cec5SDimitry Andric SDValue ArgValue; 13890b57cec5SDimitry Andric for (CCValAssign &VA : ArgLocs) { 13900b57cec5SDimitry Andric 13910b57cec5SDimitry Andric // Arguments stored on registers. 13920b57cec5SDimitry Andric if (VA.isRegLoc()) { 13930b57cec5SDimitry Andric EVT RegVT = VA.getLocVT(); 13940b57cec5SDimitry Andric const TargetRegisterClass *RC; 13950b57cec5SDimitry Andric if (RegVT == MVT::i8) { 13960b57cec5SDimitry Andric RC = &AVR::GPR8RegClass; 13970b57cec5SDimitry Andric } else if (RegVT == MVT::i16) { 13980b57cec5SDimitry Andric RC = &AVR::DREGSRegClass; 13990b57cec5SDimitry Andric } else { 14000b57cec5SDimitry Andric llvm_unreachable("Unknown argument type!"); 14010b57cec5SDimitry Andric } 14020b57cec5SDimitry Andric 140304eeddc0SDimitry Andric Register Reg = MF.addLiveIn(VA.getLocReg(), RC); 14040b57cec5SDimitry Andric ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); 14050b57cec5SDimitry Andric 14060b57cec5SDimitry Andric // :NOTE: Clang should not promote any i8 into i16 but for safety the 14070b57cec5SDimitry Andric // following code will handle zexts or sexts generated by other 14080b57cec5SDimitry Andric // front ends. Otherwise: 14090b57cec5SDimitry Andric // If this is an 8 bit value, it is really passed promoted 14100b57cec5SDimitry Andric // to 16 bits. Insert an assert[sz]ext to capture this, then 14110b57cec5SDimitry Andric // truncate to the right size. 14120b57cec5SDimitry Andric switch (VA.getLocInfo()) { 14130b57cec5SDimitry Andric default: 14140b57cec5SDimitry Andric llvm_unreachable("Unknown loc info!"); 14150b57cec5SDimitry Andric case CCValAssign::Full: 14160b57cec5SDimitry Andric break; 14170b57cec5SDimitry Andric case CCValAssign::BCvt: 14180b57cec5SDimitry Andric ArgValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), ArgValue); 14190b57cec5SDimitry Andric break; 14200b57cec5SDimitry Andric case CCValAssign::SExt: 14210b57cec5SDimitry Andric ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, 14220b57cec5SDimitry Andric DAG.getValueType(VA.getValVT())); 14230b57cec5SDimitry Andric ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); 14240b57cec5SDimitry Andric break; 14250b57cec5SDimitry Andric case CCValAssign::ZExt: 14260b57cec5SDimitry Andric ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, 14270b57cec5SDimitry Andric DAG.getValueType(VA.getValVT())); 14280b57cec5SDimitry Andric ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); 14290b57cec5SDimitry Andric break; 14300b57cec5SDimitry Andric } 14310b57cec5SDimitry Andric 14320b57cec5SDimitry Andric InVals.push_back(ArgValue); 14330b57cec5SDimitry Andric } else { 1434349cc55cSDimitry Andric // Only arguments passed on the stack should make it here. 14350b57cec5SDimitry Andric assert(VA.isMemLoc()); 14360b57cec5SDimitry Andric 14370b57cec5SDimitry Andric EVT LocVT = VA.getLocVT(); 14380b57cec5SDimitry Andric 14390b57cec5SDimitry Andric // Create the frame index object for this incoming parameter. 14400b57cec5SDimitry Andric int FI = MFI.CreateFixedObject(LocVT.getSizeInBits() / 8, 14410b57cec5SDimitry Andric VA.getLocMemOffset(), true); 14420b57cec5SDimitry Andric 14430b57cec5SDimitry Andric // Create the SelectionDAG nodes corresponding to a load 14440b57cec5SDimitry Andric // from this parameter. 14450b57cec5SDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DL)); 14460b57cec5SDimitry Andric InVals.push_back(DAG.getLoad(LocVT, dl, Chain, FIN, 1447e8d8bef9SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI))); 14480b57cec5SDimitry Andric } 14490b57cec5SDimitry Andric } 14500b57cec5SDimitry Andric 14510b57cec5SDimitry Andric // If the function takes variable number of arguments, make a frame index for 14520b57cec5SDimitry Andric // the start of the first vararg value... for expansion of llvm.va_start. 14530b57cec5SDimitry Andric if (isVarArg) { 145406c3fb27SDimitry Andric unsigned StackSize = CCInfo.getStackSize(); 14550b57cec5SDimitry Andric AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>(); 14560b57cec5SDimitry Andric 14570b57cec5SDimitry Andric AFI->setVarArgsFrameIndex(MFI.CreateFixedObject(2, StackSize, true)); 14580b57cec5SDimitry Andric } 14590b57cec5SDimitry Andric 14600b57cec5SDimitry Andric return Chain; 14610b57cec5SDimitry Andric } 14620b57cec5SDimitry Andric 14630b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14640b57cec5SDimitry Andric // Call Calling Convention Implementation 14650b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14660b57cec5SDimitry Andric 14670b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, 14680b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) const { 14690b57cec5SDimitry Andric SelectionDAG &DAG = CLI.DAG; 14700b57cec5SDimitry Andric SDLoc &DL = CLI.DL; 14710b57cec5SDimitry Andric SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; 14720b57cec5SDimitry Andric SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; 14730b57cec5SDimitry Andric SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; 14740b57cec5SDimitry Andric SDValue Chain = CLI.Chain; 14750b57cec5SDimitry Andric SDValue Callee = CLI.Callee; 14760b57cec5SDimitry Andric bool &isTailCall = CLI.IsTailCall; 14770b57cec5SDimitry Andric CallingConv::ID CallConv = CLI.CallConv; 14780b57cec5SDimitry Andric bool isVarArg = CLI.IsVarArg; 14790b57cec5SDimitry Andric 14800b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 14810b57cec5SDimitry Andric 14820b57cec5SDimitry Andric // AVR does not yet support tail call optimization. 14830b57cec5SDimitry Andric isTailCall = false; 14840b57cec5SDimitry Andric 14850b57cec5SDimitry Andric // Analyze operands of the call, assigning locations to each operand. 14860b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 14870b57cec5SDimitry Andric CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs, 14880b57cec5SDimitry Andric *DAG.getContext()); 14890b57cec5SDimitry Andric 14900b57cec5SDimitry Andric // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every 14910b57cec5SDimitry Andric // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol 14920b57cec5SDimitry Andric // node so that legalize doesn't hack it. 14930b57cec5SDimitry Andric const Function *F = nullptr; 14940b57cec5SDimitry Andric if (const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { 14950b57cec5SDimitry Andric const GlobalValue *GV = G->getGlobal(); 149681ad6265SDimitry Andric if (isa<Function>(GV)) 14970b57cec5SDimitry Andric F = cast<Function>(GV); 14980b57cec5SDimitry Andric Callee = 14990b57cec5SDimitry Andric DAG.getTargetGlobalAddress(GV, DL, getPointerTy(DAG.getDataLayout())); 15000b57cec5SDimitry Andric } else if (const ExternalSymbolSDNode *ES = 15010b57cec5SDimitry Andric dyn_cast<ExternalSymbolSDNode>(Callee)) { 15020b57cec5SDimitry Andric Callee = DAG.getTargetExternalSymbol(ES->getSymbol(), 15030b57cec5SDimitry Andric getPointerTy(DAG.getDataLayout())); 15040b57cec5SDimitry Andric } 15050b57cec5SDimitry Andric 15065ffd83dbSDimitry Andric // Variadic functions do not need all the analysis below. 15075ffd83dbSDimitry Andric if (isVarArg) { 15085ffd83dbSDimitry Andric CCInfo.AnalyzeCallOperands(Outs, ArgCC_AVR_Vararg); 15095ffd83dbSDimitry Andric } else { 151081ad6265SDimitry Andric analyzeArguments(&CLI, F, &DAG.getDataLayout(), Outs, ArgLocs, CCInfo, 151181ad6265SDimitry Andric Subtarget.hasTinyEncoding()); 15125ffd83dbSDimitry Andric } 15130b57cec5SDimitry Andric 15140b57cec5SDimitry Andric // Get a count of how many bytes are to be pushed on the stack. 151506c3fb27SDimitry Andric unsigned NumBytes = CCInfo.getStackSize(); 15160b57cec5SDimitry Andric 15170b57cec5SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, DL); 15180b57cec5SDimitry Andric 15190b57cec5SDimitry Andric SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; 15200b57cec5SDimitry Andric 15210b57cec5SDimitry Andric // First, walk the register assignments, inserting copies. 15220b57cec5SDimitry Andric unsigned AI, AE; 15230b57cec5SDimitry Andric bool HasStackArgs = false; 15240b57cec5SDimitry Andric for (AI = 0, AE = ArgLocs.size(); AI != AE; ++AI) { 15250b57cec5SDimitry Andric CCValAssign &VA = ArgLocs[AI]; 15260b57cec5SDimitry Andric EVT RegVT = VA.getLocVT(); 15270b57cec5SDimitry Andric SDValue Arg = OutVals[AI]; 15280b57cec5SDimitry Andric 15290b57cec5SDimitry Andric // Promote the value if needed. With Clang this should not happen. 15300b57cec5SDimitry Andric switch (VA.getLocInfo()) { 15310b57cec5SDimitry Andric default: 15320b57cec5SDimitry Andric llvm_unreachable("Unknown loc info!"); 15330b57cec5SDimitry Andric case CCValAssign::Full: 15340b57cec5SDimitry Andric break; 15350b57cec5SDimitry Andric case CCValAssign::SExt: 15360b57cec5SDimitry Andric Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, RegVT, Arg); 15370b57cec5SDimitry Andric break; 15380b57cec5SDimitry Andric case CCValAssign::ZExt: 15390b57cec5SDimitry Andric Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, RegVT, Arg); 15400b57cec5SDimitry Andric break; 15410b57cec5SDimitry Andric case CCValAssign::AExt: 15420b57cec5SDimitry Andric Arg = DAG.getNode(ISD::ANY_EXTEND, DL, RegVT, Arg); 15430b57cec5SDimitry Andric break; 15440b57cec5SDimitry Andric case CCValAssign::BCvt: 15450b57cec5SDimitry Andric Arg = DAG.getNode(ISD::BITCAST, DL, RegVT, Arg); 15460b57cec5SDimitry Andric break; 15470b57cec5SDimitry Andric } 15480b57cec5SDimitry Andric 15490b57cec5SDimitry Andric // Stop when we encounter a stack argument, we need to process them 15500b57cec5SDimitry Andric // in reverse order in the loop below. 15510b57cec5SDimitry Andric if (VA.isMemLoc()) { 15520b57cec5SDimitry Andric HasStackArgs = true; 15530b57cec5SDimitry Andric break; 15540b57cec5SDimitry Andric } 15550b57cec5SDimitry Andric 15560b57cec5SDimitry Andric // Arguments that can be passed on registers must be kept in the RegsToPass 15570b57cec5SDimitry Andric // vector. 15580b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 15590b57cec5SDimitry Andric } 15600b57cec5SDimitry Andric 1561fe6060f1SDimitry Andric // Second, stack arguments have to walked. 1562fe6060f1SDimitry Andric // Previously this code created chained stores but those chained stores appear 1563fe6060f1SDimitry Andric // to be unchained in the legalization phase. Therefore, do not attempt to 1564fe6060f1SDimitry Andric // chain them here. In fact, chaining them here somehow causes the first and 1565fe6060f1SDimitry Andric // second store to be reversed which is the exact opposite of the intended 1566fe6060f1SDimitry Andric // effect. 15670b57cec5SDimitry Andric if (HasStackArgs) { 1568fe6060f1SDimitry Andric SmallVector<SDValue, 8> MemOpChains; 1569fe6060f1SDimitry Andric for (; AI != AE; AI++) { 1570fe6060f1SDimitry Andric CCValAssign &VA = ArgLocs[AI]; 1571fe6060f1SDimitry Andric SDValue Arg = OutVals[AI]; 15720b57cec5SDimitry Andric 15730b57cec5SDimitry Andric assert(VA.isMemLoc()); 15740b57cec5SDimitry Andric 15750b57cec5SDimitry Andric // SP points to one stack slot further so add one to adjust it. 15760b57cec5SDimitry Andric SDValue PtrOff = DAG.getNode( 15770b57cec5SDimitry Andric ISD::ADD, DL, getPointerTy(DAG.getDataLayout()), 15780b57cec5SDimitry Andric DAG.getRegister(AVR::SP, getPointerTy(DAG.getDataLayout())), 15790b57cec5SDimitry Andric DAG.getIntPtrConstant(VA.getLocMemOffset() + 1, DL)); 15800b57cec5SDimitry Andric 1581fe6060f1SDimitry Andric MemOpChains.push_back( 15820b57cec5SDimitry Andric DAG.getStore(Chain, DL, Arg, PtrOff, 1583fe6060f1SDimitry Andric MachinePointerInfo::getStack(MF, VA.getLocMemOffset()))); 15840b57cec5SDimitry Andric } 1585fe6060f1SDimitry Andric 1586fe6060f1SDimitry Andric if (!MemOpChains.empty()) 1587fe6060f1SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); 15880b57cec5SDimitry Andric } 15890b57cec5SDimitry Andric 15900b57cec5SDimitry Andric // Build a sequence of copy-to-reg nodes chained together with token chain and 159106c3fb27SDimitry Andric // flag operands which copy the outgoing args into registers. The InGlue in 15920b57cec5SDimitry Andric // necessary since all emited instructions must be stuck together. 159306c3fb27SDimitry Andric SDValue InGlue; 15940b57cec5SDimitry Andric for (auto Reg : RegsToPass) { 159506c3fb27SDimitry Andric Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, InGlue); 159606c3fb27SDimitry Andric InGlue = Chain.getValue(1); 15970b57cec5SDimitry Andric } 15980b57cec5SDimitry Andric 15990b57cec5SDimitry Andric // Returns a chain & a flag for retval copy to use. 16000b57cec5SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 16010b57cec5SDimitry Andric SmallVector<SDValue, 8> Ops; 16020b57cec5SDimitry Andric Ops.push_back(Chain); 16030b57cec5SDimitry Andric Ops.push_back(Callee); 16040b57cec5SDimitry Andric 16050b57cec5SDimitry Andric // Add argument registers to the end of the list so that they are known live 16060b57cec5SDimitry Andric // into the call. 16070b57cec5SDimitry Andric for (auto Reg : RegsToPass) { 16080b57cec5SDimitry Andric Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType())); 16090b57cec5SDimitry Andric } 16100b57cec5SDimitry Andric 1611bdd1243dSDimitry Andric // The zero register (usually R1) must be passed as an implicit register so 1612bdd1243dSDimitry Andric // that this register is correctly zeroed in interrupts. 1613bdd1243dSDimitry Andric Ops.push_back(DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8)); 1614bdd1243dSDimitry Andric 16150b57cec5SDimitry Andric // Add a register mask operand representing the call-preserved registers. 16160b57cec5SDimitry Andric const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 16170b57cec5SDimitry Andric const uint32_t *Mask = 16180b57cec5SDimitry Andric TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv); 16190b57cec5SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention"); 16200b57cec5SDimitry Andric Ops.push_back(DAG.getRegisterMask(Mask)); 16210b57cec5SDimitry Andric 162206c3fb27SDimitry Andric if (InGlue.getNode()) { 162306c3fb27SDimitry Andric Ops.push_back(InGlue); 16240b57cec5SDimitry Andric } 16250b57cec5SDimitry Andric 16260b57cec5SDimitry Andric Chain = DAG.getNode(AVRISD::CALL, DL, NodeTys, Ops); 162706c3fb27SDimitry Andric InGlue = Chain.getValue(1); 16280b57cec5SDimitry Andric 16290b57cec5SDimitry Andric // Create the CALLSEQ_END node. 163006c3fb27SDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL); 16310b57cec5SDimitry Andric 16320b57cec5SDimitry Andric if (!Ins.empty()) { 163306c3fb27SDimitry Andric InGlue = Chain.getValue(1); 16340b57cec5SDimitry Andric } 16350b57cec5SDimitry Andric 16360b57cec5SDimitry Andric // Handle result values, copying them out of physregs into vregs that we 16370b57cec5SDimitry Andric // return. 163806c3fb27SDimitry Andric return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, DL, DAG, 16390b57cec5SDimitry Andric InVals); 16400b57cec5SDimitry Andric } 16410b57cec5SDimitry Andric 16420b57cec5SDimitry Andric /// Lower the result values of a call into the 16430b57cec5SDimitry Andric /// appropriate copies out of appropriate physical registers. 16440b57cec5SDimitry Andric /// 16450b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerCallResult( 164606c3fb27SDimitry Andric SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg, 1647349cc55cSDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl, 1648349cc55cSDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 16490b57cec5SDimitry Andric 16500b57cec5SDimitry Andric // Assign locations to each value returned by this call. 16510b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 16520b57cec5SDimitry Andric CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, 16530b57cec5SDimitry Andric *DAG.getContext()); 16540b57cec5SDimitry Andric 16550b57cec5SDimitry Andric // Handle runtime calling convs. 16565ffd83dbSDimitry Andric if (CallConv == CallingConv::AVR_BUILTIN) { 16575ffd83dbSDimitry Andric CCInfo.AnalyzeCallResult(Ins, RetCC_AVR_BUILTIN); 16585ffd83dbSDimitry Andric } else { 165981ad6265SDimitry Andric analyzeReturnValues(Ins, CCInfo, Subtarget.hasTinyEncoding()); 16600b57cec5SDimitry Andric } 16610b57cec5SDimitry Andric 16620b57cec5SDimitry Andric // Copy all of the result registers out of their specified physreg. 16630b57cec5SDimitry Andric for (CCValAssign const &RVLoc : RVLocs) { 16640b57cec5SDimitry Andric Chain = DAG.getCopyFromReg(Chain, dl, RVLoc.getLocReg(), RVLoc.getValVT(), 166506c3fb27SDimitry Andric InGlue) 16660b57cec5SDimitry Andric .getValue(1); 166706c3fb27SDimitry Andric InGlue = Chain.getValue(2); 16680b57cec5SDimitry Andric InVals.push_back(Chain.getValue(0)); 16690b57cec5SDimitry Andric } 16700b57cec5SDimitry Andric 16710b57cec5SDimitry Andric return Chain; 16720b57cec5SDimitry Andric } 16730b57cec5SDimitry Andric 16740b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 16750b57cec5SDimitry Andric // Return Value Calling Convention Implementation 16760b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 16770b57cec5SDimitry Andric 16785ffd83dbSDimitry Andric bool AVRTargetLowering::CanLowerReturn( 16795ffd83dbSDimitry Andric CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, 16805ffd83dbSDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { 16815ffd83dbSDimitry Andric if (CallConv == CallingConv::AVR_BUILTIN) { 16820b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 16830b57cec5SDimitry Andric CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context); 16845ffd83dbSDimitry Andric return CCInfo.CheckReturn(Outs, RetCC_AVR_BUILTIN); 16855ffd83dbSDimitry Andric } 16860b57cec5SDimitry Andric 16875ffd83dbSDimitry Andric unsigned TotalBytes = getTotalArgumentsSizeInBytes(Outs); 1688bdd1243dSDimitry Andric return TotalBytes <= (unsigned)(Subtarget.hasTinyEncoding() ? 4 : 8); 16890b57cec5SDimitry Andric } 16900b57cec5SDimitry Andric 16910b57cec5SDimitry Andric SDValue 16920b57cec5SDimitry Andric AVRTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, 16930b57cec5SDimitry Andric bool isVarArg, 16940b57cec5SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 16950b57cec5SDimitry Andric const SmallVectorImpl<SDValue> &OutVals, 16960b57cec5SDimitry Andric const SDLoc &dl, SelectionDAG &DAG) const { 16970b57cec5SDimitry Andric // CCValAssign - represent the assignment of the return value to locations. 16980b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 16990b57cec5SDimitry Andric 17000b57cec5SDimitry Andric // CCState - Info about the registers and stack slot. 17010b57cec5SDimitry Andric CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs, 17020b57cec5SDimitry Andric *DAG.getContext()); 17030b57cec5SDimitry Andric 17040b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 17050b57cec5SDimitry Andric 17065ffd83dbSDimitry Andric // Analyze return values. 17075ffd83dbSDimitry Andric if (CallConv == CallingConv::AVR_BUILTIN) { 17085ffd83dbSDimitry Andric CCInfo.AnalyzeReturn(Outs, RetCC_AVR_BUILTIN); 17095ffd83dbSDimitry Andric } else { 171081ad6265SDimitry Andric analyzeReturnValues(Outs, CCInfo, Subtarget.hasTinyEncoding()); 17110b57cec5SDimitry Andric } 17120b57cec5SDimitry Andric 171306c3fb27SDimitry Andric SDValue Glue; 17140b57cec5SDimitry Andric SmallVector<SDValue, 4> RetOps(1, Chain); 17150b57cec5SDimitry Andric // Copy the result values into the output registers. 17165ffd83dbSDimitry Andric for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { 17170b57cec5SDimitry Andric CCValAssign &VA = RVLocs[i]; 17180b57cec5SDimitry Andric assert(VA.isRegLoc() && "Can only return in registers!"); 17190b57cec5SDimitry Andric 172006c3fb27SDimitry Andric Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue); 17210b57cec5SDimitry Andric 17220b57cec5SDimitry Andric // Guarantee that all emitted copies are stuck together with flags. 172306c3fb27SDimitry Andric Glue = Chain.getValue(1); 17240b57cec5SDimitry Andric RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 17250b57cec5SDimitry Andric } 17260b57cec5SDimitry Andric 17270b57cec5SDimitry Andric // Don't emit the ret/reti instruction when the naked attribute is present in 17280b57cec5SDimitry Andric // the function being compiled. 1729349cc55cSDimitry Andric if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) { 17300b57cec5SDimitry Andric return Chain; 17310b57cec5SDimitry Andric } 17320b57cec5SDimitry Andric 17335ffd83dbSDimitry Andric const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>(); 17345ffd83dbSDimitry Andric 1735bdd1243dSDimitry Andric if (!AFI->isInterruptOrSignalHandler()) { 1736bdd1243dSDimitry Andric // The return instruction has an implicit zero register operand: it must 1737bdd1243dSDimitry Andric // contain zero on return. 1738bdd1243dSDimitry Andric // This is not needed in interrupts however, where the zero register is 1739bdd1243dSDimitry Andric // handled specially (only pushed/popped when needed). 1740bdd1243dSDimitry Andric RetOps.push_back(DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8)); 1741bdd1243dSDimitry Andric } 1742bdd1243dSDimitry Andric 17430b57cec5SDimitry Andric unsigned RetOpc = 174406c3fb27SDimitry Andric AFI->isInterruptOrSignalHandler() ? AVRISD::RETI_GLUE : AVRISD::RET_GLUE; 17450b57cec5SDimitry Andric 17460b57cec5SDimitry Andric RetOps[0] = Chain; // Update chain. 17470b57cec5SDimitry Andric 174806c3fb27SDimitry Andric if (Glue.getNode()) { 174906c3fb27SDimitry Andric RetOps.push_back(Glue); 17500b57cec5SDimitry Andric } 17510b57cec5SDimitry Andric 17520b57cec5SDimitry Andric return DAG.getNode(RetOpc, dl, MVT::Other, RetOps); 17530b57cec5SDimitry Andric } 17540b57cec5SDimitry Andric 17550b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 17560b57cec5SDimitry Andric // Custom Inserters 17570b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 17580b57cec5SDimitry Andric 17590b57cec5SDimitry Andric MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI, 176006c3fb27SDimitry Andric MachineBasicBlock *BB, 176106c3fb27SDimitry Andric bool Tiny) const { 17620b57cec5SDimitry Andric unsigned Opc; 17630b57cec5SDimitry Andric const TargetRegisterClass *RC; 17640b57cec5SDimitry Andric bool HasRepeatedOperand = false; 17650b57cec5SDimitry Andric MachineFunction *F = BB->getParent(); 17660b57cec5SDimitry Andric MachineRegisterInfo &RI = F->getRegInfo(); 17670b57cec5SDimitry Andric const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 17680b57cec5SDimitry Andric DebugLoc dl = MI.getDebugLoc(); 17690b57cec5SDimitry Andric 17700b57cec5SDimitry Andric switch (MI.getOpcode()) { 17710b57cec5SDimitry Andric default: 17720b57cec5SDimitry Andric llvm_unreachable("Invalid shift opcode!"); 17730b57cec5SDimitry Andric case AVR::Lsl8: 17740b57cec5SDimitry Andric Opc = AVR::ADDRdRr; // LSL is an alias of ADD Rd, Rd 17750b57cec5SDimitry Andric RC = &AVR::GPR8RegClass; 17760b57cec5SDimitry Andric HasRepeatedOperand = true; 17770b57cec5SDimitry Andric break; 17780b57cec5SDimitry Andric case AVR::Lsl16: 17790b57cec5SDimitry Andric Opc = AVR::LSLWRd; 17800b57cec5SDimitry Andric RC = &AVR::DREGSRegClass; 17810b57cec5SDimitry Andric break; 17820b57cec5SDimitry Andric case AVR::Asr8: 17830b57cec5SDimitry Andric Opc = AVR::ASRRd; 17840b57cec5SDimitry Andric RC = &AVR::GPR8RegClass; 17850b57cec5SDimitry Andric break; 17860b57cec5SDimitry Andric case AVR::Asr16: 17870b57cec5SDimitry Andric Opc = AVR::ASRWRd; 17880b57cec5SDimitry Andric RC = &AVR::DREGSRegClass; 17890b57cec5SDimitry Andric break; 17900b57cec5SDimitry Andric case AVR::Lsr8: 17910b57cec5SDimitry Andric Opc = AVR::LSRRd; 17920b57cec5SDimitry Andric RC = &AVR::GPR8RegClass; 17930b57cec5SDimitry Andric break; 17940b57cec5SDimitry Andric case AVR::Lsr16: 17950b57cec5SDimitry Andric Opc = AVR::LSRWRd; 17960b57cec5SDimitry Andric RC = &AVR::DREGSRegClass; 17970b57cec5SDimitry Andric break; 17980b57cec5SDimitry Andric case AVR::Rol8: 179906c3fb27SDimitry Andric Opc = Tiny ? AVR::ROLBRdR17 : AVR::ROLBRdR1; 18000b57cec5SDimitry Andric RC = &AVR::GPR8RegClass; 18010b57cec5SDimitry Andric break; 18020b57cec5SDimitry Andric case AVR::Rol16: 18030b57cec5SDimitry Andric Opc = AVR::ROLWRd; 18040b57cec5SDimitry Andric RC = &AVR::DREGSRegClass; 18050b57cec5SDimitry Andric break; 18060b57cec5SDimitry Andric case AVR::Ror8: 1807480093f4SDimitry Andric Opc = AVR::RORBRd; 18080b57cec5SDimitry Andric RC = &AVR::GPR8RegClass; 18090b57cec5SDimitry Andric break; 18100b57cec5SDimitry Andric case AVR::Ror16: 18110b57cec5SDimitry Andric Opc = AVR::RORWRd; 18120b57cec5SDimitry Andric RC = &AVR::DREGSRegClass; 18130b57cec5SDimitry Andric break; 18140b57cec5SDimitry Andric } 18150b57cec5SDimitry Andric 18160b57cec5SDimitry Andric const BasicBlock *LLVM_BB = BB->getBasicBlock(); 18170b57cec5SDimitry Andric 18180b57cec5SDimitry Andric MachineFunction::iterator I; 1819349cc55cSDimitry Andric for (I = BB->getIterator(); I != F->end() && &(*I) != BB; ++I) 1820349cc55cSDimitry Andric ; 1821349cc55cSDimitry Andric if (I != F->end()) 1822349cc55cSDimitry Andric ++I; 18230b57cec5SDimitry Andric 18240b57cec5SDimitry Andric // Create loop block. 18250b57cec5SDimitry Andric MachineBasicBlock *LoopBB = F->CreateMachineBasicBlock(LLVM_BB); 1826e8d8bef9SDimitry Andric MachineBasicBlock *CheckBB = F->CreateMachineBasicBlock(LLVM_BB); 18270b57cec5SDimitry Andric MachineBasicBlock *RemBB = F->CreateMachineBasicBlock(LLVM_BB); 18280b57cec5SDimitry Andric 18290b57cec5SDimitry Andric F->insert(I, LoopBB); 1830e8d8bef9SDimitry Andric F->insert(I, CheckBB); 18310b57cec5SDimitry Andric F->insert(I, RemBB); 18320b57cec5SDimitry Andric 18330b57cec5SDimitry Andric // Update machine-CFG edges by transferring all successors of the current 18340b57cec5SDimitry Andric // block to the block containing instructions after shift. 18350b57cec5SDimitry Andric RemBB->splice(RemBB->begin(), BB, std::next(MachineBasicBlock::iterator(MI)), 18360b57cec5SDimitry Andric BB->end()); 18370b57cec5SDimitry Andric RemBB->transferSuccessorsAndUpdatePHIs(BB); 18380b57cec5SDimitry Andric 1839e8d8bef9SDimitry Andric // Add edges BB => LoopBB => CheckBB => RemBB, CheckBB => LoopBB. 1840e8d8bef9SDimitry Andric BB->addSuccessor(CheckBB); 1841e8d8bef9SDimitry Andric LoopBB->addSuccessor(CheckBB); 1842e8d8bef9SDimitry Andric CheckBB->addSuccessor(LoopBB); 1843e8d8bef9SDimitry Andric CheckBB->addSuccessor(RemBB); 18440b57cec5SDimitry Andric 1845e8d8bef9SDimitry Andric Register ShiftAmtReg = RI.createVirtualRegister(&AVR::GPR8RegClass); 1846e8d8bef9SDimitry Andric Register ShiftAmtReg2 = RI.createVirtualRegister(&AVR::GPR8RegClass); 18478bcb0991SDimitry Andric Register ShiftReg = RI.createVirtualRegister(RC); 18488bcb0991SDimitry Andric Register ShiftReg2 = RI.createVirtualRegister(RC); 18498bcb0991SDimitry Andric Register ShiftAmtSrcReg = MI.getOperand(2).getReg(); 18508bcb0991SDimitry Andric Register SrcReg = MI.getOperand(1).getReg(); 18518bcb0991SDimitry Andric Register DstReg = MI.getOperand(0).getReg(); 18520b57cec5SDimitry Andric 18530b57cec5SDimitry Andric // BB: 1854e8d8bef9SDimitry Andric // rjmp CheckBB 1855e8d8bef9SDimitry Andric BuildMI(BB, dl, TII.get(AVR::RJMPk)).addMBB(CheckBB); 18560b57cec5SDimitry Andric 18570b57cec5SDimitry Andric // LoopBB: 18580b57cec5SDimitry Andric // ShiftReg2 = shift ShiftReg 18590b57cec5SDimitry Andric auto ShiftMI = BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2).addReg(ShiftReg); 18600b57cec5SDimitry Andric if (HasRepeatedOperand) 18610b57cec5SDimitry Andric ShiftMI.addReg(ShiftReg); 18620b57cec5SDimitry Andric 1863e8d8bef9SDimitry Andric // CheckBB: 1864e8d8bef9SDimitry Andric // ShiftReg = phi [%SrcReg, BB], [%ShiftReg2, LoopBB] 1865e8d8bef9SDimitry Andric // ShiftAmt = phi [%N, BB], [%ShiftAmt2, LoopBB] 18660b57cec5SDimitry Andric // DestReg = phi [%SrcReg, BB], [%ShiftReg, LoopBB] 1867e8d8bef9SDimitry Andric // ShiftAmt2 = ShiftAmt - 1; 1868e8d8bef9SDimitry Andric // if (ShiftAmt2 >= 0) goto LoopBB; 1869e8d8bef9SDimitry Andric BuildMI(CheckBB, dl, TII.get(AVR::PHI), ShiftReg) 18700b57cec5SDimitry Andric .addReg(SrcReg) 18710b57cec5SDimitry Andric .addMBB(BB) 18720b57cec5SDimitry Andric .addReg(ShiftReg2) 18730b57cec5SDimitry Andric .addMBB(LoopBB); 1874e8d8bef9SDimitry Andric BuildMI(CheckBB, dl, TII.get(AVR::PHI), ShiftAmtReg) 1875e8d8bef9SDimitry Andric .addReg(ShiftAmtSrcReg) 1876e8d8bef9SDimitry Andric .addMBB(BB) 1877e8d8bef9SDimitry Andric .addReg(ShiftAmtReg2) 1878e8d8bef9SDimitry Andric .addMBB(LoopBB); 1879e8d8bef9SDimitry Andric BuildMI(CheckBB, dl, TII.get(AVR::PHI), DstReg) 1880e8d8bef9SDimitry Andric .addReg(SrcReg) 1881e8d8bef9SDimitry Andric .addMBB(BB) 1882e8d8bef9SDimitry Andric .addReg(ShiftReg2) 1883e8d8bef9SDimitry Andric .addMBB(LoopBB); 1884e8d8bef9SDimitry Andric 1885349cc55cSDimitry Andric BuildMI(CheckBB, dl, TII.get(AVR::DECRd), ShiftAmtReg2).addReg(ShiftAmtReg); 1886e8d8bef9SDimitry Andric BuildMI(CheckBB, dl, TII.get(AVR::BRPLk)).addMBB(LoopBB); 18870b57cec5SDimitry Andric 18880b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now. 18890b57cec5SDimitry Andric return RemBB; 18900b57cec5SDimitry Andric } 18910b57cec5SDimitry Andric 1892bdd1243dSDimitry Andric // Do a multibyte AVR shift. Insert shift instructions and put the output 1893bdd1243dSDimitry Andric // registers in the Regs array. 1894bdd1243dSDimitry Andric // Because AVR does not have a normal shift instruction (only a single bit shift 1895bdd1243dSDimitry Andric // instruction), we have to emulate this behavior with other instructions. 1896bdd1243dSDimitry Andric // It first tries large steps (moving registers around) and then smaller steps 1897bdd1243dSDimitry Andric // like single bit shifts. 1898bdd1243dSDimitry Andric // Large shifts actually reduce the number of shifted registers, so the below 1899bdd1243dSDimitry Andric // algorithms have to work independently of the number of registers that are 1900bdd1243dSDimitry Andric // shifted. 1901bdd1243dSDimitry Andric // For more information and background, see this blogpost: 1902bdd1243dSDimitry Andric // https://aykevl.nl/2021/02/avr-bitshift 1903bdd1243dSDimitry Andric static void insertMultibyteShift(MachineInstr &MI, MachineBasicBlock *BB, 1904bdd1243dSDimitry Andric MutableArrayRef<std::pair<Register, int>> Regs, 1905bdd1243dSDimitry Andric ISD::NodeType Opc, int64_t ShiftAmt) { 1906bdd1243dSDimitry Andric const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo(); 1907bdd1243dSDimitry Andric const AVRSubtarget &STI = BB->getParent()->getSubtarget<AVRSubtarget>(); 1908bdd1243dSDimitry Andric MachineRegisterInfo &MRI = BB->getParent()->getRegInfo(); 1909bdd1243dSDimitry Andric const DebugLoc &dl = MI.getDebugLoc(); 1910bdd1243dSDimitry Andric 1911bdd1243dSDimitry Andric const bool ShiftLeft = Opc == ISD::SHL; 1912bdd1243dSDimitry Andric const bool ArithmeticShift = Opc == ISD::SRA; 1913bdd1243dSDimitry Andric 1914bdd1243dSDimitry Andric // Zero a register, for use in later operations. 1915bdd1243dSDimitry Andric Register ZeroReg = MRI.createVirtualRegister(&AVR::GPR8RegClass); 1916bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::COPY), ZeroReg) 1917bdd1243dSDimitry Andric .addReg(STI.getZeroRegister()); 1918bdd1243dSDimitry Andric 1919bdd1243dSDimitry Andric // Do a shift modulo 6 or 7. This is a bit more complicated than most shifts 1920bdd1243dSDimitry Andric // and is hard to compose with the rest, so these are special cased. 1921bdd1243dSDimitry Andric // The basic idea is to shift one or two bits in the opposite direction and 1922bdd1243dSDimitry Andric // then move registers around to get the correct end result. 1923bdd1243dSDimitry Andric if (ShiftLeft && (ShiftAmt % 8) >= 6) { 1924bdd1243dSDimitry Andric // Left shift modulo 6 or 7. 1925bdd1243dSDimitry Andric 1926bdd1243dSDimitry Andric // Create a slice of the registers we're going to modify, to ease working 1927bdd1243dSDimitry Andric // with them. 1928bdd1243dSDimitry Andric size_t ShiftRegsOffset = ShiftAmt / 8; 1929bdd1243dSDimitry Andric size_t ShiftRegsSize = Regs.size() - ShiftRegsOffset; 1930bdd1243dSDimitry Andric MutableArrayRef<std::pair<Register, int>> ShiftRegs = 1931bdd1243dSDimitry Andric Regs.slice(ShiftRegsOffset, ShiftRegsSize); 1932bdd1243dSDimitry Andric 1933bdd1243dSDimitry Andric // Shift one to the right, keeping the least significant bit as the carry 1934bdd1243dSDimitry Andric // bit. 1935bdd1243dSDimitry Andric insertMultibyteShift(MI, BB, ShiftRegs, ISD::SRL, 1); 1936bdd1243dSDimitry Andric 1937bdd1243dSDimitry Andric // Rotate the least significant bit from the carry bit into a new register 1938bdd1243dSDimitry Andric // (that starts out zero). 1939bdd1243dSDimitry Andric Register LowByte = MRI.createVirtualRegister(&AVR::GPR8RegClass); 1940bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::RORRd), LowByte).addReg(ZeroReg); 1941bdd1243dSDimitry Andric 1942bdd1243dSDimitry Andric // Shift one more to the right if this is a modulo-6 shift. 1943bdd1243dSDimitry Andric if (ShiftAmt % 8 == 6) { 1944bdd1243dSDimitry Andric insertMultibyteShift(MI, BB, ShiftRegs, ISD::SRL, 1); 1945bdd1243dSDimitry Andric Register NewLowByte = MRI.createVirtualRegister(&AVR::GPR8RegClass); 1946bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::RORRd), NewLowByte).addReg(LowByte); 1947bdd1243dSDimitry Andric LowByte = NewLowByte; 1948bdd1243dSDimitry Andric } 1949bdd1243dSDimitry Andric 1950bdd1243dSDimitry Andric // Move all registers to the left, zeroing the bottom registers as needed. 1951bdd1243dSDimitry Andric for (size_t I = 0; I < Regs.size(); I++) { 1952bdd1243dSDimitry Andric int ShiftRegsIdx = I + 1; 1953bdd1243dSDimitry Andric if (ShiftRegsIdx < (int)ShiftRegs.size()) { 1954bdd1243dSDimitry Andric Regs[I] = ShiftRegs[ShiftRegsIdx]; 1955bdd1243dSDimitry Andric } else if (ShiftRegsIdx == (int)ShiftRegs.size()) { 1956bdd1243dSDimitry Andric Regs[I] = std::pair(LowByte, 0); 1957bdd1243dSDimitry Andric } else { 1958bdd1243dSDimitry Andric Regs[I] = std::pair(ZeroReg, 0); 1959bdd1243dSDimitry Andric } 1960bdd1243dSDimitry Andric } 1961bdd1243dSDimitry Andric 1962bdd1243dSDimitry Andric return; 1963bdd1243dSDimitry Andric } 1964bdd1243dSDimitry Andric 1965bdd1243dSDimitry Andric // Right shift modulo 6 or 7. 1966bdd1243dSDimitry Andric if (!ShiftLeft && (ShiftAmt % 8) >= 6) { 1967bdd1243dSDimitry Andric // Create a view on the registers we're going to modify, to ease working 1968bdd1243dSDimitry Andric // with them. 1969bdd1243dSDimitry Andric size_t ShiftRegsSize = Regs.size() - (ShiftAmt / 8); 1970bdd1243dSDimitry Andric MutableArrayRef<std::pair<Register, int>> ShiftRegs = 1971bdd1243dSDimitry Andric Regs.slice(0, ShiftRegsSize); 1972bdd1243dSDimitry Andric 1973bdd1243dSDimitry Andric // Shift one to the left. 1974bdd1243dSDimitry Andric insertMultibyteShift(MI, BB, ShiftRegs, ISD::SHL, 1); 1975bdd1243dSDimitry Andric 1976bdd1243dSDimitry Andric // Sign or zero extend the most significant register into a new register. 1977bdd1243dSDimitry Andric // The HighByte is the byte that still has one (or two) bits from the 1978bdd1243dSDimitry Andric // original value. The ExtByte is purely a zero/sign extend byte (all bits 1979bdd1243dSDimitry Andric // are either 0 or 1). 1980bdd1243dSDimitry Andric Register HighByte = MRI.createVirtualRegister(&AVR::GPR8RegClass); 1981bdd1243dSDimitry Andric Register ExtByte = 0; 1982bdd1243dSDimitry Andric if (ArithmeticShift) { 1983bdd1243dSDimitry Andric // Sign-extend bit that was shifted out last. 1984bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::SBCRdRr), HighByte) 1985bdd1243dSDimitry Andric .addReg(HighByte, RegState::Undef) 1986bdd1243dSDimitry Andric .addReg(HighByte, RegState::Undef); 1987bdd1243dSDimitry Andric ExtByte = HighByte; 1988bdd1243dSDimitry Andric // The highest bit of the original value is the same as the zero-extend 1989bdd1243dSDimitry Andric // byte, so HighByte and ExtByte are the same. 1990bdd1243dSDimitry Andric } else { 1991bdd1243dSDimitry Andric // Use the zero register for zero extending. 1992bdd1243dSDimitry Andric ExtByte = ZeroReg; 1993bdd1243dSDimitry Andric // Rotate most significant bit into a new register (that starts out zero). 1994bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::ADCRdRr), HighByte) 1995bdd1243dSDimitry Andric .addReg(ExtByte) 1996bdd1243dSDimitry Andric .addReg(ExtByte); 1997bdd1243dSDimitry Andric } 1998bdd1243dSDimitry Andric 1999bdd1243dSDimitry Andric // Shift one more to the left for modulo 6 shifts. 2000bdd1243dSDimitry Andric if (ShiftAmt % 8 == 6) { 2001bdd1243dSDimitry Andric insertMultibyteShift(MI, BB, ShiftRegs, ISD::SHL, 1); 2002bdd1243dSDimitry Andric // Shift the topmost bit into the HighByte. 2003bdd1243dSDimitry Andric Register NewExt = MRI.createVirtualRegister(&AVR::GPR8RegClass); 2004bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::ADCRdRr), NewExt) 2005bdd1243dSDimitry Andric .addReg(HighByte) 2006bdd1243dSDimitry Andric .addReg(HighByte); 2007bdd1243dSDimitry Andric HighByte = NewExt; 2008bdd1243dSDimitry Andric } 2009bdd1243dSDimitry Andric 2010bdd1243dSDimitry Andric // Move all to the right, while sign or zero extending. 2011bdd1243dSDimitry Andric for (int I = Regs.size() - 1; I >= 0; I--) { 2012bdd1243dSDimitry Andric int ShiftRegsIdx = I - (Regs.size() - ShiftRegs.size()) - 1; 2013bdd1243dSDimitry Andric if (ShiftRegsIdx >= 0) { 2014bdd1243dSDimitry Andric Regs[I] = ShiftRegs[ShiftRegsIdx]; 2015bdd1243dSDimitry Andric } else if (ShiftRegsIdx == -1) { 2016bdd1243dSDimitry Andric Regs[I] = std::pair(HighByte, 0); 2017bdd1243dSDimitry Andric } else { 2018bdd1243dSDimitry Andric Regs[I] = std::pair(ExtByte, 0); 2019bdd1243dSDimitry Andric } 2020bdd1243dSDimitry Andric } 2021bdd1243dSDimitry Andric 2022bdd1243dSDimitry Andric return; 2023bdd1243dSDimitry Andric } 2024bdd1243dSDimitry Andric 2025bdd1243dSDimitry Andric // For shift amounts of at least one register, simply rename the registers and 2026bdd1243dSDimitry Andric // zero the bottom registers. 2027bdd1243dSDimitry Andric while (ShiftLeft && ShiftAmt >= 8) { 2028bdd1243dSDimitry Andric // Move all registers one to the left. 2029bdd1243dSDimitry Andric for (size_t I = 0; I < Regs.size() - 1; I++) { 2030bdd1243dSDimitry Andric Regs[I] = Regs[I + 1]; 2031bdd1243dSDimitry Andric } 2032bdd1243dSDimitry Andric 2033bdd1243dSDimitry Andric // Zero the least significant register. 2034bdd1243dSDimitry Andric Regs[Regs.size() - 1] = std::pair(ZeroReg, 0); 2035bdd1243dSDimitry Andric 2036bdd1243dSDimitry Andric // Continue shifts with the leftover registers. 2037bdd1243dSDimitry Andric Regs = Regs.drop_back(1); 2038bdd1243dSDimitry Andric 2039bdd1243dSDimitry Andric ShiftAmt -= 8; 2040bdd1243dSDimitry Andric } 2041bdd1243dSDimitry Andric 2042bdd1243dSDimitry Andric // And again, the same for right shifts. 2043bdd1243dSDimitry Andric Register ShrExtendReg = 0; 2044bdd1243dSDimitry Andric if (!ShiftLeft && ShiftAmt >= 8) { 2045bdd1243dSDimitry Andric if (ArithmeticShift) { 2046bdd1243dSDimitry Andric // Sign extend the most significant register into ShrExtendReg. 2047bdd1243dSDimitry Andric ShrExtendReg = MRI.createVirtualRegister(&AVR::GPR8RegClass); 2048bdd1243dSDimitry Andric Register Tmp = MRI.createVirtualRegister(&AVR::GPR8RegClass); 2049bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::ADDRdRr), Tmp) 2050bdd1243dSDimitry Andric .addReg(Regs[0].first, 0, Regs[0].second) 2051bdd1243dSDimitry Andric .addReg(Regs[0].first, 0, Regs[0].second); 2052bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::SBCRdRr), ShrExtendReg) 2053bdd1243dSDimitry Andric .addReg(Tmp) 2054bdd1243dSDimitry Andric .addReg(Tmp); 2055bdd1243dSDimitry Andric } else { 2056bdd1243dSDimitry Andric ShrExtendReg = ZeroReg; 2057bdd1243dSDimitry Andric } 2058bdd1243dSDimitry Andric for (; ShiftAmt >= 8; ShiftAmt -= 8) { 2059bdd1243dSDimitry Andric // Move all registers one to the right. 2060bdd1243dSDimitry Andric for (size_t I = Regs.size() - 1; I != 0; I--) { 2061bdd1243dSDimitry Andric Regs[I] = Regs[I - 1]; 2062bdd1243dSDimitry Andric } 2063bdd1243dSDimitry Andric 2064bdd1243dSDimitry Andric // Zero or sign extend the most significant register. 2065bdd1243dSDimitry Andric Regs[0] = std::pair(ShrExtendReg, 0); 2066bdd1243dSDimitry Andric 2067bdd1243dSDimitry Andric // Continue shifts with the leftover registers. 2068bdd1243dSDimitry Andric Regs = Regs.drop_front(1); 2069bdd1243dSDimitry Andric } 2070bdd1243dSDimitry Andric } 2071bdd1243dSDimitry Andric 2072bdd1243dSDimitry Andric // The bigger shifts are already handled above. 2073bdd1243dSDimitry Andric assert((ShiftAmt < 8) && "Unexpect shift amount"); 2074bdd1243dSDimitry Andric 2075bdd1243dSDimitry Andric // Shift by four bits, using a complicated swap/eor/andi/eor sequence. 2076bdd1243dSDimitry Andric // It only works for logical shifts because the bits shifted in are all 2077bdd1243dSDimitry Andric // zeroes. 2078bdd1243dSDimitry Andric // To shift a single byte right, it produces code like this: 2079bdd1243dSDimitry Andric // swap r0 2080bdd1243dSDimitry Andric // andi r0, 0x0f 2081bdd1243dSDimitry Andric // For a two-byte (16-bit) shift, it adds the following instructions to shift 2082bdd1243dSDimitry Andric // the upper byte into the lower byte: 2083bdd1243dSDimitry Andric // swap r1 2084bdd1243dSDimitry Andric // eor r0, r1 2085bdd1243dSDimitry Andric // andi r1, 0x0f 2086bdd1243dSDimitry Andric // eor r0, r1 2087bdd1243dSDimitry Andric // For bigger shifts, it repeats the above sequence. For example, for a 3-byte 2088bdd1243dSDimitry Andric // (24-bit) shift it adds: 2089bdd1243dSDimitry Andric // swap r2 2090bdd1243dSDimitry Andric // eor r1, r2 2091bdd1243dSDimitry Andric // andi r2, 0x0f 2092bdd1243dSDimitry Andric // eor r1, r2 2093bdd1243dSDimitry Andric if (!ArithmeticShift && ShiftAmt >= 4) { 2094bdd1243dSDimitry Andric Register Prev = 0; 2095bdd1243dSDimitry Andric for (size_t I = 0; I < Regs.size(); I++) { 2096bdd1243dSDimitry Andric size_t Idx = ShiftLeft ? I : Regs.size() - I - 1; 2097bdd1243dSDimitry Andric Register SwapReg = MRI.createVirtualRegister(&AVR::LD8RegClass); 2098bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::SWAPRd), SwapReg) 2099bdd1243dSDimitry Andric .addReg(Regs[Idx].first, 0, Regs[Idx].second); 2100bdd1243dSDimitry Andric if (I != 0) { 2101bdd1243dSDimitry Andric Register R = MRI.createVirtualRegister(&AVR::GPR8RegClass); 2102bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::EORRdRr), R) 2103bdd1243dSDimitry Andric .addReg(Prev) 2104bdd1243dSDimitry Andric .addReg(SwapReg); 2105bdd1243dSDimitry Andric Prev = R; 2106bdd1243dSDimitry Andric } 2107bdd1243dSDimitry Andric Register AndReg = MRI.createVirtualRegister(&AVR::LD8RegClass); 2108bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::ANDIRdK), AndReg) 2109bdd1243dSDimitry Andric .addReg(SwapReg) 2110bdd1243dSDimitry Andric .addImm(ShiftLeft ? 0xf0 : 0x0f); 2111bdd1243dSDimitry Andric if (I != 0) { 2112bdd1243dSDimitry Andric Register R = MRI.createVirtualRegister(&AVR::GPR8RegClass); 2113bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::EORRdRr), R) 2114bdd1243dSDimitry Andric .addReg(Prev) 2115bdd1243dSDimitry Andric .addReg(AndReg); 2116bdd1243dSDimitry Andric size_t PrevIdx = ShiftLeft ? Idx - 1 : Idx + 1; 2117bdd1243dSDimitry Andric Regs[PrevIdx] = std::pair(R, 0); 2118bdd1243dSDimitry Andric } 2119bdd1243dSDimitry Andric Prev = AndReg; 2120bdd1243dSDimitry Andric Regs[Idx] = std::pair(AndReg, 0); 2121bdd1243dSDimitry Andric } 2122bdd1243dSDimitry Andric ShiftAmt -= 4; 2123bdd1243dSDimitry Andric } 2124bdd1243dSDimitry Andric 2125bdd1243dSDimitry Andric // Shift by one. This is the fallback that always works, and the shift 2126bdd1243dSDimitry Andric // operation that is used for 1, 2, and 3 bit shifts. 2127bdd1243dSDimitry Andric while (ShiftLeft && ShiftAmt) { 2128bdd1243dSDimitry Andric // Shift one to the left. 2129bdd1243dSDimitry Andric for (ssize_t I = Regs.size() - 1; I >= 0; I--) { 2130bdd1243dSDimitry Andric Register Out = MRI.createVirtualRegister(&AVR::GPR8RegClass); 2131bdd1243dSDimitry Andric Register In = Regs[I].first; 2132bdd1243dSDimitry Andric Register InSubreg = Regs[I].second; 2133bdd1243dSDimitry Andric if (I == (ssize_t)Regs.size() - 1) { // first iteration 2134bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::ADDRdRr), Out) 2135bdd1243dSDimitry Andric .addReg(In, 0, InSubreg) 2136bdd1243dSDimitry Andric .addReg(In, 0, InSubreg); 2137bdd1243dSDimitry Andric } else { 2138bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::ADCRdRr), Out) 2139bdd1243dSDimitry Andric .addReg(In, 0, InSubreg) 2140bdd1243dSDimitry Andric .addReg(In, 0, InSubreg); 2141bdd1243dSDimitry Andric } 2142bdd1243dSDimitry Andric Regs[I] = std::pair(Out, 0); 2143bdd1243dSDimitry Andric } 2144bdd1243dSDimitry Andric ShiftAmt--; 2145bdd1243dSDimitry Andric } 2146bdd1243dSDimitry Andric while (!ShiftLeft && ShiftAmt) { 2147bdd1243dSDimitry Andric // Shift one to the right. 2148bdd1243dSDimitry Andric for (size_t I = 0; I < Regs.size(); I++) { 2149bdd1243dSDimitry Andric Register Out = MRI.createVirtualRegister(&AVR::GPR8RegClass); 2150bdd1243dSDimitry Andric Register In = Regs[I].first; 2151bdd1243dSDimitry Andric Register InSubreg = Regs[I].second; 2152bdd1243dSDimitry Andric if (I == 0) { 2153bdd1243dSDimitry Andric unsigned Opc = ArithmeticShift ? AVR::ASRRd : AVR::LSRRd; 2154bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(Opc), Out).addReg(In, 0, InSubreg); 2155bdd1243dSDimitry Andric } else { 2156bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::RORRd), Out).addReg(In, 0, InSubreg); 2157bdd1243dSDimitry Andric } 2158bdd1243dSDimitry Andric Regs[I] = std::pair(Out, 0); 2159bdd1243dSDimitry Andric } 2160bdd1243dSDimitry Andric ShiftAmt--; 2161bdd1243dSDimitry Andric } 2162bdd1243dSDimitry Andric 2163bdd1243dSDimitry Andric if (ShiftAmt != 0) { 2164bdd1243dSDimitry Andric llvm_unreachable("don't know how to shift!"); // sanity check 2165bdd1243dSDimitry Andric } 2166bdd1243dSDimitry Andric } 2167bdd1243dSDimitry Andric 2168bdd1243dSDimitry Andric // Do a wide (32-bit) shift. 2169bdd1243dSDimitry Andric MachineBasicBlock * 2170bdd1243dSDimitry Andric AVRTargetLowering::insertWideShift(MachineInstr &MI, 2171bdd1243dSDimitry Andric MachineBasicBlock *BB) const { 2172bdd1243dSDimitry Andric const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 2173bdd1243dSDimitry Andric const DebugLoc &dl = MI.getDebugLoc(); 2174bdd1243dSDimitry Andric 2175bdd1243dSDimitry Andric // How much to shift to the right (meaning: a negative number indicates a left 2176bdd1243dSDimitry Andric // shift). 2177bdd1243dSDimitry Andric int64_t ShiftAmt = MI.getOperand(4).getImm(); 2178bdd1243dSDimitry Andric ISD::NodeType Opc; 2179bdd1243dSDimitry Andric switch (MI.getOpcode()) { 2180bdd1243dSDimitry Andric case AVR::Lsl32: 2181bdd1243dSDimitry Andric Opc = ISD::SHL; 2182bdd1243dSDimitry Andric break; 2183bdd1243dSDimitry Andric case AVR::Lsr32: 2184bdd1243dSDimitry Andric Opc = ISD::SRL; 2185bdd1243dSDimitry Andric break; 2186bdd1243dSDimitry Andric case AVR::Asr32: 2187bdd1243dSDimitry Andric Opc = ISD::SRA; 2188bdd1243dSDimitry Andric break; 2189bdd1243dSDimitry Andric } 2190bdd1243dSDimitry Andric 2191bdd1243dSDimitry Andric // Read the input registers, with the most significant register at index 0. 2192bdd1243dSDimitry Andric std::array<std::pair<Register, int>, 4> Registers = { 2193bdd1243dSDimitry Andric std::pair(MI.getOperand(3).getReg(), AVR::sub_hi), 2194bdd1243dSDimitry Andric std::pair(MI.getOperand(3).getReg(), AVR::sub_lo), 2195bdd1243dSDimitry Andric std::pair(MI.getOperand(2).getReg(), AVR::sub_hi), 2196bdd1243dSDimitry Andric std::pair(MI.getOperand(2).getReg(), AVR::sub_lo), 2197bdd1243dSDimitry Andric }; 2198bdd1243dSDimitry Andric 2199bdd1243dSDimitry Andric // Do the shift. The registers are modified in-place. 2200bdd1243dSDimitry Andric insertMultibyteShift(MI, BB, Registers, Opc, ShiftAmt); 2201bdd1243dSDimitry Andric 2202bdd1243dSDimitry Andric // Combine the 8-bit registers into 16-bit register pairs. 2203bdd1243dSDimitry Andric // This done either from LSB to MSB or from MSB to LSB, depending on the 2204bdd1243dSDimitry Andric // shift. It's an optimization so that the register allocator will use the 2205bdd1243dSDimitry Andric // fewest movs possible (which order we use isn't a correctness issue, just an 2206bdd1243dSDimitry Andric // optimization issue). 2207bdd1243dSDimitry Andric // - lsl prefers starting from the most significant byte (2nd case). 2208bdd1243dSDimitry Andric // - lshr prefers starting from the least significant byte (1st case). 2209bdd1243dSDimitry Andric // - for ashr it depends on the number of shifted bytes. 2210bdd1243dSDimitry Andric // Some shift operations still don't get the most optimal mov sequences even 2211bdd1243dSDimitry Andric // with this distinction. TODO: figure out why and try to fix it (but we're 2212bdd1243dSDimitry Andric // already equal to or faster than avr-gcc in all cases except ashr 8). 2213bdd1243dSDimitry Andric if (Opc != ISD::SHL && 2214bdd1243dSDimitry Andric (Opc != ISD::SRA || (ShiftAmt < 16 || ShiftAmt >= 22))) { 2215bdd1243dSDimitry Andric // Use the resulting registers starting with the least significant byte. 2216bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::REG_SEQUENCE), MI.getOperand(0).getReg()) 2217bdd1243dSDimitry Andric .addReg(Registers[3].first, 0, Registers[3].second) 2218bdd1243dSDimitry Andric .addImm(AVR::sub_lo) 2219bdd1243dSDimitry Andric .addReg(Registers[2].first, 0, Registers[2].second) 2220bdd1243dSDimitry Andric .addImm(AVR::sub_hi); 2221bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::REG_SEQUENCE), MI.getOperand(1).getReg()) 2222bdd1243dSDimitry Andric .addReg(Registers[1].first, 0, Registers[1].second) 2223bdd1243dSDimitry Andric .addImm(AVR::sub_lo) 2224bdd1243dSDimitry Andric .addReg(Registers[0].first, 0, Registers[0].second) 2225bdd1243dSDimitry Andric .addImm(AVR::sub_hi); 2226bdd1243dSDimitry Andric } else { 2227bdd1243dSDimitry Andric // Use the resulting registers starting with the most significant byte. 2228bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::REG_SEQUENCE), MI.getOperand(1).getReg()) 2229bdd1243dSDimitry Andric .addReg(Registers[0].first, 0, Registers[0].second) 2230bdd1243dSDimitry Andric .addImm(AVR::sub_hi) 2231bdd1243dSDimitry Andric .addReg(Registers[1].first, 0, Registers[1].second) 2232bdd1243dSDimitry Andric .addImm(AVR::sub_lo); 2233bdd1243dSDimitry Andric BuildMI(*BB, MI, dl, TII.get(AVR::REG_SEQUENCE), MI.getOperand(0).getReg()) 2234bdd1243dSDimitry Andric .addReg(Registers[2].first, 0, Registers[2].second) 2235bdd1243dSDimitry Andric .addImm(AVR::sub_hi) 2236bdd1243dSDimitry Andric .addReg(Registers[3].first, 0, Registers[3].second) 2237bdd1243dSDimitry Andric .addImm(AVR::sub_lo); 2238bdd1243dSDimitry Andric } 2239bdd1243dSDimitry Andric 2240bdd1243dSDimitry Andric // Remove the pseudo instruction. 2241bdd1243dSDimitry Andric MI.eraseFromParent(); 2242bdd1243dSDimitry Andric return BB; 2243bdd1243dSDimitry Andric } 2244bdd1243dSDimitry Andric 22450b57cec5SDimitry Andric static bool isCopyMulResult(MachineBasicBlock::iterator const &I) { 22460b57cec5SDimitry Andric if (I->getOpcode() == AVR::COPY) { 22478bcb0991SDimitry Andric Register SrcReg = I->getOperand(1).getReg(); 22480b57cec5SDimitry Andric return (SrcReg == AVR::R0 || SrcReg == AVR::R1); 22490b57cec5SDimitry Andric } 22500b57cec5SDimitry Andric 22510b57cec5SDimitry Andric return false; 22520b57cec5SDimitry Andric } 22530b57cec5SDimitry Andric 22540b57cec5SDimitry Andric // The mul instructions wreak havock on our zero_reg R1. We need to clear it 22550b57cec5SDimitry Andric // after the result has been evacuated. This is probably not the best way to do 22560b57cec5SDimitry Andric // it, but it works for now. 22570b57cec5SDimitry Andric MachineBasicBlock *AVRTargetLowering::insertMul(MachineInstr &MI, 22580b57cec5SDimitry Andric MachineBasicBlock *BB) const { 22590b57cec5SDimitry Andric const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 22600b57cec5SDimitry Andric MachineBasicBlock::iterator I(MI); 22610b57cec5SDimitry Andric ++I; // in any case insert *after* the mul instruction 22620b57cec5SDimitry Andric if (isCopyMulResult(I)) 22630b57cec5SDimitry Andric ++I; 22640b57cec5SDimitry Andric if (isCopyMulResult(I)) 22650b57cec5SDimitry Andric ++I; 22660b57cec5SDimitry Andric BuildMI(*BB, I, MI.getDebugLoc(), TII.get(AVR::EORRdRr), AVR::R1) 22670b57cec5SDimitry Andric .addReg(AVR::R1) 22680b57cec5SDimitry Andric .addReg(AVR::R1); 22690b57cec5SDimitry Andric return BB; 22700b57cec5SDimitry Andric } 22710b57cec5SDimitry Andric 2272bdd1243dSDimitry Andric // Insert a read from the zero register. 227304eeddc0SDimitry Andric MachineBasicBlock * 2274bdd1243dSDimitry Andric AVRTargetLowering::insertCopyZero(MachineInstr &MI, 2275bdd1243dSDimitry Andric MachineBasicBlock *BB) const { 227604eeddc0SDimitry Andric const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 227704eeddc0SDimitry Andric MachineBasicBlock::iterator I(MI); 227804eeddc0SDimitry Andric BuildMI(*BB, I, MI.getDebugLoc(), TII.get(AVR::COPY)) 227904eeddc0SDimitry Andric .add(MI.getOperand(0)) 2280bdd1243dSDimitry Andric .addReg(Subtarget.getZeroRegister()); 228104eeddc0SDimitry Andric MI.eraseFromParent(); 228204eeddc0SDimitry Andric return BB; 228304eeddc0SDimitry Andric } 228404eeddc0SDimitry Andric 228581ad6265SDimitry Andric // Lower atomicrmw operation to disable interrupts, do operation, and restore 228681ad6265SDimitry Andric // interrupts. This works because all AVR microcontrollers are single core. 228781ad6265SDimitry Andric MachineBasicBlock *AVRTargetLowering::insertAtomicArithmeticOp( 228881ad6265SDimitry Andric MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode, int Width) const { 228981ad6265SDimitry Andric MachineRegisterInfo &MRI = BB->getParent()->getRegInfo(); 229081ad6265SDimitry Andric const TargetInstrInfo &TII = *Subtarget.getInstrInfo(); 229181ad6265SDimitry Andric MachineBasicBlock::iterator I(MI); 229281ad6265SDimitry Andric DebugLoc dl = MI.getDebugLoc(); 229381ad6265SDimitry Andric 229481ad6265SDimitry Andric // Example instruction sequence, for an atomic 8-bit add: 229581ad6265SDimitry Andric // ldi r25, 5 229681ad6265SDimitry Andric // in r0, SREG 229781ad6265SDimitry Andric // cli 229881ad6265SDimitry Andric // ld r24, X 229981ad6265SDimitry Andric // add r25, r24 230081ad6265SDimitry Andric // st X, r25 230181ad6265SDimitry Andric // out SREG, r0 230281ad6265SDimitry Andric 230381ad6265SDimitry Andric const TargetRegisterClass *RC = 230481ad6265SDimitry Andric (Width == 8) ? &AVR::GPR8RegClass : &AVR::DREGSRegClass; 230581ad6265SDimitry Andric unsigned LoadOpcode = (Width == 8) ? AVR::LDRdPtr : AVR::LDWRdPtr; 230681ad6265SDimitry Andric unsigned StoreOpcode = (Width == 8) ? AVR::STPtrRr : AVR::STWPtrRr; 230781ad6265SDimitry Andric 230881ad6265SDimitry Andric // Disable interrupts. 2309bdd1243dSDimitry Andric BuildMI(*BB, I, dl, TII.get(AVR::INRdA), Subtarget.getTmpRegister()) 231081ad6265SDimitry Andric .addImm(Subtarget.getIORegSREG()); 231181ad6265SDimitry Andric BuildMI(*BB, I, dl, TII.get(AVR::BCLRs)).addImm(7); 231281ad6265SDimitry Andric 231381ad6265SDimitry Andric // Load the original value. 231481ad6265SDimitry Andric BuildMI(*BB, I, dl, TII.get(LoadOpcode), MI.getOperand(0).getReg()) 231581ad6265SDimitry Andric .add(MI.getOperand(1)); 231681ad6265SDimitry Andric 231781ad6265SDimitry Andric // Do the arithmetic operation. 231881ad6265SDimitry Andric Register Result = MRI.createVirtualRegister(RC); 231981ad6265SDimitry Andric BuildMI(*BB, I, dl, TII.get(Opcode), Result) 232081ad6265SDimitry Andric .addReg(MI.getOperand(0).getReg()) 232181ad6265SDimitry Andric .add(MI.getOperand(2)); 232281ad6265SDimitry Andric 232381ad6265SDimitry Andric // Store the result. 232481ad6265SDimitry Andric BuildMI(*BB, I, dl, TII.get(StoreOpcode)) 232581ad6265SDimitry Andric .add(MI.getOperand(1)) 232681ad6265SDimitry Andric .addReg(Result); 232781ad6265SDimitry Andric 232881ad6265SDimitry Andric // Restore interrupts. 232981ad6265SDimitry Andric BuildMI(*BB, I, dl, TII.get(AVR::OUTARr)) 233081ad6265SDimitry Andric .addImm(Subtarget.getIORegSREG()) 2331bdd1243dSDimitry Andric .addReg(Subtarget.getTmpRegister()); 233281ad6265SDimitry Andric 233381ad6265SDimitry Andric // Remove the pseudo instruction. 233481ad6265SDimitry Andric MI.eraseFromParent(); 233581ad6265SDimitry Andric return BB; 233681ad6265SDimitry Andric } 233781ad6265SDimitry Andric 23380b57cec5SDimitry Andric MachineBasicBlock * 23390b57cec5SDimitry Andric AVRTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, 23400b57cec5SDimitry Andric MachineBasicBlock *MBB) const { 23410b57cec5SDimitry Andric int Opc = MI.getOpcode(); 234206c3fb27SDimitry Andric const AVRSubtarget &STI = MBB->getParent()->getSubtarget<AVRSubtarget>(); 23430b57cec5SDimitry Andric 23440b57cec5SDimitry Andric // Pseudo shift instructions with a non constant shift amount are expanded 23450b57cec5SDimitry Andric // into a loop. 23460b57cec5SDimitry Andric switch (Opc) { 23470b57cec5SDimitry Andric case AVR::Lsl8: 23480b57cec5SDimitry Andric case AVR::Lsl16: 23490b57cec5SDimitry Andric case AVR::Lsr8: 23500b57cec5SDimitry Andric case AVR::Lsr16: 23510b57cec5SDimitry Andric case AVR::Rol8: 23520b57cec5SDimitry Andric case AVR::Rol16: 23530b57cec5SDimitry Andric case AVR::Ror8: 23540b57cec5SDimitry Andric case AVR::Ror16: 23550b57cec5SDimitry Andric case AVR::Asr8: 23560b57cec5SDimitry Andric case AVR::Asr16: 235706c3fb27SDimitry Andric return insertShift(MI, MBB, STI.hasTinyEncoding()); 2358bdd1243dSDimitry Andric case AVR::Lsl32: 2359bdd1243dSDimitry Andric case AVR::Lsr32: 2360bdd1243dSDimitry Andric case AVR::Asr32: 2361bdd1243dSDimitry Andric return insertWideShift(MI, MBB); 23620b57cec5SDimitry Andric case AVR::MULRdRr: 23630b57cec5SDimitry Andric case AVR::MULSRdRr: 23640b57cec5SDimitry Andric return insertMul(MI, MBB); 2365bdd1243dSDimitry Andric case AVR::CopyZero: 2366bdd1243dSDimitry Andric return insertCopyZero(MI, MBB); 236781ad6265SDimitry Andric case AVR::AtomicLoadAdd8: 236881ad6265SDimitry Andric return insertAtomicArithmeticOp(MI, MBB, AVR::ADDRdRr, 8); 236981ad6265SDimitry Andric case AVR::AtomicLoadAdd16: 237081ad6265SDimitry Andric return insertAtomicArithmeticOp(MI, MBB, AVR::ADDWRdRr, 16); 237181ad6265SDimitry Andric case AVR::AtomicLoadSub8: 237281ad6265SDimitry Andric return insertAtomicArithmeticOp(MI, MBB, AVR::SUBRdRr, 8); 237381ad6265SDimitry Andric case AVR::AtomicLoadSub16: 237481ad6265SDimitry Andric return insertAtomicArithmeticOp(MI, MBB, AVR::SUBWRdRr, 16); 237581ad6265SDimitry Andric case AVR::AtomicLoadAnd8: 237681ad6265SDimitry Andric return insertAtomicArithmeticOp(MI, MBB, AVR::ANDRdRr, 8); 237781ad6265SDimitry Andric case AVR::AtomicLoadAnd16: 237881ad6265SDimitry Andric return insertAtomicArithmeticOp(MI, MBB, AVR::ANDWRdRr, 16); 237981ad6265SDimitry Andric case AVR::AtomicLoadOr8: 238081ad6265SDimitry Andric return insertAtomicArithmeticOp(MI, MBB, AVR::ORRdRr, 8); 238181ad6265SDimitry Andric case AVR::AtomicLoadOr16: 238281ad6265SDimitry Andric return insertAtomicArithmeticOp(MI, MBB, AVR::ORWRdRr, 16); 238381ad6265SDimitry Andric case AVR::AtomicLoadXor8: 238481ad6265SDimitry Andric return insertAtomicArithmeticOp(MI, MBB, AVR::EORRdRr, 8); 238581ad6265SDimitry Andric case AVR::AtomicLoadXor16: 238681ad6265SDimitry Andric return insertAtomicArithmeticOp(MI, MBB, AVR::EORWRdRr, 16); 23870b57cec5SDimitry Andric } 23880b57cec5SDimitry Andric 23890b57cec5SDimitry Andric assert((Opc == AVR::Select16 || Opc == AVR::Select8) && 23900b57cec5SDimitry Andric "Unexpected instr type to insert"); 23910b57cec5SDimitry Andric 23920b57cec5SDimitry Andric const AVRInstrInfo &TII = (const AVRInstrInfo &)*MI.getParent() 23930b57cec5SDimitry Andric ->getParent() 23940b57cec5SDimitry Andric ->getSubtarget() 23950b57cec5SDimitry Andric .getInstrInfo(); 23960b57cec5SDimitry Andric DebugLoc dl = MI.getDebugLoc(); 23970b57cec5SDimitry Andric 23980b57cec5SDimitry Andric // To "insert" a SELECT instruction, we insert the diamond 23990b57cec5SDimitry Andric // control-flow pattern. The incoming instruction knows the 24000b57cec5SDimitry Andric // destination vreg to set, the condition code register to branch 24010b57cec5SDimitry Andric // on, the true/false values to select between, and a branch opcode 24020b57cec5SDimitry Andric // to use. 24030b57cec5SDimitry Andric 24040b57cec5SDimitry Andric MachineFunction *MF = MBB->getParent(); 24050b57cec5SDimitry Andric const BasicBlock *LLVM_BB = MBB->getBasicBlock(); 24060b57cec5SDimitry Andric MachineBasicBlock *FallThrough = MBB->getFallThrough(); 24070b57cec5SDimitry Andric 24080b57cec5SDimitry Andric // If the current basic block falls through to another basic block, 24090b57cec5SDimitry Andric // we must insert an unconditional branch to the fallthrough destination 24100b57cec5SDimitry Andric // if we are to insert basic blocks at the prior fallthrough point. 24110b57cec5SDimitry Andric if (FallThrough != nullptr) { 24120b57cec5SDimitry Andric BuildMI(MBB, dl, TII.get(AVR::RJMPk)).addMBB(FallThrough); 24130b57cec5SDimitry Andric } 24140b57cec5SDimitry Andric 24150b57cec5SDimitry Andric MachineBasicBlock *trueMBB = MF->CreateMachineBasicBlock(LLVM_BB); 24160b57cec5SDimitry Andric MachineBasicBlock *falseMBB = MF->CreateMachineBasicBlock(LLVM_BB); 24170b57cec5SDimitry Andric 24180b57cec5SDimitry Andric MachineFunction::iterator I; 2419349cc55cSDimitry Andric for (I = MF->begin(); I != MF->end() && &(*I) != MBB; ++I) 2420349cc55cSDimitry Andric ; 2421349cc55cSDimitry Andric if (I != MF->end()) 2422349cc55cSDimitry Andric ++I; 24230b57cec5SDimitry Andric MF->insert(I, trueMBB); 24240b57cec5SDimitry Andric MF->insert(I, falseMBB); 24250b57cec5SDimitry Andric 24265f757f3fSDimitry Andric // Set the call frame size on entry to the new basic blocks. 24275f757f3fSDimitry Andric unsigned CallFrameSize = TII.getCallFrameSizeAt(MI); 24285f757f3fSDimitry Andric trueMBB->setCallFrameSize(CallFrameSize); 24295f757f3fSDimitry Andric falseMBB->setCallFrameSize(CallFrameSize); 24305f757f3fSDimitry Andric 24310b57cec5SDimitry Andric // Transfer remaining instructions and all successors of the current 24320b57cec5SDimitry Andric // block to the block which will contain the Phi node for the 24330b57cec5SDimitry Andric // select. 24340b57cec5SDimitry Andric trueMBB->splice(trueMBB->begin(), MBB, 24350b57cec5SDimitry Andric std::next(MachineBasicBlock::iterator(MI)), MBB->end()); 24360b57cec5SDimitry Andric trueMBB->transferSuccessorsAndUpdatePHIs(MBB); 24370b57cec5SDimitry Andric 24380b57cec5SDimitry Andric AVRCC::CondCodes CC = (AVRCC::CondCodes)MI.getOperand(3).getImm(); 24390b57cec5SDimitry Andric BuildMI(MBB, dl, TII.getBrCond(CC)).addMBB(trueMBB); 24400b57cec5SDimitry Andric BuildMI(MBB, dl, TII.get(AVR::RJMPk)).addMBB(falseMBB); 24410b57cec5SDimitry Andric MBB->addSuccessor(falseMBB); 24420b57cec5SDimitry Andric MBB->addSuccessor(trueMBB); 24430b57cec5SDimitry Andric 24440b57cec5SDimitry Andric // Unconditionally flow back to the true block 24450b57cec5SDimitry Andric BuildMI(falseMBB, dl, TII.get(AVR::RJMPk)).addMBB(trueMBB); 24460b57cec5SDimitry Andric falseMBB->addSuccessor(trueMBB); 24470b57cec5SDimitry Andric 24480b57cec5SDimitry Andric // Set up the Phi node to determine where we came from 2449349cc55cSDimitry Andric BuildMI(*trueMBB, trueMBB->begin(), dl, TII.get(AVR::PHI), 2450349cc55cSDimitry Andric MI.getOperand(0).getReg()) 24510b57cec5SDimitry Andric .addReg(MI.getOperand(1).getReg()) 24520b57cec5SDimitry Andric .addMBB(MBB) 24530b57cec5SDimitry Andric .addReg(MI.getOperand(2).getReg()) 24540b57cec5SDimitry Andric .addMBB(falseMBB); 24550b57cec5SDimitry Andric 24560b57cec5SDimitry Andric MI.eraseFromParent(); // The pseudo instruction is gone now. 24570b57cec5SDimitry Andric return trueMBB; 24580b57cec5SDimitry Andric } 24590b57cec5SDimitry Andric 24600b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 24610b57cec5SDimitry Andric // Inline Asm Support 24620b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 24630b57cec5SDimitry Andric 24640b57cec5SDimitry Andric AVRTargetLowering::ConstraintType 24650b57cec5SDimitry Andric AVRTargetLowering::getConstraintType(StringRef Constraint) const { 24660b57cec5SDimitry Andric if (Constraint.size() == 1) { 24670b57cec5SDimitry Andric // See http://www.nongnu.org/avr-libc/user-manual/inline_asm.html 24680b57cec5SDimitry Andric switch (Constraint[0]) { 24690b57cec5SDimitry Andric default: 24700b57cec5SDimitry Andric break; 24710b57cec5SDimitry Andric case 'a': // Simple upper registers 24720b57cec5SDimitry Andric case 'b': // Base pointer registers pairs 24730b57cec5SDimitry Andric case 'd': // Upper register 24740b57cec5SDimitry Andric case 'l': // Lower registers 24750b57cec5SDimitry Andric case 'e': // Pointer register pairs 24760b57cec5SDimitry Andric case 'q': // Stack pointer register 24770b57cec5SDimitry Andric case 'r': // Any register 24780b57cec5SDimitry Andric case 'w': // Special upper register pairs 24790b57cec5SDimitry Andric return C_RegisterClass; 24800b57cec5SDimitry Andric case 't': // Temporary register 2481349cc55cSDimitry Andric case 'x': 2482349cc55cSDimitry Andric case 'X': // Pointer register pair X 2483349cc55cSDimitry Andric case 'y': 2484349cc55cSDimitry Andric case 'Y': // Pointer register pair Y 2485349cc55cSDimitry Andric case 'z': 2486349cc55cSDimitry Andric case 'Z': // Pointer register pair Z 24870b57cec5SDimitry Andric return C_Register; 24880b57cec5SDimitry Andric case 'Q': // A memory address based on Y or Z pointer with displacement. 24890b57cec5SDimitry Andric return C_Memory; 24900b57cec5SDimitry Andric case 'G': // Floating point constant 24910b57cec5SDimitry Andric case 'I': // 6-bit positive integer constant 24920b57cec5SDimitry Andric case 'J': // 6-bit negative integer constant 24930b57cec5SDimitry Andric case 'K': // Integer constant (Range: 2) 24940b57cec5SDimitry Andric case 'L': // Integer constant (Range: 0) 24950b57cec5SDimitry Andric case 'M': // 8-bit integer constant 24960b57cec5SDimitry Andric case 'N': // Integer constant (Range: -1) 24970b57cec5SDimitry Andric case 'O': // Integer constant (Range: 8, 16, 24) 24980b57cec5SDimitry Andric case 'P': // Integer constant (Range: 1) 24990b57cec5SDimitry Andric case 'R': // Integer constant (Range: -6 to 5)x 25000b57cec5SDimitry Andric return C_Immediate; 25010b57cec5SDimitry Andric } 25020b57cec5SDimitry Andric } 25030b57cec5SDimitry Andric 25040b57cec5SDimitry Andric return TargetLowering::getConstraintType(Constraint); 25050b57cec5SDimitry Andric } 25060b57cec5SDimitry Andric 25075f757f3fSDimitry Andric InlineAsm::ConstraintCode 25080b57cec5SDimitry Andric AVRTargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const { 25090b57cec5SDimitry Andric // Not sure if this is actually the right thing to do, but we got to do 25100b57cec5SDimitry Andric // *something* [agnat] 25110b57cec5SDimitry Andric switch (ConstraintCode[0]) { 25120b57cec5SDimitry Andric case 'Q': 25135f757f3fSDimitry Andric return InlineAsm::ConstraintCode::Q; 25140b57cec5SDimitry Andric } 25150b57cec5SDimitry Andric return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); 25160b57cec5SDimitry Andric } 25170b57cec5SDimitry Andric 25180b57cec5SDimitry Andric AVRTargetLowering::ConstraintWeight 25190b57cec5SDimitry Andric AVRTargetLowering::getSingleConstraintMatchWeight( 25200b57cec5SDimitry Andric AsmOperandInfo &info, const char *constraint) const { 25210b57cec5SDimitry Andric ConstraintWeight weight = CW_Invalid; 25220b57cec5SDimitry Andric Value *CallOperandVal = info.CallOperandVal; 25230b57cec5SDimitry Andric 25240b57cec5SDimitry Andric // If we don't have a value, we can't do a match, 25250b57cec5SDimitry Andric // but allow it at the lowest weight. 25260b57cec5SDimitry Andric // (this behaviour has been copied from the ARM backend) 25270b57cec5SDimitry Andric if (!CallOperandVal) { 25280b57cec5SDimitry Andric return CW_Default; 25290b57cec5SDimitry Andric } 25300b57cec5SDimitry Andric 25310b57cec5SDimitry Andric // Look at the constraint type. 25320b57cec5SDimitry Andric switch (*constraint) { 25330b57cec5SDimitry Andric default: 25340b57cec5SDimitry Andric weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); 25350b57cec5SDimitry Andric break; 25360b57cec5SDimitry Andric case 'd': 25370b57cec5SDimitry Andric case 'r': 25380b57cec5SDimitry Andric case 'l': 25390b57cec5SDimitry Andric weight = CW_Register; 25400b57cec5SDimitry Andric break; 25410b57cec5SDimitry Andric case 'a': 25420b57cec5SDimitry Andric case 'b': 25430b57cec5SDimitry Andric case 'e': 25440b57cec5SDimitry Andric case 'q': 25450b57cec5SDimitry Andric case 't': 25460b57cec5SDimitry Andric case 'w': 2547349cc55cSDimitry Andric case 'x': 2548349cc55cSDimitry Andric case 'X': 2549349cc55cSDimitry Andric case 'y': 2550349cc55cSDimitry Andric case 'Y': 2551349cc55cSDimitry Andric case 'z': 2552349cc55cSDimitry Andric case 'Z': 25530b57cec5SDimitry Andric weight = CW_SpecificReg; 25540b57cec5SDimitry Andric break; 25550b57cec5SDimitry Andric case 'G': 25560b57cec5SDimitry Andric if (const ConstantFP *C = dyn_cast<ConstantFP>(CallOperandVal)) { 25570b57cec5SDimitry Andric if (C->isZero()) { 25580b57cec5SDimitry Andric weight = CW_Constant; 25590b57cec5SDimitry Andric } 25600b57cec5SDimitry Andric } 25610b57cec5SDimitry Andric break; 25620b57cec5SDimitry Andric case 'I': 25630b57cec5SDimitry Andric if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) { 25640b57cec5SDimitry Andric if (isUInt<6>(C->getZExtValue())) { 25650b57cec5SDimitry Andric weight = CW_Constant; 25660b57cec5SDimitry Andric } 25670b57cec5SDimitry Andric } 25680b57cec5SDimitry Andric break; 25690b57cec5SDimitry Andric case 'J': 25700b57cec5SDimitry Andric if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) { 25710b57cec5SDimitry Andric if ((C->getSExtValue() >= -63) && (C->getSExtValue() <= 0)) { 25720b57cec5SDimitry Andric weight = CW_Constant; 25730b57cec5SDimitry Andric } 25740b57cec5SDimitry Andric } 25750b57cec5SDimitry Andric break; 25760b57cec5SDimitry Andric case 'K': 25770b57cec5SDimitry Andric if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) { 25780b57cec5SDimitry Andric if (C->getZExtValue() == 2) { 25790b57cec5SDimitry Andric weight = CW_Constant; 25800b57cec5SDimitry Andric } 25810b57cec5SDimitry Andric } 25820b57cec5SDimitry Andric break; 25830b57cec5SDimitry Andric case 'L': 25840b57cec5SDimitry Andric if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) { 25850b57cec5SDimitry Andric if (C->getZExtValue() == 0) { 25860b57cec5SDimitry Andric weight = CW_Constant; 25870b57cec5SDimitry Andric } 25880b57cec5SDimitry Andric } 25890b57cec5SDimitry Andric break; 25900b57cec5SDimitry Andric case 'M': 25910b57cec5SDimitry Andric if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) { 25920b57cec5SDimitry Andric if (isUInt<8>(C->getZExtValue())) { 25930b57cec5SDimitry Andric weight = CW_Constant; 25940b57cec5SDimitry Andric } 25950b57cec5SDimitry Andric } 25960b57cec5SDimitry Andric break; 25970b57cec5SDimitry Andric case 'N': 25980b57cec5SDimitry Andric if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) { 25990b57cec5SDimitry Andric if (C->getSExtValue() == -1) { 26000b57cec5SDimitry Andric weight = CW_Constant; 26010b57cec5SDimitry Andric } 26020b57cec5SDimitry Andric } 26030b57cec5SDimitry Andric break; 26040b57cec5SDimitry Andric case 'O': 26050b57cec5SDimitry Andric if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) { 26060b57cec5SDimitry Andric if ((C->getZExtValue() == 8) || (C->getZExtValue() == 16) || 26070b57cec5SDimitry Andric (C->getZExtValue() == 24)) { 26080b57cec5SDimitry Andric weight = CW_Constant; 26090b57cec5SDimitry Andric } 26100b57cec5SDimitry Andric } 26110b57cec5SDimitry Andric break; 26120b57cec5SDimitry Andric case 'P': 26130b57cec5SDimitry Andric if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) { 26140b57cec5SDimitry Andric if (C->getZExtValue() == 1) { 26150b57cec5SDimitry Andric weight = CW_Constant; 26160b57cec5SDimitry Andric } 26170b57cec5SDimitry Andric } 26180b57cec5SDimitry Andric break; 26190b57cec5SDimitry Andric case 'R': 26200b57cec5SDimitry Andric if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) { 26210b57cec5SDimitry Andric if ((C->getSExtValue() >= -6) && (C->getSExtValue() <= 5)) { 26220b57cec5SDimitry Andric weight = CW_Constant; 26230b57cec5SDimitry Andric } 26240b57cec5SDimitry Andric } 26250b57cec5SDimitry Andric break; 26260b57cec5SDimitry Andric case 'Q': 26270b57cec5SDimitry Andric weight = CW_Memory; 26280b57cec5SDimitry Andric break; 26290b57cec5SDimitry Andric } 26300b57cec5SDimitry Andric 26310b57cec5SDimitry Andric return weight; 26320b57cec5SDimitry Andric } 26330b57cec5SDimitry Andric 26340b57cec5SDimitry Andric std::pair<unsigned, const TargetRegisterClass *> 26350b57cec5SDimitry Andric AVRTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 26360b57cec5SDimitry Andric StringRef Constraint, 26370b57cec5SDimitry Andric MVT VT) const { 26380b57cec5SDimitry Andric if (Constraint.size() == 1) { 26390b57cec5SDimitry Andric switch (Constraint[0]) { 26400b57cec5SDimitry Andric case 'a': // Simple upper registers r16..r23. 2641fe6060f1SDimitry Andric if (VT == MVT::i8) 26420b57cec5SDimitry Andric return std::make_pair(0U, &AVR::LD8loRegClass); 2643fe6060f1SDimitry Andric else if (VT == MVT::i16) 2644fe6060f1SDimitry Andric return std::make_pair(0U, &AVR::DREGSLD8loRegClass); 2645fe6060f1SDimitry Andric break; 26460b57cec5SDimitry Andric case 'b': // Base pointer registers: y, z. 2647fe6060f1SDimitry Andric if (VT == MVT::i8 || VT == MVT::i16) 26480b57cec5SDimitry Andric return std::make_pair(0U, &AVR::PTRDISPREGSRegClass); 2649fe6060f1SDimitry Andric break; 26500b57cec5SDimitry Andric case 'd': // Upper registers r16..r31. 2651fe6060f1SDimitry Andric if (VT == MVT::i8) 26520b57cec5SDimitry Andric return std::make_pair(0U, &AVR::LD8RegClass); 2653fe6060f1SDimitry Andric else if (VT == MVT::i16) 2654fe6060f1SDimitry Andric return std::make_pair(0U, &AVR::DLDREGSRegClass); 2655fe6060f1SDimitry Andric break; 26560b57cec5SDimitry Andric case 'l': // Lower registers r0..r15. 2657fe6060f1SDimitry Andric if (VT == MVT::i8) 26580b57cec5SDimitry Andric return std::make_pair(0U, &AVR::GPR8loRegClass); 2659fe6060f1SDimitry Andric else if (VT == MVT::i16) 2660fe6060f1SDimitry Andric return std::make_pair(0U, &AVR::DREGSloRegClass); 2661fe6060f1SDimitry Andric break; 26620b57cec5SDimitry Andric case 'e': // Pointer register pairs: x, y, z. 2663fe6060f1SDimitry Andric if (VT == MVT::i8 || VT == MVT::i16) 26640b57cec5SDimitry Andric return std::make_pair(0U, &AVR::PTRREGSRegClass); 2665fe6060f1SDimitry Andric break; 26660b57cec5SDimitry Andric case 'q': // Stack pointer register: SPH:SPL. 26670b57cec5SDimitry Andric return std::make_pair(0U, &AVR::GPRSPRegClass); 26680b57cec5SDimitry Andric case 'r': // Any register: r0..r31. 26690b57cec5SDimitry Andric if (VT == MVT::i8) 26700b57cec5SDimitry Andric return std::make_pair(0U, &AVR::GPR8RegClass); 2671fe6060f1SDimitry Andric else if (VT == MVT::i16) 26720b57cec5SDimitry Andric return std::make_pair(0U, &AVR::DREGSRegClass); 2673fe6060f1SDimitry Andric break; 26740b57cec5SDimitry Andric case 't': // Temporary register: r0. 2675fe6060f1SDimitry Andric if (VT == MVT::i8) 2676bdd1243dSDimitry Andric return std::make_pair(unsigned(Subtarget.getTmpRegister()), 2677bdd1243dSDimitry Andric &AVR::GPR8RegClass); 2678fe6060f1SDimitry Andric break; 26790b57cec5SDimitry Andric case 'w': // Special upper register pairs: r24, r26, r28, r30. 2680fe6060f1SDimitry Andric if (VT == MVT::i8 || VT == MVT::i16) 26810b57cec5SDimitry Andric return std::make_pair(0U, &AVR::IWREGSRegClass); 2682fe6060f1SDimitry Andric break; 26830b57cec5SDimitry Andric case 'x': // Pointer register pair X: r27:r26. 26840b57cec5SDimitry Andric case 'X': 2685fe6060f1SDimitry Andric if (VT == MVT::i8 || VT == MVT::i16) 26860b57cec5SDimitry Andric return std::make_pair(unsigned(AVR::R27R26), &AVR::PTRREGSRegClass); 2687fe6060f1SDimitry Andric break; 26880b57cec5SDimitry Andric case 'y': // Pointer register pair Y: r29:r28. 26890b57cec5SDimitry Andric case 'Y': 2690fe6060f1SDimitry Andric if (VT == MVT::i8 || VT == MVT::i16) 26910b57cec5SDimitry Andric return std::make_pair(unsigned(AVR::R29R28), &AVR::PTRREGSRegClass); 2692fe6060f1SDimitry Andric break; 26930b57cec5SDimitry Andric case 'z': // Pointer register pair Z: r31:r30. 26940b57cec5SDimitry Andric case 'Z': 2695fe6060f1SDimitry Andric if (VT == MVT::i8 || VT == MVT::i16) 26960b57cec5SDimitry Andric return std::make_pair(unsigned(AVR::R31R30), &AVR::PTRREGSRegClass); 2697fe6060f1SDimitry Andric break; 26980b57cec5SDimitry Andric default: 26990b57cec5SDimitry Andric break; 27000b57cec5SDimitry Andric } 27010b57cec5SDimitry Andric } 27020b57cec5SDimitry Andric 27030b57cec5SDimitry Andric return TargetLowering::getRegForInlineAsmConstraint( 27040b57cec5SDimitry Andric Subtarget.getRegisterInfo(), Constraint, VT); 27050b57cec5SDimitry Andric } 27060b57cec5SDimitry Andric 27070b57cec5SDimitry Andric void AVRTargetLowering::LowerAsmOperandForConstraint(SDValue Op, 27085f757f3fSDimitry Andric StringRef Constraint, 27090b57cec5SDimitry Andric std::vector<SDValue> &Ops, 27100b57cec5SDimitry Andric SelectionDAG &DAG) const { 271104eeddc0SDimitry Andric SDValue Result; 27120b57cec5SDimitry Andric SDLoc DL(Op); 27130b57cec5SDimitry Andric EVT Ty = Op.getValueType(); 27140b57cec5SDimitry Andric 27150b57cec5SDimitry Andric // Currently only support length 1 constraints. 27165f757f3fSDimitry Andric if (Constraint.size() != 1) { 27170b57cec5SDimitry Andric return; 27180b57cec5SDimitry Andric } 27190b57cec5SDimitry Andric 27200b57cec5SDimitry Andric char ConstraintLetter = Constraint[0]; 27210b57cec5SDimitry Andric switch (ConstraintLetter) { 27220b57cec5SDimitry Andric default: 27230b57cec5SDimitry Andric break; 27240b57cec5SDimitry Andric // Deal with integers first: 27250b57cec5SDimitry Andric case 'I': 27260b57cec5SDimitry Andric case 'J': 27270b57cec5SDimitry Andric case 'K': 27280b57cec5SDimitry Andric case 'L': 27290b57cec5SDimitry Andric case 'M': 27300b57cec5SDimitry Andric case 'N': 27310b57cec5SDimitry Andric case 'O': 27320b57cec5SDimitry Andric case 'P': 27330b57cec5SDimitry Andric case 'R': { 27340b57cec5SDimitry Andric const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op); 27350b57cec5SDimitry Andric if (!C) { 27360b57cec5SDimitry Andric return; 27370b57cec5SDimitry Andric } 27380b57cec5SDimitry Andric 27390b57cec5SDimitry Andric int64_t CVal64 = C->getSExtValue(); 27400b57cec5SDimitry Andric uint64_t CUVal64 = C->getZExtValue(); 27410b57cec5SDimitry Andric switch (ConstraintLetter) { 27420b57cec5SDimitry Andric case 'I': // 0..63 27430b57cec5SDimitry Andric if (!isUInt<6>(CUVal64)) 27440b57cec5SDimitry Andric return; 27450b57cec5SDimitry Andric Result = DAG.getTargetConstant(CUVal64, DL, Ty); 27460b57cec5SDimitry Andric break; 27470b57cec5SDimitry Andric case 'J': // -63..0 27480b57cec5SDimitry Andric if (CVal64 < -63 || CVal64 > 0) 27490b57cec5SDimitry Andric return; 27500b57cec5SDimitry Andric Result = DAG.getTargetConstant(CVal64, DL, Ty); 27510b57cec5SDimitry Andric break; 27520b57cec5SDimitry Andric case 'K': // 2 27530b57cec5SDimitry Andric if (CUVal64 != 2) 27540b57cec5SDimitry Andric return; 27550b57cec5SDimitry Andric Result = DAG.getTargetConstant(CUVal64, DL, Ty); 27560b57cec5SDimitry Andric break; 27570b57cec5SDimitry Andric case 'L': // 0 27580b57cec5SDimitry Andric if (CUVal64 != 0) 27590b57cec5SDimitry Andric return; 27600b57cec5SDimitry Andric Result = DAG.getTargetConstant(CUVal64, DL, Ty); 27610b57cec5SDimitry Andric break; 27620b57cec5SDimitry Andric case 'M': // 0..255 27630b57cec5SDimitry Andric if (!isUInt<8>(CUVal64)) 27640b57cec5SDimitry Andric return; 27650b57cec5SDimitry Andric // i8 type may be printed as a negative number, 27660b57cec5SDimitry Andric // e.g. 254 would be printed as -2, 27670b57cec5SDimitry Andric // so we force it to i16 at least. 27680b57cec5SDimitry Andric if (Ty.getSimpleVT() == MVT::i8) { 27690b57cec5SDimitry Andric Ty = MVT::i16; 27700b57cec5SDimitry Andric } 27710b57cec5SDimitry Andric Result = DAG.getTargetConstant(CUVal64, DL, Ty); 27720b57cec5SDimitry Andric break; 27730b57cec5SDimitry Andric case 'N': // -1 27740b57cec5SDimitry Andric if (CVal64 != -1) 27750b57cec5SDimitry Andric return; 27760b57cec5SDimitry Andric Result = DAG.getTargetConstant(CVal64, DL, Ty); 27770b57cec5SDimitry Andric break; 27780b57cec5SDimitry Andric case 'O': // 8, 16, 24 27790b57cec5SDimitry Andric if (CUVal64 != 8 && CUVal64 != 16 && CUVal64 != 24) 27800b57cec5SDimitry Andric return; 27810b57cec5SDimitry Andric Result = DAG.getTargetConstant(CUVal64, DL, Ty); 27820b57cec5SDimitry Andric break; 27830b57cec5SDimitry Andric case 'P': // 1 27840b57cec5SDimitry Andric if (CUVal64 != 1) 27850b57cec5SDimitry Andric return; 27860b57cec5SDimitry Andric Result = DAG.getTargetConstant(CUVal64, DL, Ty); 27870b57cec5SDimitry Andric break; 27880b57cec5SDimitry Andric case 'R': // -6..5 27890b57cec5SDimitry Andric if (CVal64 < -6 || CVal64 > 5) 27900b57cec5SDimitry Andric return; 27910b57cec5SDimitry Andric Result = DAG.getTargetConstant(CVal64, DL, Ty); 27920b57cec5SDimitry Andric break; 27930b57cec5SDimitry Andric } 27940b57cec5SDimitry Andric 27950b57cec5SDimitry Andric break; 27960b57cec5SDimitry Andric } 27970b57cec5SDimitry Andric case 'G': 27980b57cec5SDimitry Andric const ConstantFPSDNode *FC = dyn_cast<ConstantFPSDNode>(Op); 27990b57cec5SDimitry Andric if (!FC || !FC->isZero()) 28000b57cec5SDimitry Andric return; 28010b57cec5SDimitry Andric // Soften float to i8 0 28020b57cec5SDimitry Andric Result = DAG.getTargetConstant(0, DL, MVT::i8); 28030b57cec5SDimitry Andric break; 28040b57cec5SDimitry Andric } 28050b57cec5SDimitry Andric 28060b57cec5SDimitry Andric if (Result.getNode()) { 28070b57cec5SDimitry Andric Ops.push_back(Result); 28080b57cec5SDimitry Andric return; 28090b57cec5SDimitry Andric } 28100b57cec5SDimitry Andric 28110b57cec5SDimitry Andric return TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); 28120b57cec5SDimitry Andric } 28130b57cec5SDimitry Andric 2814480093f4SDimitry Andric Register AVRTargetLowering::getRegisterByName(const char *RegName, LLT VT, 28158bcb0991SDimitry Andric const MachineFunction &MF) const { 28168bcb0991SDimitry Andric Register Reg; 28170b57cec5SDimitry Andric 2818480093f4SDimitry Andric if (VT == LLT::scalar(8)) { 28190b57cec5SDimitry Andric Reg = StringSwitch<unsigned>(RegName) 2820fe6060f1SDimitry Andric .Case("r0", AVR::R0) 2821fe6060f1SDimitry Andric .Case("r1", AVR::R1) 28220b57cec5SDimitry Andric .Default(0); 28230b57cec5SDimitry Andric } else { 28240b57cec5SDimitry Andric Reg = StringSwitch<unsigned>(RegName) 2825fe6060f1SDimitry Andric .Case("r0", AVR::R1R0) 2826fe6060f1SDimitry Andric .Case("sp", AVR::SP) 28270b57cec5SDimitry Andric .Default(0); 28280b57cec5SDimitry Andric } 28290b57cec5SDimitry Andric 28300b57cec5SDimitry Andric if (Reg) 28310b57cec5SDimitry Andric return Reg; 28320b57cec5SDimitry Andric 2833fe6060f1SDimitry Andric report_fatal_error( 2834fe6060f1SDimitry Andric Twine("Invalid register name \"" + StringRef(RegName) + "\".")); 28350b57cec5SDimitry Andric } 28360b57cec5SDimitry Andric 28370b57cec5SDimitry Andric } // end of namespace llvm 2838