diff options
Diffstat (limited to 'lib/Target/MSP430')
-rw-r--r-- | lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp | 111 | ||||
-rw-r--r-- | lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp | 8 | ||||
-rw-r--r-- | lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp | 14 | ||||
-rw-r--r-- | lib/Target/MSP430/AsmPrinter/Makefile | 1 | ||||
-rw-r--r-- | lib/Target/MSP430/CMakeLists.txt | 3 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430.h | 2 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430.td | 10 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430BranchSelector.cpp | 179 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430ISelLowering.cpp | 67 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430ISelLowering.h | 17 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430InstrFormats.td | 166 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430InstrInfo.cpp | 42 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430InstrInfo.h | 18 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430InstrInfo.td | 1340 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430TargetMachine.cpp | 6 | ||||
-rw-r--r-- | lib/Target/MSP430/MSP430TargetMachine.h | 1 | ||||
-rw-r--r-- | lib/Target/MSP430/Makefile | 2 | ||||
-rw-r--r-- | lib/Target/MSP430/TargetInfo/Makefile | 1 |
18 files changed, 1279 insertions, 709 deletions
diff --git a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp index 145359f..6033197 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp @@ -38,9 +38,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Mangler.h" #include "llvm/Support/ErrorHandling.h" - using namespace llvm; STATISTIC(EmittedInsts, "Number of machine instrs printed"); @@ -80,7 +78,6 @@ namespace { const char *ExtraCode); void printInstructionThroughMCStreamer(const MachineInstr *MI); - void PrintGlobalVariable(const GlobalVariable* GVar); void emitFunctionHeader(const MachineFunction &MF); bool runOnMachineFunction(MachineFunction &F); @@ -91,89 +88,6 @@ namespace { }; } // end of anonymous namespace -void MSP430AsmPrinter::PrintGlobalVariable(const GlobalVariable* GVar) { - if (!GVar->hasInitializer()) - return; // External global require no code - - // Check to see if this is a special global used by LLVM, if so, emit it. - if (EmitSpecialLLVMGlobal(GVar)) - return; - - const TargetData *TD = TM.getTargetData(); - - std::string name = Mang->getMangledName(GVar); - Constant *C = GVar->getInitializer(); - unsigned Size = TD->getTypeAllocSize(C->getType()); - unsigned Align = TD->getPreferredAlignmentLog(GVar); - - printVisibility(name, GVar->getVisibility()); - - O << "\t.type\t" << name << ",@object\n"; - - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GVar, Mang, - TM)); - - if (C->isNullValue() && !GVar->hasSection() && - !GVar->isThreadLocal() && - (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) { - - if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. - - if (GVar->hasLocalLinkage()) - O << "\t.local\t" << name << '\n'; - - O << MAI->getCOMMDirective() << name << ',' << Size; - if (MAI->getCOMMDirectiveTakesAlignment()) - O << ',' << (MAI->getAlignmentIsInBytes() ? (1 << Align) : Align); - - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << '\n'; - return; - } - - switch (GVar->getLinkage()) { - case GlobalValue::CommonLinkage: - case GlobalValue::LinkOnceAnyLinkage: - case GlobalValue::LinkOnceODRLinkage: - case GlobalValue::WeakAnyLinkage: - case GlobalValue::WeakODRLinkage: - O << "\t.weak\t" << name << '\n'; - break; - case GlobalValue::DLLExportLinkage: - case GlobalValue::AppendingLinkage: - // FIXME: appending linkage variables should go into a section of - // their name or something. For now, just emit them as external. - case GlobalValue::ExternalLinkage: - // If external or appending, declare as a global symbol - O << "\t.globl " << name << '\n'; - // FALL THROUGH - case GlobalValue::PrivateLinkage: - case GlobalValue::LinkerPrivateLinkage: - case GlobalValue::InternalLinkage: - break; - default: - assert(0 && "Unknown linkage type!"); - } - - // Use 16-bit alignment by default to simplify bunch of stuff - EmitAlignment(Align, GVar); - O << name << ":"; - if (VerboseAsm) { - O.PadToColumn(MAI->getCommentColumn()); - O << MAI->getCommentString() << ' '; - WriteAsOperand(O, GVar, /*PrintType=*/false, GVar->getParent()); - } - O << '\n'; - - EmitGlobalConstant(C); - - if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << name << ", " << Size << '\n'; -} void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) { const Function *F = MF.getFunction(); @@ -190,20 +104,20 @@ void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) { case Function::LinkerPrivateLinkage: break; case Function::ExternalLinkage: - O << "\t.globl\t" << CurrentFnName << '\n'; + O << "\t.globl\t" << *CurrentFnSym << '\n'; break; case Function::LinkOnceAnyLinkage: case Function::LinkOnceODRLinkage: case Function::WeakAnyLinkage: case Function::WeakODRLinkage: - O << "\t.weak\t" << CurrentFnName << '\n'; + O << "\t.weak\t" << *CurrentFnSym << '\n'; break; } - printVisibility(CurrentFnName, F->getVisibility()); + printVisibility(CurrentFnSym, F->getVisibility()); - O << "\t.type\t" << CurrentFnName << ",@function\n" - << CurrentFnName << ":\n"; + O << "\t.type\t" << *CurrentFnSym << ",@function\n"; + O << *CurrentFnSym << ":\n"; } bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) { @@ -226,7 +140,7 @@ bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) { } if (MAI->hasDotTypeDotSizeDirective()) - O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n'; + O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n'; // We didn't modify anything return false; @@ -259,18 +173,18 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, O << MO.getImm(); return; case MachineOperand::MO_MachineBasicBlock: - GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + O << *GetMBBSymbol(MO.getMBB()->getNumber()); return; case MachineOperand::MO_GlobalAddress: { bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - std::string Name = Mang->getMangledName(MO.getGlobal()); uint64_t Offset = MO.getOffset(); O << (isMemOp ? '&' : '#'); if (Offset) O << '(' << Offset << '+'; - O << Name; + O << *GetGlobalValueSymbol(MO.getGlobal()); + if (Offset) O << ')'; @@ -278,11 +192,8 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, } case MachineOperand::MO_ExternalSymbol: { bool isMemOp = Modifier && !strcmp(Modifier, "mem"); - std::string Name(MAI->getGlobalPrefix()); - Name += MO.getSymbolName(); - - O << (isMemOp ? '&' : '#') << Name; - + O << (isMemOp ? '&' : '#'); + O << MAI->getGlobalPrefix() << MO.getSymbolName(); return; } default: diff --git a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp index 0a403c4..a480307 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp @@ -39,7 +39,7 @@ void MSP430InstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo) { O << Op.getImm(); else { assert(Op.isExpr() && "unknown pcrel immediate operand"); - Op.getExpr()->print(O, &MAI); + O << *Op.getExpr(); } } @@ -53,8 +53,7 @@ void MSP430InstPrinter::printOperand(const MCInst *MI, unsigned OpNo, O << '#' << Op.getImm(); } else { assert(Op.isExpr() && "unknown operand kind in printOperand"); - O << '#'; - Op.getExpr()->print(O, &MAI); + O << '#' << *Op.getExpr(); } } @@ -65,8 +64,7 @@ void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo, // Print displacement first if (Disp.isExpr()) { - O << '&'; - Disp.getExpr()->print(O, &MAI); + O << '&' << *Disp.getExpr(); } else { assert(Disp.isImm() && "Expected immediate in displacement field"); if (!Base.getReg()) diff --git a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp index 595b7e7..e1f80b7 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430MCInstLower.cpp @@ -22,37 +22,27 @@ #include "llvm/MC/MCInst.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Mangler.h" #include "llvm/ADT/SmallString.h" using namespace llvm; MCSymbol *MSP430MCInstLower:: GetGlobalAddressSymbol(const MachineOperand &MO) const { - const GlobalValue *GV = MO.getGlobal(); - - SmallString<128> Name; - Mang.getNameWithPrefix(Name, GV, false); - switch (MO.getTargetFlags()) { default: llvm_unreachable("Unknown target flag on GV operand"); case 0: break; } - return Ctx.GetOrCreateSymbol(Name.str()); + return Printer.GetGlobalValueSymbol(MO.getGlobal()); } MCSymbol *MSP430MCInstLower:: GetExternalSymbolSymbol(const MachineOperand &MO) const { - SmallString<128> Name; - Name += Printer.MAI->getGlobalPrefix(); - Name += MO.getSymbolName(); - switch (MO.getTargetFlags()) { default: assert(0 && "Unknown target flag on GV operand"); case 0: break; } - return Ctx.GetOrCreateSymbol(Name.str()); + return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); } MCSymbol *MSP430MCInstLower:: diff --git a/lib/Target/MSP430/AsmPrinter/Makefile b/lib/Target/MSP430/AsmPrinter/Makefile index 4f340c6..c8a44a1 100644 --- a/lib/Target/MSP430/AsmPrinter/Makefile +++ b/lib/Target/MSP430/AsmPrinter/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMMSP430AsmPrinter +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' MSP430 target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. diff --git a/lib/Target/MSP430/CMakeLists.txt b/lib/Target/MSP430/CMakeLists.txt index 60e0bb1..29abe46 100644 --- a/lib/Target/MSP430/CMakeLists.txt +++ b/lib/Target/MSP430/CMakeLists.txt @@ -11,9 +11,10 @@ tablegen(MSP430GenCallingConv.inc -gen-callingconv) tablegen(MSP430GenSubtarget.inc -gen-subtarget) add_llvm_target(MSP430CodeGen - MSP430InstrInfo.cpp + MSP430BranchSelector.cpp MSP430ISelDAGToDAG.cpp MSP430ISelLowering.cpp + MSP430InstrInfo.cpp MSP430MCAsmInfo.cpp MSP430RegisterInfo.cpp MSP430Subtarget.cpp diff --git a/lib/Target/MSP430/MSP430.h b/lib/Target/MSP430/MSP430.h index 1ff178d..e742118 100644 --- a/lib/Target/MSP430/MSP430.h +++ b/lib/Target/MSP430/MSP430.h @@ -39,6 +39,8 @@ namespace llvm { FunctionPass *createMSP430ISelDag(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel); + FunctionPass *createMSP430BranchSelectionPass(); + extern Target TheMSP430Target; } // end namespace llvm; diff --git a/lib/Target/MSP430/MSP430.td b/lib/Target/MSP430/MSP430.td index 870a3df..fe533d3 100644 --- a/lib/Target/MSP430/MSP430.td +++ b/lib/Target/MSP430/MSP430.td @@ -48,8 +48,14 @@ include "MSP430CallingConv.td" include "MSP430InstrInfo.td" -def MSP430InstrInfo : InstrInfo {} - +def MSP430InstrInfo : InstrInfo { + // Define how we want to layout our TargetSpecific information field... This + // should be kept up-to-date with the fields in the MSP430InstrInfo.h file. + let TSFlagsFields = ["FormBits", + "Size"]; + let TSFlagsShifts = [0, + 2]; +} def MSP430InstPrinter : AsmWriter { string AsmWriterClassName = "InstPrinter"; diff --git a/lib/Target/MSP430/MSP430BranchSelector.cpp b/lib/Target/MSP430/MSP430BranchSelector.cpp new file mode 100644 index 0000000..836e425 --- /dev/null +++ b/lib/Target/MSP430/MSP430BranchSelector.cpp @@ -0,0 +1,179 @@ +//===-- MSP430BranchSelector.cpp - Emit long conditional branches--*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that scans a machine function to determine which +// conditional branches need more than 10 bits of displacement to reach their +// target basic block. It does this in two passes; a calculation of basic block +// positions pass, and a branch psuedo op to machine branch opcode pass. This +// pass should be run last, just before the assembly printer. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "msp430-branch-select" +#include "MSP430.h" +#include "MSP430InstrInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/MathExtras.h" +using namespace llvm; + +STATISTIC(NumExpanded, "Number of branches expanded to long format"); + +namespace { + struct MSP430BSel : public MachineFunctionPass { + static char ID; + MSP430BSel() : MachineFunctionPass(&ID) {} + + /// BlockSizes - The sizes of the basic blocks in the function. + std::vector<unsigned> BlockSizes; + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual const char *getPassName() const { + return "MSP430 Branch Selector"; + } + }; + char MSP430BSel::ID = 0; +} + +/// createMSP430BranchSelectionPass - returns an instance of the Branch +/// Selection Pass +/// +FunctionPass *llvm::createMSP430BranchSelectionPass() { + return new MSP430BSel(); +} + +bool MSP430BSel::runOnMachineFunction(MachineFunction &Fn) { + const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo(); + // Give the blocks of the function a dense, in-order, numbering. + Fn.RenumberBlocks(); + BlockSizes.resize(Fn.getNumBlockIDs()); + + // Measure each MBB and compute a size for the entire function. + unsigned FuncSize = 0; + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; + ++MFI) { + MachineBasicBlock *MBB = MFI; + + unsigned BlockSize = 0; + for (MachineBasicBlock::iterator MBBI = MBB->begin(), EE = MBB->end(); + MBBI != EE; ++MBBI) + BlockSize += TII->GetInstSizeInBytes(MBBI); + + BlockSizes[MBB->getNumber()] = BlockSize; + FuncSize += BlockSize; + } + + // If the entire function is smaller than the displacement of a branch field, + // we know we don't need to shrink any branches in this function. This is a + // common case. + if (FuncSize < (1 << 9)) { + BlockSizes.clear(); + return false; + } + + // For each conditional branch, if the offset to its destination is larger + // than the offset field allows, transform it into a long branch sequence + // like this: + // short branch: + // bCC MBB + // long branch: + // b!CC $PC+6 + // b MBB + // + bool MadeChange = true; + bool EverMadeChange = false; + while (MadeChange) { + // Iteratively expand branches until we reach a fixed point. + MadeChange = false; + + for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; + ++MFI) { + MachineBasicBlock &MBB = *MFI; + unsigned MBBStartOffset = 0; + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); + I != E; ++I) { + if ((I->getOpcode() != MSP430::JCC || I->getOperand(0).isImm()) && + I->getOpcode() != MSP430::JMP) { + MBBStartOffset += TII->GetInstSizeInBytes(I); + continue; + } + + // Determine the offset from the current branch to the destination + // block. + MachineBasicBlock *Dest = I->getOperand(0).getMBB(); + + int BranchSize; + if (Dest->getNumber() <= MBB.getNumber()) { + // If this is a backwards branch, the delta is the offset from the + // start of this block to this branch, plus the sizes of all blocks + // from this block to the dest. + BranchSize = MBBStartOffset; + + for (unsigned i = Dest->getNumber(), e = MBB.getNumber(); i != e; ++i) + BranchSize += BlockSizes[i]; + } else { + // Otherwise, add the size of the blocks between this block and the + // dest to the number of bytes left in this block. + BranchSize = -MBBStartOffset; + + for (unsigned i = MBB.getNumber(), e = Dest->getNumber(); i != e; ++i) + BranchSize += BlockSizes[i]; + } + + // If this branch is in range, ignore it. + if (isInt<10>(BranchSize)) { + MBBStartOffset += 2; + continue; + } + + // Otherwise, we have to expand it to a long branch. + unsigned NewSize; + MachineInstr *OldBranch = I; + DebugLoc dl = OldBranch->getDebugLoc(); + + if (I->getOpcode() == MSP430::JMP) { + NewSize = 4; + } else { + // The BCC operands are: + // 0. MSP430 branch predicate + // 1. Target MBB + SmallVector<MachineOperand, 1> Cond; + Cond.push_back(I->getOperand(1)); + + // Jump over the uncond branch inst (i.e. $+6) on opposite condition. + TII->ReverseBranchCondition(Cond); + BuildMI(MBB, I, dl, TII->get(MSP430::JCC)) + .addImm(4).addOperand(Cond[0]); + + NewSize = 6; + } + // Uncond branch to the real destination. + I = BuildMI(MBB, I, dl, TII->get(MSP430::B)).addMBB(Dest); + + // Remove the old branch from the function. + OldBranch->eraseFromParent(); + + // Remember that this instruction is NewSize bytes, increase the size of the + // block by NewSize-2, remember to iterate. + BlockSizes[MBB.getNumber()] += NewSize-2; + MBBStartOffset += NewSize; + + ++NumExpanded; + MadeChange = true; + } + } + EverMadeChange |= MadeChange; + } + + BlockSizes.clear(); + return true; +} diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index d3dce4b..b794911 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -675,21 +675,53 @@ static SDValue EmitCMP(SDValue &LHS, SDValue &RHS, SDValue &TargetCC, case ISD::SETULE: std::swap(LHS, RHS); // FALLTHROUGH case ISD::SETUGE: + // Turn lhs u>= rhs with lhs constant into rhs u< lhs+1, this allows us to + // fold constant into instruction. + if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { + LHS = RHS; + RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); + TCC = MSP430CC::COND_LO; + break; + } TCC = MSP430CC::COND_HS; // aka COND_C break; case ISD::SETUGT: std::swap(LHS, RHS); // FALLTHROUGH case ISD::SETULT: + // Turn lhs u< rhs with lhs constant into rhs u>= lhs+1, this allows us to + // fold constant into instruction. + if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { + LHS = RHS; + RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); + TCC = MSP430CC::COND_HS; + break; + } TCC = MSP430CC::COND_LO; // aka COND_NC break; case ISD::SETLE: std::swap(LHS, RHS); // FALLTHROUGH case ISD::SETGE: + // Turn lhs >= rhs with lhs constant into rhs < lhs+1, this allows us to + // fold constant into instruction. + if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { + LHS = RHS; + RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); + TCC = MSP430CC::COND_L; + break; + } TCC = MSP430CC::COND_GE; break; case ISD::SETGT: std::swap(LHS, RHS); // FALLTHROUGH case ISD::SETLT: + // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows us to + // fold constant into instruction. + if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) { + LHS = RHS; + RHS = DAG.getConstant(C->getSExtValue() + 1, C->getValueType(0)); + TCC = MSP430CC::COND_GE; + break; + } TCC = MSP430CC::COND_L; break; } @@ -723,6 +755,8 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { // If we are doing an AND and testing against zero, then the CMP // will not be generated. The AND (or BIT) will generate the condition codes, // but they are different from CMP. + // FIXME: since we're doing a post-processing, use a pseudoinstr here, so + // lowering & isel wouldn't diverge. bool andCC = false; if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) { if (RHSC->isNullValue() && LHS.hasOneUse() && @@ -750,11 +784,11 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { case MSP430CC::COND_HS: // Res = SRW & 1, no processing is required break; - case MSP430CC::COND_LO: + case MSP430CC::COND_LO: // Res = ~(SRW & 1) Invert = true; break; - case MSP430CC::COND_NE: + case MSP430CC::COND_NE: if (andCC) { // C = ~Z, thus Res = SRW & 1, no processing is required } else { @@ -762,7 +796,7 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { Shift = true; } break; - case MSP430CC::COND_E: + case MSP430CC::COND_E: if (andCC) { // C = ~Z, thus Res = ~(SRW & 1) } else { @@ -776,7 +810,7 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { SDValue One = DAG.getConstant(1, VT); if (Convert) { SDValue SR = DAG.getCopyFromReg(DAG.getEntryNode(), dl, MSP430::SRW, - MVT::i16, Flag); + MVT::i16, Flag); if (Shift) // FIXME: somewhere this is turned into a SRL, lower it MSP specific? SR = DAG.getNode(ISD::SRA, dl, MVT::i16, SR, One); @@ -933,6 +967,31 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const { } } +bool MSP430TargetLowering::isTruncateFree(const Type *Ty1, + const Type *Ty2) const { + if (!Ty1->isInteger() || !Ty2->isInteger()) + return false; + + return (Ty1->getPrimitiveSizeInBits() > Ty2->getPrimitiveSizeInBits()); +} + +bool MSP430TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { + if (!VT1.isInteger() || !VT2.isInteger()) + return false; + + return (VT1.getSizeInBits() > VT2.getSizeInBits()); +} + +bool MSP430TargetLowering::isZExtFree(const Type *Ty1, const Type *Ty2) const { + // MSP430 implicitly zero-extends 8-bit results in 16-bit registers. + return 0 && Ty1->isInteger(8) && Ty2->isInteger(16); +} + +bool MSP430TargetLowering::isZExtFree(EVT VT1, EVT VT2) const { + // MSP430 implicitly zero-extends 8-bit results in 16-bit registers. + return 0 && VT1 == MVT::i8 && VT2 == MVT::i16; +} + //===----------------------------------------------------------------------===// // Other Lowering Code //===----------------------------------------------------------------------===// diff --git a/lib/Target/MSP430/MSP430ISelLowering.h b/lib/Target/MSP430/MSP430ISelLowering.h index 4921500..6152a05 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.h +++ b/lib/Target/MSP430/MSP430ISelLowering.h @@ -99,6 +99,23 @@ namespace llvm { std::pair<unsigned, const TargetRegisterClass*> getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const; + /// isTruncateFree - Return true if it's free to truncate a value of type + /// Ty1 to type Ty2. e.g. On msp430 it's free to truncate a i16 value in + /// register R15W to i8 by referencing its sub-register R15B. + virtual bool isTruncateFree(const Type *Ty1, const Type *Ty2) const; + virtual bool isTruncateFree(EVT VT1, EVT VT2) const; + + /// isZExtFree - Return true if any actual instruction that defines a value + /// of type Ty1 implicit zero-extends the value to Ty2 in the result + /// register. This does not necessarily include registers defined in unknown + /// ways, such as incoming arguments, or copies from unknown virtual + /// registers. Also, if isTruncateFree(Ty2, Ty1) is true, this does not + /// necessarily apply to truncate instructions. e.g. on msp430, all + /// instructions that define 8-bit values implicit zero-extend the result + /// out to 16 bits. + virtual bool isZExtFree(const Type *Ty1, const Type *Ty2) const; + virtual bool isZExtFree(EVT VT1, EVT VT2) const; + MachineBasicBlock* EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *BB, DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const; diff --git a/lib/Target/MSP430/MSP430InstrFormats.td b/lib/Target/MSP430/MSP430InstrFormats.td index 61b3399..4ccc7df 100644 --- a/lib/Target/MSP430/MSP430InstrFormats.td +++ b/lib/Target/MSP430/MSP430InstrFormats.td @@ -11,8 +11,48 @@ // Describe MSP430 instructions format here // +// Format specifies the encoding used by the instruction. This is part of the +// ad-hoc solution used to emit machine instruction encodings by our machine +// code emitter. +class Format<bits<2> val> { + bits<2> Value = val; +} + +def PseudoFrm : Format<0>; +def SingleOpFrm : Format<1>; +def DoubleOpFrm : Format<2>; +def CondJumpFrm : Format<3>; + +class SourceMode<bits<2> val> { + bits<2> Value = val; +} + +def SrcReg : SourceMode<0>; +def SrcMem : SourceMode<1>; +def SrcIndReg : SourceMode<2>; +def SrcPostInc : SourceMode<3>; +def SrcImm : SourceMode<3>; + +class DestMode<bit val> { + bit Value = val; +} + +def DstReg : DestMode<0>; +def DstMem : DestMode<1>; + +class SizeVal<bits<3> val> { + bits<3> Value = val; +} + +def SizeUnknown : SizeVal<0>; // Unknown / unset size +def SizeSpecial : SizeVal<1>; // Special instruction, e.g. pseudo +def Size2Bytes : SizeVal<2>; +def Size4Bytes : SizeVal<3>; +def Size6Bytes : SizeVal<4>; + // Generic MSP430 Format -class MSP430Inst<dag outs, dag ins, string asmstr> : Instruction { +class MSP430Inst<dag outs, dag ins, SizeVal sz, Format f, + string asmstr> : Instruction { field bits<16> Inst; let Namespace = "MSP430"; @@ -20,48 +60,150 @@ class MSP430Inst<dag outs, dag ins, string asmstr> : Instruction { dag OutOperandList = outs; dag InOperandList = ins; + Format Form = f; + bits<2> FormBits = Form.Value; + + SizeVal Sz = sz; + bits<3> Size = Sz.Value; + let AsmString = asmstr; } // FIXME: Create different classes for different addressing modes. // MSP430 Double Operand (Format I) Instructions -class IForm<bits<4> opcode, bit ad, bit bw, bits<2> as, +class IForm<bits<4> opcode, DestMode dest, bit bw, SourceMode src, SizeVal sz, dag outs, dag ins, string asmstr, list<dag> pattern> - : MSP430Inst<outs, ins, asmstr> { + : MSP430Inst<outs, ins, sz, DoubleOpFrm, asmstr> { let Pattern = pattern; + + DestMode ad = dest; + SourceMode as = src; let Inst{12-15} = opcode; - let Inst{7} = ad; + let Inst{7} = ad.Value; let Inst{6} = bw; - let Inst{4-5} = as; + let Inst{4-5} = as.Value; } +// 8 bit IForm instructions +class IForm8<bits<4> opcode, DestMode dest, SourceMode src, SizeVal sz, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm<opcode, dest, 1, src, sz, outs, ins, asmstr, pattern>; + +class I8rr<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm8<opcode, DstReg, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>; + +class I8ri<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm8<opcode, DstReg, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>; + +class I8rm<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm8<opcode, DstReg, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>; + +class I8mr<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm8<opcode, DstMem, SrcReg, Size4Bytes, outs, ins, asmstr, pattern>; + +class I8mi<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm8<opcode, DstMem, SrcImm, Size6Bytes, outs, ins, asmstr, pattern>; + +class I8mm<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm8<opcode, DstMem, SrcMem, Size6Bytes, outs, ins, asmstr, pattern>; + +// 16 bit IForm instructions +class IForm16<bits<4> opcode, DestMode dest, SourceMode src, SizeVal sz, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm<opcode, dest, 0, src, sz, outs, ins, asmstr, pattern>; + +class I16rr<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm16<opcode, DstReg, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>; + +class I16ri<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm16<opcode, DstReg, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>; + +class I16rm<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm16<opcode, DstReg, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>; + +class I16mr<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm16<opcode, DstMem, SrcReg, Size4Bytes, outs, ins, asmstr, pattern>; + +class I16mi<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm16<opcode, DstMem, SrcImm, Size6Bytes, outs, ins, asmstr, pattern>; + +class I16mm<bits<4> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IForm16<opcode, DstMem, SrcMem, Size6Bytes, outs, ins, asmstr, pattern>; + // MSP430 Single Operand (Format II) Instructions -class IIForm<bits<9> opcode, bit bw, bits<2> ad, +class IIForm<bits<9> opcode, bit bw, SourceMode src, SizeVal sz, dag outs, dag ins, string asmstr, list<dag> pattern> - : MSP430Inst<outs, ins, asmstr> { + : MSP430Inst<outs, ins, sz, SingleOpFrm, asmstr> { let Pattern = pattern; + SourceMode as = src; + let Inst{7-15} = opcode; let Inst{6} = bw; - let Inst{4-5} = ad; + let Inst{4-5} = as.Value; } +// 8 bit IIForm instructions +class IIForm8<bits<9> opcode, SourceMode src, SizeVal sz, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm<opcode, 1, src, sz, outs, ins, asmstr, pattern>; + +class II8r<bits<9> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm8<opcode, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>; + +class II8m<bits<9> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm8<opcode, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>; + +class II8i<bits<9> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm8<opcode, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>; + +// 16 bit IIForm instructions +class IIForm16<bits<9> opcode, SourceMode src, SizeVal sz, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm<opcode, 0, src, sz, outs, ins, asmstr, pattern>; + +class II16r<bits<9> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm16<opcode, SrcReg, Size2Bytes, outs, ins, asmstr, pattern>; + +class II16m<bits<9> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm16<opcode, SrcMem, Size4Bytes, outs, ins, asmstr, pattern>; + +class II16i<bits<9> opcode, + dag outs, dag ins, string asmstr, list<dag> pattern> + : IIForm16<opcode, SrcImm, Size4Bytes, outs, ins, asmstr, pattern>; + // MSP430 Conditional Jumps Instructions -class CJForm<bits<3> opcode, bits<3> cond, bit s, +class CJForm<bits<3> opcode, bits<3> cond, dag outs, dag ins, string asmstr, list<dag> pattern> - : MSP430Inst<outs, ins, asmstr> { + : MSP430Inst<outs, ins, Size2Bytes, CondJumpFrm, asmstr> { let Pattern = pattern; let Inst{13-15} = opcode; let Inst{10-12} = cond; - let Inst{9} = s; } // Pseudo instructions class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern> - : MSP430Inst<outs, ins, asmstr> { + : MSP430Inst<outs, ins, SizeSpecial, PseudoFrm, asmstr> { let Pattern = pattern; let Inst{15-0} = 0; } diff --git a/lib/Target/MSP430/MSP430InstrInfo.cpp b/lib/Target/MSP430/MSP430InstrInfo.cpp index 2ae6759..9dc69e0 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.cpp +++ b/lib/Target/MSP430/MSP430InstrInfo.cpp @@ -344,3 +344,45 @@ MSP430InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, } return Count; } + +/// GetInstSize - Return the number of bytes of code the specified +/// instruction may be. This returns the maximum number of bytes. +/// +unsigned MSP430InstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { + const TargetInstrDesc &Desc = MI->getDesc(); + + switch (Desc.TSFlags & MSP430II::SizeMask) { + default: + switch (Desc.getOpcode()) { + default: + assert(0 && "Unknown instruction size!"); + case TargetInstrInfo::DBG_LABEL: + case TargetInstrInfo::EH_LABEL: + case TargetInstrInfo::IMPLICIT_DEF: + case TargetInstrInfo::KILL: + return 0; + case TargetInstrInfo::INLINEASM: { + const MachineFunction *MF = MI->getParent()->getParent(); + const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo(); + return TII.getInlineAsmLength(MI->getOperand(0).getSymbolName(), + *MF->getTarget().getMCAsmInfo()); + } + } + case MSP430II::SizeSpecial: + switch (MI->getOpcode()) { + default: + assert(0 && "Unknown instruction size!"); + case MSP430::SAR8r1c: + case MSP430::SAR16r1c: + return 4; + } + case MSP430II::Size2Bytes: + return 2; + case MSP430II::Size4Bytes: + return 4; + case MSP430II::Size6Bytes: + return 6; + } + + return 6; +} diff --git a/lib/Target/MSP430/MSP430InstrInfo.h b/lib/Target/MSP430/MSP430InstrInfo.h index e4ceeb9..6ef4b0a 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.h +++ b/lib/Target/MSP430/MSP430InstrInfo.h @@ -21,6 +21,22 @@ namespace llvm { class MSP430TargetMachine; +/// MSP430II - This namespace holds all of the target specific flags that +/// instruction info tracks. +/// +namespace MSP430II { + enum { + SizeShift = 2, + SizeMask = 7 << SizeShift, + + SizeUnknown = 0 << SizeShift, + SizeSpecial = 1 << SizeShift, + Size2Bytes = 2 << SizeShift, + Size4Bytes = 3 << SizeShift, + Size6Bytes = 4 << SizeShift + }; +} + class MSP430InstrInfo : public TargetInstrInfoImpl { const MSP430RegisterInfo RI; MSP430TargetMachine &TM; @@ -59,6 +75,8 @@ public: MachineBasicBlock::iterator MI, const std::vector<CalleeSavedInfo> &CSI) const; + unsigned GetInstSizeInBytes(const MachineInstr *MI) const; + // Branch folding goodness bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const; bool isUnpredicatedTerminator(const MachineInstr *MI) const; diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td index 022d171..cd502cf 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.td +++ b/lib/Target/MSP430/MSP430InstrInfo.td @@ -157,23 +157,35 @@ def NOP : Pseudo<(outs), (ins), "nop", []>; // FIXME: Provide proper encoding! let isReturn = 1, isTerminator = 1, isBarrier = 1 in { - def RET : Pseudo<(outs), (ins), "ret", [(MSP430retflag)]>; - def RETI : Pseudo<(outs), (ins), "reti", [(MSP430retiflag)]>; + def RET : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs), (ins), "ret", [(MSP430retflag)]>; + def RETI : II16r<0x0, (outs), (ins), "reti", [(MSP430retiflag)]>; } let isBranch = 1, isTerminator = 1 in { +// FIXME: expand opcode & cond field for branches! + // Direct branch -let isBarrier = 1 in - def JMP : Pseudo<(outs), (ins brtarget:$dst), +let isBarrier = 1 in { + // Short branch + def JMP : CJForm<0, 0, + (outs), (ins brtarget:$dst), "jmp\t$dst", [(br bb:$dst)]>; + // Long branch + def B : I16ri<0, + (outs), (ins brtarget:$dst), + "br\t$dst", + []>; +} // Conditional branches let Uses = [SRW] in - def JCC : Pseudo<(outs), (ins brtarget:$dst, cc:$cc), - "j$cc\t$dst", - [(MSP430brcc bb:$dst, imm:$cc)]>; + def JCC : CJForm<0, 0, + (outs), (ins brtarget:$dst, cc:$cc), + "j$cc\t$dst", + [(MSP430brcc bb:$dst, imm:$cc)]>; } // isBranch, isTerminator //===----------------------------------------------------------------------===// @@ -186,12 +198,15 @@ let isCall = 1 in // registers are added manually. let Defs = [R12W, R13W, R14W, R15W, SRW], Uses = [SPW] in { - def CALLi : Pseudo<(outs), (ins i16imm:$dst, variable_ops), - "call\t$dst", [(MSP430call imm:$dst)]>; - def CALLr : Pseudo<(outs), (ins GR16:$dst, variable_ops), - "call\t$dst", [(MSP430call GR16:$dst)]>; - def CALLm : Pseudo<(outs), (ins memsrc:$dst, variable_ops), - "call\t${dst:mem}", [(MSP430call (load addr:$dst))]>; + def CALLi : II16i<0x0, + (outs), (ins i16imm:$dst, variable_ops), + "call\t$dst", [(MSP430call imm:$dst)]>; + def CALLr : II16r<0x0, + (outs), (ins GR16:$dst, variable_ops), + "call\t$dst", [(MSP430call GR16:$dst)]>; + def CALLm : II16m<0x0, + (outs), (ins memsrc:$dst, variable_ops), + "call\t${dst:mem}", [(MSP430call (load addr:$dst))]>; } @@ -200,10 +215,12 @@ let isCall = 1 in // let Defs = [SPW], Uses = [SPW], neverHasSideEffects=1 in { let mayLoad = 1 in -def POP16r : Pseudo<(outs GR16:$reg), (ins), "pop.w\t$reg", []>; +def POP16r : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$reg), (ins), "pop.w\t$reg", []>; let mayStore = 1 in -def PUSH16r : Pseudo<(outs), (ins GR16:$reg), "push.w\t$reg",[]>; +def PUSH16r : II16r<0x0, + (outs), (ins GR16:$reg), "push.w\t$reg",[]>; } //===----------------------------------------------------------------------===// @@ -211,45 +228,55 @@ def PUSH16r : Pseudo<(outs), (ins GR16:$reg), "push.w\t$reg",[]>; // FIXME: Provide proper encoding! let neverHasSideEffects = 1 in { -def MOV8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src), - "mov.b\t{$src, $dst}", - []>; -def MOV16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "mov.w\t{$src, $dst}", - []>; +def MOV8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src), + "mov.b\t{$src, $dst}", + []>; +def MOV16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src), + "mov.w\t{$src, $dst}", + []>; } // FIXME: Provide proper encoding! let isReMaterializable = 1, isAsCheapAsAMove = 1 in { -def MOV8ri : Pseudo<(outs GR8:$dst), (ins i8imm:$src), - "mov.b\t{$src, $dst}", - [(set GR8:$dst, imm:$src)]>; -def MOV16ri : Pseudo<(outs GR16:$dst), (ins i16imm:$src), - "mov.w\t{$src, $dst}", - [(set GR16:$dst, imm:$src)]>; +def MOV8ri : I8ri<0x0, + (outs GR8:$dst), (ins i8imm:$src), + "mov.b\t{$src, $dst}", + [(set GR8:$dst, imm:$src)]>; +def MOV16ri : I16ri<0x0, + (outs GR16:$dst), (ins i16imm:$src), + "mov.w\t{$src, $dst}", + [(set GR16:$dst, imm:$src)]>; } let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { -def MOV8rm : Pseudo<(outs GR8:$dst), (ins memsrc:$src), - "mov.b\t{$src, $dst}", - [(set GR8:$dst, (load addr:$src))]>; -def MOV16rm : Pseudo<(outs GR16:$dst), (ins memsrc:$src), - "mov.w\t{$src, $dst}", - [(set GR16:$dst, (load addr:$src))]>; +def MOV8rm : I8rm<0x0, + (outs GR8:$dst), (ins memsrc:$src), + "mov.b\t{$src, $dst}", + [(set GR8:$dst, (load addr:$src))]>; +def MOV16rm : I16rm<0x0, + (outs GR16:$dst), (ins memsrc:$src), + "mov.w\t{$src, $dst}", + [(set GR16:$dst, (load addr:$src))]>; } -def MOVZX16rr8 : Pseudo<(outs GR16:$dst), (ins GR8:$src), - "mov.b\t{$src, $dst}", - [(set GR16:$dst, (zext GR8:$src))]>; -def MOVZX16rm8 : Pseudo<(outs GR16:$dst), (ins memsrc:$src), - "mov.b\t{$src, $dst}", - [(set GR16:$dst, (zextloadi16i8 addr:$src))]>; +def MOVZX16rr8 : I8rr<0x0, + (outs GR16:$dst), (ins GR8:$src), + "mov.b\t{$src, $dst}", + [(set GR16:$dst, (zext GR8:$src))]>; +def MOVZX16rm8 : I8rm<0x0, + (outs GR16:$dst), (ins memsrc:$src), + "mov.b\t{$src, $dst}", + [(set GR16:$dst, (zextloadi16i8 addr:$src))]>; let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb" in { -def MOV8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR16:$base), - "mov.b\t{@$base+, $dst}", []>; -def MOV16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$base), - "mov.w\t{@$base+, $dst}", []>; +def MOV8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR8:$dst, GR16:$base_wb), (ins GR16:$base), + "mov.b\t{@$base+, $dst}", []>; +def MOV16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$dst, GR16:$base_wb), (ins GR16:$base), + "mov.w\t{@$base+, $dst}", []>; } // Any instruction that defines a 8-bit result leaves the high half of the @@ -267,27 +294,32 @@ def def8 : PatLeaf<(i8 GR8:$src), [{ def : Pat<(i16 (zext def8:$src)), (SUBREG_TO_REG (i16 0), GR8:$src, subreg_8bit)>; - -def MOV8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "mov.b\t{$src, $dst}", - [(store (i8 imm:$src), addr:$dst)]>; -def MOV16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "mov.w\t{$src, $dst}", - [(store (i16 imm:$src), addr:$dst)]>; - -def MOV8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "mov.b\t{$src, $dst}", - [(store GR8:$src, addr:$dst)]>; -def MOV16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "mov.w\t{$src, $dst}", - [(store GR16:$src, addr:$dst)]>; - -def MOV8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "mov.b\t{$src, $dst}", - [(store (i8 (load addr:$src)), addr:$dst)]>; -def MOV16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "mov.w\t{$src, $dst}", - [(store (i16 (load addr:$src)), addr:$dst)]>; +def MOV8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "mov.b\t{$src, $dst}", + [(store (i8 imm:$src), addr:$dst)]>; +def MOV16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "mov.w\t{$src, $dst}", + [(store (i16 imm:$src), addr:$dst)]>; + +def MOV8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "mov.b\t{$src, $dst}", + [(store GR8:$src, addr:$dst)]>; +def MOV16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "mov.w\t{$src, $dst}", + [(store GR16:$src, addr:$dst)]>; + +def MOV8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "mov.b\t{$src, $dst}", + [(store (i8 (load addr:$src)), addr:$dst)]>; +def MOV16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "mov.w\t{$src, $dst}", + [(store (i16 (load addr:$src)), addr:$dst)]>; //===----------------------------------------------------------------------===// // Arithmetic Instructions @@ -297,496 +329,624 @@ let isTwoAddress = 1 in { let Defs = [SRW] in { let isCommutable = 1 in { // X = ADD Y, Z == X = ADD Z, Y -// FIXME: Provide proper encoding! -def ADD8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "add.b\t{$src2, $dst}", - [(set GR8:$dst, (add GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def ADD16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "add.w\t{$src2, $dst}", - [(set GR16:$dst, (add GR16:$src1, GR16:$src2)), - (implicit SRW)]>; + +def ADD8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "add.b\t{$src2, $dst}", + [(set GR8:$dst, (add GR8:$src1, GR8:$src2)), + (implicit SRW)]>; +def ADD16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "add.w\t{$src2, $dst}", + [(set GR16:$dst, (add GR16:$src1, GR16:$src2)), + (implicit SRW)]>; } -def ADD8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "add.b\t{$src2, $dst}", - [(set GR8:$dst, (add GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def ADD16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "add.w\t{$src2, $dst}", - [(set GR16:$dst, (add GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; +def ADD8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "add.b\t{$src2, $dst}", + [(set GR8:$dst, (add GR8:$src1, (load addr:$src2))), + (implicit SRW)]>; +def ADD16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "add.w\t{$src2, $dst}", + [(set GR16:$dst, (add GR16:$src1, (load addr:$src2))), + (implicit SRW)]>; let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb, $src1 = $dst" in { -def ADD8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base), - "add.b\t{@$base+, $dst}", []>; -def ADD16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base), +def ADD8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR8:$dst, GR16:$base_wb), + (ins GR8:$src1, GR16:$base), + "add.b\t{@$base+, $dst}", []>; +def ADD16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$dst, GR16:$base_wb), + (ins GR16:$src1, GR16:$base), "add.w\t{@$base+, $dst}", []>; } -def ADD8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "add.b\t{$src2, $dst}", - [(set GR8:$dst, (add GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def ADD16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "add.w\t{$src2, $dst}", - [(set GR16:$dst, (add GR16:$src1, imm:$src2)), - (implicit SRW)]>; +def ADD8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "add.b\t{$src2, $dst}", + [(set GR8:$dst, (add GR8:$src1, imm:$src2)), + (implicit SRW)]>; +def ADD16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "add.w\t{$src2, $dst}", + [(set GR16:$dst, (add GR16:$src1, imm:$src2)), + (implicit SRW)]>; let isTwoAddress = 0 in { -def ADD8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "add.b\t{$src, $dst}", - [(store (add (load addr:$dst), GR8:$src), addr:$dst), - (implicit SRW)]>; -def ADD16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "add.w\t{$src, $dst}", - [(store (add (load addr:$dst), GR16:$src), addr:$dst), - (implicit SRW)]>; - -def ADD8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "add.b\t{$src, $dst}", - [(store (add (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SRW)]>; -def ADD16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "add.w\t{$src, $dst}", - [(store (add (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SRW)]>; - -def ADD8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "add.b\t{$src, $dst}", - [(store (add (load addr:$dst), (i8 (load addr:$src))), addr:$dst), - (implicit SRW)]>; -def ADD16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "add.w\t{$src, $dst}", - [(store (add (load addr:$dst), (i16 (load addr:$src))), addr:$dst), - (implicit SRW)]>; +def ADD8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "add.b\t{$src, $dst}", + [(store (add (load addr:$dst), GR8:$src), addr:$dst), + (implicit SRW)]>; +def ADD16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "add.w\t{$src, $dst}", + [(store (add (load addr:$dst), GR16:$src), addr:$dst), + (implicit SRW)]>; + +def ADD8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "add.b\t{$src, $dst}", + [(store (add (load addr:$dst), (i8 imm:$src)), addr:$dst), + (implicit SRW)]>; +def ADD16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "add.w\t{$src, $dst}", + [(store (add (load addr:$dst), (i16 imm:$src)), addr:$dst), + (implicit SRW)]>; + +def ADD8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "add.b\t{$src, $dst}", + [(store (add (load addr:$dst), + (i8 (load addr:$src))), addr:$dst), + (implicit SRW)]>; +def ADD16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "add.w\t{$src, $dst}", + [(store (add (load addr:$dst), + (i16 (load addr:$src))), addr:$dst), + (implicit SRW)]>; } let Uses = [SRW] in { let isCommutable = 1 in { // X = ADDC Y, Z == X = ADDC Z, Y -def ADC8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "addc.b\t{$src2, $dst}", - [(set GR8:$dst, (adde GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def ADC16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "addc.w\t{$src2, $dst}", - [(set GR16:$dst, (adde GR16:$src1, GR16:$src2)), - (implicit SRW)]>; +def ADC8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "addc.b\t{$src2, $dst}", + [(set GR8:$dst, (adde GR8:$src1, GR8:$src2)), + (implicit SRW)]>; +def ADC16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "addc.w\t{$src2, $dst}", + [(set GR16:$dst, (adde GR16:$src1, GR16:$src2)), + (implicit SRW)]>; } // isCommutable -def ADC8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "addc.b\t{$src2, $dst}", - [(set GR8:$dst, (adde GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def ADC16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "addc.w\t{$src2, $dst}", - [(set GR16:$dst, (adde GR16:$src1, imm:$src2)), - (implicit SRW)]>; - -def ADC8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "addc.b\t{$src2, $dst}", - [(set GR8:$dst, (adde GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def ADC16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "addc.w\t{$src2, $dst}", - [(set GR16:$dst, (adde GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; +def ADC8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "addc.b\t{$src2, $dst}", + [(set GR8:$dst, (adde GR8:$src1, imm:$src2)), + (implicit SRW)]>; +def ADC16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "addc.w\t{$src2, $dst}", + [(set GR16:$dst, (adde GR16:$src1, imm:$src2)), + (implicit SRW)]>; + +def ADC8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "addc.b\t{$src2, $dst}", + [(set GR8:$dst, (adde GR8:$src1, (load addr:$src2))), + (implicit SRW)]>; +def ADC16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "addc.w\t{$src2, $dst}", + [(set GR16:$dst, (adde GR16:$src1, (load addr:$src2))), + (implicit SRW)]>; let isTwoAddress = 0 in { -def ADC8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "addc.b\t{$src, $dst}", - [(store (adde (load addr:$dst), GR8:$src), addr:$dst), - (implicit SRW)]>; -def ADC16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "addc.w\t{$src, $dst}", - [(store (adde (load addr:$dst), GR16:$src), addr:$dst), - (implicit SRW)]>; - -def ADC8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "addc.b\t{$src, $dst}", - [(store (adde (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SRW)]>; -def ADC16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "addc.w\t{$src, $dst}", - [(store (adde (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SRW)]>; - -def ADC8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "addc.b\t{$src, $dst}", - [(store (adde (load addr:$dst), (i8 (load addr:$src))), addr:$dst), - (implicit SRW)]>; -def ADC16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "addc.w\t{$src, $dst}", - [(store (adde (load addr:$dst), (i16 (load addr:$src))), addr:$dst), - (implicit SRW)]>; +def ADC8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "addc.b\t{$src, $dst}", + [(store (adde (load addr:$dst), GR8:$src), addr:$dst), + (implicit SRW)]>; +def ADC16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "addc.w\t{$src, $dst}", + [(store (adde (load addr:$dst), GR16:$src), addr:$dst), + (implicit SRW)]>; + +def ADC8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "addc.b\t{$src, $dst}", + [(store (adde (load addr:$dst), (i8 imm:$src)), addr:$dst), + (implicit SRW)]>; +def ADC16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "addc.w\t{$src, $dst}", + [(store (adde (load addr:$dst), (i16 imm:$src)), addr:$dst), + (implicit SRW)]>; + +def ADC8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "addc.b\t{$src, $dst}", + [(store (adde (load addr:$dst), + (i8 (load addr:$src))), addr:$dst), + (implicit SRW)]>; +def ADC16mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "addc.w\t{$src, $dst}", + [(store (adde (load addr:$dst), + (i16 (load addr:$src))), addr:$dst), + (implicit SRW)]>; } } // Uses = [SRW] let isCommutable = 1 in { // X = AND Y, Z == X = AND Z, Y -def AND8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "and.b\t{$src2, $dst}", - [(set GR8:$dst, (and GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def AND16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "and.w\t{$src2, $dst}", - [(set GR16:$dst, (and GR16:$src1, GR16:$src2)), - (implicit SRW)]>; +def AND8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "and.b\t{$src2, $dst}", + [(set GR8:$dst, (and GR8:$src1, GR8:$src2)), + (implicit SRW)]>; +def AND16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "and.w\t{$src2, $dst}", + [(set GR16:$dst, (and GR16:$src1, GR16:$src2)), + (implicit SRW)]>; } -def AND8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "and.b\t{$src2, $dst}", - [(set GR8:$dst, (and GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def AND16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "and.w\t{$src2, $dst}", - [(set GR16:$dst, (and GR16:$src1, imm:$src2)), - (implicit SRW)]>; - -def AND8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "and.b\t{$src2, $dst}", - [(set GR8:$dst, (and GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def AND16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "and.w\t{$src2, $dst}", - [(set GR16:$dst, (and GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; +def AND8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "and.b\t{$src2, $dst}", + [(set GR8:$dst, (and GR8:$src1, imm:$src2)), + (implicit SRW)]>; +def AND16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "and.w\t{$src2, $dst}", + [(set GR16:$dst, (and GR16:$src1, imm:$src2)), + (implicit SRW)]>; + +def AND8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "and.b\t{$src2, $dst}", + [(set GR8:$dst, (and GR8:$src1, (load addr:$src2))), + (implicit SRW)]>; +def AND16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "and.w\t{$src2, $dst}", + [(set GR16:$dst, (and GR16:$src1, (load addr:$src2))), + (implicit SRW)]>; let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb, $src1 = $dst" in { -def AND8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base), - "and.b\t{@$base+, $dst}", []>; -def AND16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base), - "and.w\t{@$base+, $dst}", []>; +def AND8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR8:$dst, GR16:$base_wb), + (ins GR8:$src1, GR16:$base), + "and.b\t{@$base+, $dst}", []>; +def AND16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$dst, GR16:$base_wb), + (ins GR16:$src1, GR16:$base), + "and.w\t{@$base+, $dst}", []>; } let isTwoAddress = 0 in { -def AND8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "and.b\t{$src, $dst}", - [(store (and (load addr:$dst), GR8:$src), addr:$dst), - (implicit SRW)]>; -def AND16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "and.w\t{$src, $dst}", - [(store (and (load addr:$dst), GR16:$src), addr:$dst), - (implicit SRW)]>; - -def AND8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "and.b\t{$src, $dst}", - [(store (and (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SRW)]>; -def AND16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "and.w\t{$src, $dst}", - [(store (and (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SRW)]>; - -def AND8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "and.b\t{$src, $dst}", - [(store (and (load addr:$dst), (i8 (load addr:$src))), addr:$dst), - (implicit SRW)]>; -def AND16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "and.w\t{$src, $dst}", - [(store (and (load addr:$dst), (i16 (load addr:$src))), addr:$dst), - (implicit SRW)]>; +def AND8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "and.b\t{$src, $dst}", + [(store (and (load addr:$dst), GR8:$src), addr:$dst), + (implicit SRW)]>; +def AND16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "and.w\t{$src, $dst}", + [(store (and (load addr:$dst), GR16:$src), addr:$dst), + (implicit SRW)]>; + +def AND8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "and.b\t{$src, $dst}", + [(store (and (load addr:$dst), (i8 imm:$src)), addr:$dst), + (implicit SRW)]>; +def AND16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "and.w\t{$src, $dst}", + [(store (and (load addr:$dst), (i16 imm:$src)), addr:$dst), + (implicit SRW)]>; + +def AND8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "and.b\t{$src, $dst}", + [(store (and (load addr:$dst), + (i8 (load addr:$src))), addr:$dst), + (implicit SRW)]>; +def AND16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "and.w\t{$src, $dst}", + [(store (and (load addr:$dst), + (i16 (load addr:$src))), addr:$dst), + (implicit SRW)]>; } let isCommutable = 1 in { // X = OR Y, Z == X = OR Z, Y -def OR8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "bis.b\t{$src2, $dst}", - [(set GR8:$dst, (or GR8:$src1, GR8:$src2))]>; -def OR16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "bis.w\t{$src2, $dst}", - [(set GR16:$dst, (or GR16:$src1, GR16:$src2))]>; +def OR8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "bis.b\t{$src2, $dst}", + [(set GR8:$dst, (or GR8:$src1, GR8:$src2))]>; +def OR16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "bis.w\t{$src2, $dst}", + [(set GR16:$dst, (or GR16:$src1, GR16:$src2))]>; } -def OR8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "bis.b\t{$src2, $dst}", - [(set GR8:$dst, (or GR8:$src1, imm:$src2))]>; -def OR16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "bis.w\t{$src2, $dst}", - [(set GR16:$dst, (or GR16:$src1, imm:$src2))]>; - -def OR8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "bis.b\t{$src2, $dst}", - [(set GR8:$dst, (or GR8:$src1, (load addr:$src2)))]>; -def OR16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "bis.w\t{$src2, $dst}", - [(set GR16:$dst, (or GR16:$src1, (load addr:$src2)))]>; +def OR8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "bis.b\t{$src2, $dst}", + [(set GR8:$dst, (or GR8:$src1, imm:$src2))]>; +def OR16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "bis.w\t{$src2, $dst}", + [(set GR16:$dst, (or GR16:$src1, imm:$src2))]>; + +def OR8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "bis.b\t{$src2, $dst}", + [(set GR8:$dst, (or GR8:$src1, (load addr:$src2)))]>; +def OR16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "bis.w\t{$src2, $dst}", + [(set GR16:$dst, (or GR16:$src1, (load addr:$src2)))]>; let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb, $src1 = $dst" in { -def OR8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base), +def OR8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR8:$dst, GR16:$base_wb), + (ins GR8:$src1, GR16:$base), "bis.b\t{@$base+, $dst}", []>; -def OR16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base), - "bis.w\t{@$base+, $dst}", []>; +def OR16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$dst, GR16:$base_wb), + (ins GR16:$src1, GR16:$base), + "bis.w\t{@$base+, $dst}", []>; } let isTwoAddress = 0 in { -def OR8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "bis.b\t{$src, $dst}", - [(store (or (load addr:$dst), GR8:$src), addr:$dst)]>; -def OR16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "bis.w\t{$src, $dst}", - [(store (or (load addr:$dst), GR16:$src), addr:$dst)]>; - -def OR8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "bis.b\t{$src, $dst}", - [(store (or (load addr:$dst), (i8 imm:$src)), addr:$dst)]>; -def OR16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "bis.w\t{$src, $dst}", - [(store (or (load addr:$dst), (i16 imm:$src)), addr:$dst)]>; - -def OR8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "bis.b\t{$src, $dst}", - [(store (or (i8 (load addr:$dst)), - (i8 (load addr:$src))), addr:$dst)]>; -def OR16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "bis.w\t{$src, $dst}", - [(store (or (i16 (load addr:$dst)), - (i16 (load addr:$src))), addr:$dst)]>; +def OR8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "bis.b\t{$src, $dst}", + [(store (or (load addr:$dst), GR8:$src), addr:$dst)]>; +def OR16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "bis.w\t{$src, $dst}", + [(store (or (load addr:$dst), GR16:$src), addr:$dst)]>; + +def OR8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "bis.b\t{$src, $dst}", + [(store (or (load addr:$dst), (i8 imm:$src)), addr:$dst)]>; +def OR16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "bis.w\t{$src, $dst}", + [(store (or (load addr:$dst), (i16 imm:$src)), addr:$dst)]>; + +def OR8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "bis.b\t{$src, $dst}", + [(store (or (i8 (load addr:$dst)), + (i8 (load addr:$src))), addr:$dst)]>; +def OR16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "bis.w\t{$src, $dst}", + [(store (or (i16 (load addr:$dst)), + (i16 (load addr:$src))), addr:$dst)]>; } // bic does not modify condition codes -def BIC8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "bic.b\t{$src2, $dst}", - [(set GR8:$dst, (and GR8:$src1, (not GR8:$src2)))]>; -def BIC16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "bic.w\t{$src2, $dst}", - [(set GR16:$dst, (and GR16:$src1, (not GR16:$src2)))]>; - -def BIC8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "bic.b\t{$src2, $dst}", - [(set GR8:$dst, (and GR8:$src1, (not (i8 (load addr:$src2)))))]>; -def BIC16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "bic.w\t{$src2, $dst}", - [(set GR16:$dst, (and GR16:$src1, (not (i16 (load addr:$src2)))))]>; +def BIC8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "bic.b\t{$src2, $dst}", + [(set GR8:$dst, (and GR8:$src1, (not GR8:$src2)))]>; +def BIC16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "bic.w\t{$src2, $dst}", + [(set GR16:$dst, (and GR16:$src1, (not GR16:$src2)))]>; + +def BIC8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "bic.b\t{$src2, $dst}", + [(set GR8:$dst, (and GR8:$src1, (not (i8 (load addr:$src2)))))]>; +def BIC16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "bic.w\t{$src2, $dst}", + [(set GR16:$dst, (and GR16:$src1, (not (i16 (load addr:$src2)))))]>; let isTwoAddress = 0 in { -def BIC8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "bic.b\t{$src, $dst}", - [(store (and (load addr:$dst), (not GR8:$src)), addr:$dst)]>; -def BIC16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "bic.w\t{$src, $dst}", - [(store (and (load addr:$dst), (not GR16:$src)), addr:$dst)]>; - -def BIC8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "bic.b\t{$src, $dst}", - [(store (and (load addr:$dst), (not (i8 (load addr:$src)))), addr:$dst)]>; -def BIC16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "bic.w\t{$src, $dst}", - [(store (and (load addr:$dst), (not (i16 (load addr:$src)))), addr:$dst)]>; +def BIC8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "bic.b\t{$src, $dst}", + [(store (and (load addr:$dst), (not GR8:$src)), addr:$dst)]>; +def BIC16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "bic.w\t{$src, $dst}", + [(store (and (load addr:$dst), (not GR16:$src)), addr:$dst)]>; + +def BIC8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "bic.b\t{$src, $dst}", + [(store (and (load addr:$dst), + (not (i8 (load addr:$src)))), addr:$dst)]>; +def BIC16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "bic.w\t{$src, $dst}", + [(store (and (load addr:$dst), + (not (i16 (load addr:$src)))), addr:$dst)]>; } let isCommutable = 1 in { // X = XOR Y, Z == X = XOR Z, Y -def XOR8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "xor.b\t{$src2, $dst}", - [(set GR8:$dst, (xor GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def XOR16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "xor.w\t{$src2, $dst}", - [(set GR16:$dst, (xor GR16:$src1, GR16:$src2)), - (implicit SRW)]>; +def XOR8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "xor.b\t{$src2, $dst}", + [(set GR8:$dst, (xor GR8:$src1, GR8:$src2)), + (implicit SRW)]>; +def XOR16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "xor.w\t{$src2, $dst}", + [(set GR16:$dst, (xor GR16:$src1, GR16:$src2)), + (implicit SRW)]>; } -def XOR8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "xor.b\t{$src2, $dst}", - [(set GR8:$dst, (xor GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def XOR16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "xor.w\t{$src2, $dst}", - [(set GR16:$dst, (xor GR16:$src1, imm:$src2)), - (implicit SRW)]>; - -def XOR8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "xor.b\t{$src2, $dst}", - [(set GR8:$dst, (xor GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def XOR16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "xor.w\t{$src2, $dst}", - [(set GR16:$dst, (xor GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; +def XOR8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "xor.b\t{$src2, $dst}", + [(set GR8:$dst, (xor GR8:$src1, imm:$src2)), + (implicit SRW)]>; +def XOR16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "xor.w\t{$src2, $dst}", + [(set GR16:$dst, (xor GR16:$src1, imm:$src2)), + (implicit SRW)]>; + +def XOR8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "xor.b\t{$src2, $dst}", + [(set GR8:$dst, (xor GR8:$src1, (load addr:$src2))), + (implicit SRW)]>; +def XOR16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "xor.w\t{$src2, $dst}", + [(set GR16:$dst, (xor GR16:$src1, (load addr:$src2))), + (implicit SRW)]>; let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb, $src1 = $dst" in { -def XOR8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base), - "xor.b\t{@$base+, $dst}", []>; -def XOR16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base), - "xor.w\t{@$base+, $dst}", []>; +def XOR8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR8:$dst, GR16:$base_wb), + (ins GR8:$src1, GR16:$base), + "xor.b\t{@$base+, $dst}", []>; +def XOR16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$dst, GR16:$base_wb), + (ins GR16:$src1, GR16:$base), + "xor.w\t{@$base+, $dst}", []>; } let isTwoAddress = 0 in { -def XOR8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "xor.b\t{$src, $dst}", - [(store (xor (load addr:$dst), GR8:$src), addr:$dst), - (implicit SRW)]>; -def XOR16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "xor.w\t{$src, $dst}", - [(store (xor (load addr:$dst), GR16:$src), addr:$dst), - (implicit SRW)]>; - -def XOR8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "xor.b\t{$src, $dst}", - [(store (xor (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SRW)]>; -def XOR16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "xor.w\t{$src, $dst}", - [(store (xor (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SRW)]>; - -def XOR8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "xor.b\t{$src, $dst}", - [(store (xor (load addr:$dst), (i8 (load addr:$src))), addr:$dst), - (implicit SRW)]>; -def XOR16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "xor.w\t{$src, $dst}", - [(store (xor (load addr:$dst), (i16 (load addr:$src))), addr:$dst), - (implicit SRW)]>; +def XOR8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "xor.b\t{$src, $dst}", + [(store (xor (load addr:$dst), GR8:$src), addr:$dst), + (implicit SRW)]>; +def XOR16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "xor.w\t{$src, $dst}", + [(store (xor (load addr:$dst), GR16:$src), addr:$dst), + (implicit SRW)]>; + +def XOR8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "xor.b\t{$src, $dst}", + [(store (xor (load addr:$dst), (i8 imm:$src)), addr:$dst), + (implicit SRW)]>; +def XOR16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "xor.w\t{$src, $dst}", + [(store (xor (load addr:$dst), (i16 imm:$src)), addr:$dst), + (implicit SRW)]>; + +def XOR8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "xor.b\t{$src, $dst}", + [(store (xor (load addr:$dst), (i8 (load addr:$src))), addr:$dst), + (implicit SRW)]>; +def XOR16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "xor.w\t{$src, $dst}", + [(store (xor (load addr:$dst), (i16 (load addr:$src))), addr:$dst), + (implicit SRW)]>; } -def SUB8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "sub.b\t{$src2, $dst}", - [(set GR8:$dst, (sub GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def SUB16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "sub.w\t{$src2, $dst}", - [(set GR16:$dst, (sub GR16:$src1, GR16:$src2)), - (implicit SRW)]>; - -def SUB8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "sub.b\t{$src2, $dst}", - [(set GR8:$dst, (sub GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def SUB16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "sub.w\t{$src2, $dst}", - [(set GR16:$dst, (sub GR16:$src1, imm:$src2)), - (implicit SRW)]>; - -def SUB8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "sub.b\t{$src2, $dst}", - [(set GR8:$dst, (sub GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def SUB16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "sub.w\t{$src2, $dst}", - [(set GR16:$dst, (sub GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; +def SUB8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "sub.b\t{$src2, $dst}", + [(set GR8:$dst, (sub GR8:$src1, GR8:$src2)), + (implicit SRW)]>; +def SUB16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "sub.w\t{$src2, $dst}", + [(set GR16:$dst, (sub GR16:$src1, GR16:$src2)), + (implicit SRW)]>; + +def SUB8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "sub.b\t{$src2, $dst}", + [(set GR8:$dst, (sub GR8:$src1, imm:$src2)), + (implicit SRW)]>; +def SUB16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "sub.w\t{$src2, $dst}", + [(set GR16:$dst, (sub GR16:$src1, imm:$src2)), + (implicit SRW)]>; + +def SUB8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "sub.b\t{$src2, $dst}", + [(set GR8:$dst, (sub GR8:$src1, (load addr:$src2))), + (implicit SRW)]>; +def SUB16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "sub.w\t{$src2, $dst}", + [(set GR16:$dst, (sub GR16:$src1, (load addr:$src2))), + (implicit SRW)]>; let mayLoad = 1, hasExtraDefRegAllocReq = 1, Constraints = "$base = $base_wb, $src1 = $dst" in { -def SUB8rm_POST : Pseudo<(outs GR8:$dst, GR16:$base_wb), (ins GR8:$src1, GR16:$base), - "sub.b\t{@$base+, $dst}", []>; -def SUB16rm_POST : Pseudo<(outs GR16:$dst, GR16:$base_wb), (ins GR16:$src1, GR16:$base), +def SUB8rm_POST : IForm8<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR8:$dst, GR16:$base_wb), + (ins GR8:$src1, GR16:$base), + "sub.b\t{@$base+, $dst}", []>; +def SUB16rm_POST : IForm16<0x0, DstReg, SrcPostInc, Size2Bytes, + (outs GR16:$dst, GR16:$base_wb), + (ins GR16:$src1, GR16:$base), "sub.w\t{@$base+, $dst}", []>; } let isTwoAddress = 0 in { -def SUB8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "sub.b\t{$src, $dst}", - [(store (sub (load addr:$dst), GR8:$src), addr:$dst), - (implicit SRW)]>; -def SUB16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "sub.w\t{$src, $dst}", - [(store (sub (load addr:$dst), GR16:$src), addr:$dst), - (implicit SRW)]>; - -def SUB8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "sub.b\t{$src, $dst}", - [(store (sub (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SRW)]>; -def SUB16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "sub.w\t{$src, $dst}", - [(store (sub (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SRW)]>; - -def SUB8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "sub.b\t{$src, $dst}", - [(store (sub (load addr:$dst), (i8 (load addr:$src))), addr:$dst), - (implicit SRW)]>; -def SUB16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "sub.w\t{$src, $dst}", - [(store (sub (load addr:$dst), (i16 (load addr:$src))), addr:$dst), - (implicit SRW)]>; +def SUB8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "sub.b\t{$src, $dst}", + [(store (sub (load addr:$dst), GR8:$src), addr:$dst), + (implicit SRW)]>; +def SUB16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "sub.w\t{$src, $dst}", + [(store (sub (load addr:$dst), GR16:$src), addr:$dst), + (implicit SRW)]>; + +def SUB8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "sub.b\t{$src, $dst}", + [(store (sub (load addr:$dst), (i8 imm:$src)), addr:$dst), + (implicit SRW)]>; +def SUB16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "sub.w\t{$src, $dst}", + [(store (sub (load addr:$dst), (i16 imm:$src)), addr:$dst), + (implicit SRW)]>; + +def SUB8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "sub.b\t{$src, $dst}", + [(store (sub (load addr:$dst), + (i8 (load addr:$src))), addr:$dst), + (implicit SRW)]>; +def SUB16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "sub.w\t{$src, $dst}", + [(store (sub (load addr:$dst), + (i16 (load addr:$src))), addr:$dst), + (implicit SRW)]>; } let Uses = [SRW] in { -def SBC8rr : Pseudo<(outs GR8:$dst), (ins GR8:$src1, GR8:$src2), - "subc.b\t{$src2, $dst}", - [(set GR8:$dst, (sube GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def SBC16rr : Pseudo<(outs GR16:$dst), (ins GR16:$src1, GR16:$src2), - "subc.w\t{$src2, $dst}", - [(set GR16:$dst, (sube GR16:$src1, GR16:$src2)), - (implicit SRW)]>; - -def SBC8ri : Pseudo<(outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), - "subc.b\t{$src2, $dst}", - [(set GR8:$dst, (sube GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def SBC16ri : Pseudo<(outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), - "subc.w\t{$src2, $dst}", - [(set GR16:$dst, (sube GR16:$src1, imm:$src2)), - (implicit SRW)]>; - -def SBC8rm : Pseudo<(outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), - "subc.b\t{$src2, $dst}", - [(set GR8:$dst, (sube GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def SBC16rm : Pseudo<(outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), - "subc.w\t{$src2, $dst}", - [(set GR16:$dst, (sube GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; +def SBC8rr : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src1, GR8:$src2), + "subc.b\t{$src2, $dst}", + [(set GR8:$dst, (sube GR8:$src1, GR8:$src2)), + (implicit SRW)]>; +def SBC16rr : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src1, GR16:$src2), + "subc.w\t{$src2, $dst}", + [(set GR16:$dst, (sube GR16:$src1, GR16:$src2)), + (implicit SRW)]>; + +def SBC8ri : I8ri<0x0, + (outs GR8:$dst), (ins GR8:$src1, i8imm:$src2), + "subc.b\t{$src2, $dst}", + [(set GR8:$dst, (sube GR8:$src1, imm:$src2)), + (implicit SRW)]>; +def SBC16ri : I16ri<0x0, + (outs GR16:$dst), (ins GR16:$src1, i16imm:$src2), + "subc.w\t{$src2, $dst}", + [(set GR16:$dst, (sube GR16:$src1, imm:$src2)), + (implicit SRW)]>; + +def SBC8rm : I8rm<0x0, + (outs GR8:$dst), (ins GR8:$src1, memsrc:$src2), + "subc.b\t{$src2, $dst}", + [(set GR8:$dst, (sube GR8:$src1, (load addr:$src2))), + (implicit SRW)]>; +def SBC16rm : I16rm<0x0, + (outs GR16:$dst), (ins GR16:$src1, memsrc:$src2), + "subc.w\t{$src2, $dst}", + [(set GR16:$dst, (sube GR16:$src1, (load addr:$src2))), + (implicit SRW)]>; let isTwoAddress = 0 in { -def SBC8mr : Pseudo<(outs), (ins memdst:$dst, GR8:$src), - "subc.b\t{$src, $dst}", - [(store (sube (load addr:$dst), GR8:$src), addr:$dst), - (implicit SRW)]>; -def SBC16mr : Pseudo<(outs), (ins memdst:$dst, GR16:$src), - "subc.w\t{$src, $dst}", - [(store (sube (load addr:$dst), GR16:$src), addr:$dst), - (implicit SRW)]>; - -def SBC8mi : Pseudo<(outs), (ins memdst:$dst, i8imm:$src), - "subc.b\t{$src, $dst}", - [(store (sube (load addr:$dst), (i8 imm:$src)), addr:$dst), - (implicit SRW)]>; -def SBC16mi : Pseudo<(outs), (ins memdst:$dst, i16imm:$src), - "subc.w\t{$src, $dst}", - [(store (sube (load addr:$dst), (i16 imm:$src)), addr:$dst), - (implicit SRW)]>; - -def SBC8mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "subc.b\t{$src, $dst}", - [(store (sube (load addr:$dst), (i8 (load addr:$src))), addr:$dst), - (implicit SRW)]>; -def SBC16mm : Pseudo<(outs), (ins memdst:$dst, memsrc:$src), - "subc.w\t{$src, $dst}", - [(store (sube (load addr:$dst), (i16 (load addr:$src))), addr:$dst), - (implicit SRW)]>; +def SBC8mr : I8mr<0x0, + (outs), (ins memdst:$dst, GR8:$src), + "subc.b\t{$src, $dst}", + [(store (sube (load addr:$dst), GR8:$src), addr:$dst), + (implicit SRW)]>; +def SBC16mr : I16mr<0x0, + (outs), (ins memdst:$dst, GR16:$src), + "subc.w\t{$src, $dst}", + [(store (sube (load addr:$dst), GR16:$src), addr:$dst), + (implicit SRW)]>; + +def SBC8mi : I8mi<0x0, + (outs), (ins memdst:$dst, i8imm:$src), + "subc.b\t{$src, $dst}", + [(store (sube (load addr:$dst), (i8 imm:$src)), addr:$dst), + (implicit SRW)]>; +def SBC16mi : I16mi<0x0, + (outs), (ins memdst:$dst, i16imm:$src), + "subc.w\t{$src, $dst}", + [(store (sube (load addr:$dst), (i16 imm:$src)), addr:$dst), + (implicit SRW)]>; + +def SBC8mm : I8mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "subc.b\t{$src, $dst}", + [(store (sube (load addr:$dst), + (i8 (load addr:$src))), addr:$dst), + (implicit SRW)]>; +def SBC16mm : I16mm<0x0, + (outs), (ins memdst:$dst, memsrc:$src), + "subc.w\t{$src, $dst}", + [(store (sube (load addr:$dst), + (i16 (load addr:$src))), addr:$dst), + (implicit SRW)]>; } } // Uses = [SRW] -// FIXME: Provide proper encoding! -def SAR8r1 : Pseudo<(outs GR8:$dst), (ins GR8:$src), - "rra.b\t$dst", - [(set GR8:$dst, (MSP430rra GR8:$src)), - (implicit SRW)]>; -def SAR16r1 : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "rra.w\t$dst", - [(set GR16:$dst, (MSP430rra GR16:$src)), - (implicit SRW)]>; - -def SHL8r1 : Pseudo<(outs GR8:$dst), (ins GR8:$src), - "rla.b\t$dst", - [(set GR8:$dst, (MSP430rla GR8:$src)), - (implicit SRW)]>; -def SHL16r1 : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "rla.w\t$dst", - [(set GR16:$dst, (MSP430rla GR16:$src)), - (implicit SRW)]>; +// FIXME: memory variant! +def SAR8r1 : II8r<0x0, + (outs GR8:$dst), (ins GR8:$src), + "rra.b\t$dst", + [(set GR8:$dst, (MSP430rra GR8:$src)), + (implicit SRW)]>; +def SAR16r1 : II16r<0x0, + (outs GR16:$dst), (ins GR16:$src), + "rra.w\t$dst", + [(set GR16:$dst, (MSP430rra GR16:$src)), + (implicit SRW)]>; + +def SHL8r1 : I8rr<0x0, + (outs GR8:$dst), (ins GR8:$src), + "rla.b\t$dst", + [(set GR8:$dst, (MSP430rla GR8:$src)), + (implicit SRW)]>; +def SHL16r1 : I16rr<0x0, + (outs GR16:$dst), (ins GR16:$src), + "rla.w\t$dst", + [(set GR16:$dst, (MSP430rla GR16:$src)), + (implicit SRW)]>; def SAR8r1c : Pseudo<(outs GR8:$dst), (ins GR8:$src), "clrc\n\t" @@ -799,121 +959,154 @@ def SAR16r1c : Pseudo<(outs GR16:$dst), (ins GR16:$src), [(set GR16:$dst, (MSP430rrc GR16:$src)), (implicit SRW)]>; -def SEXT16r : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "sxt\t$dst", - [(set GR16:$dst, (sext_inreg GR16:$src, i8)), - (implicit SRW)]>; +// FIXME: Memory sext's ? +def SEXT16r : II16r<0x0, + (outs GR16:$dst), (ins GR16:$src), + "sxt\t$dst", + [(set GR16:$dst, (sext_inreg GR16:$src, i8)), + (implicit SRW)]>; } // Defs = [SRW] -def ZEXT16r : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "mov.b\t{$src, $dst}", - [(set GR16:$dst, (zext (trunc GR16:$src)))]>; +def ZEXT16r : I8rr<0x0, + (outs GR16:$dst), (ins GR16:$src), + "mov.b\t{$src, $dst}", + [(set GR16:$dst, (zext (trunc GR16:$src)))]>; -def SWPB16r : Pseudo<(outs GR16:$dst), (ins GR16:$src), - "swpb\t$dst", - [(set GR16:$dst, (bswap GR16:$src))]>; +// FIXME: Memory bitswaps? +def SWPB16r : II16r<0x0, + (outs GR16:$dst), (ins GR16:$src), + "swpb\t$dst", + [(set GR16:$dst, (bswap GR16:$src))]>; } // isTwoAddress = 1 // Integer comparisons let Defs = [SRW] in { -def CMP8rr : Pseudo<(outs), (ins GR8:$src1, GR8:$src2), - "cmp.b\t{$src2, $src1}", - [(MSP430cmp GR8:$src1, GR8:$src2), (implicit SRW)]>; -def CMP16rr : Pseudo<(outs), (ins GR16:$src1, GR16:$src2), - "cmp.w\t{$src2, $src1}", - [(MSP430cmp GR16:$src1, GR16:$src2), (implicit SRW)]>; - -def CMP8ri : Pseudo<(outs), (ins GR8:$src1, i8imm:$src2), +def CMP8rr : I8rr<0x0, + (outs), (ins GR8:$src1, GR8:$src2), + "cmp.b\t{$src2, $src1}", + [(MSP430cmp GR8:$src1, GR8:$src2), (implicit SRW)]>; +def CMP16rr : I16rr<0x0, + (outs), (ins GR16:$src1, GR16:$src2), + "cmp.w\t{$src2, $src1}", + [(MSP430cmp GR16:$src1, GR16:$src2), (implicit SRW)]>; + +def CMP8ri : I8ri<0x0, + (outs), (ins GR8:$src1, i8imm:$src2), "cmp.b\t{$src2, $src1}", [(MSP430cmp GR8:$src1, imm:$src2), (implicit SRW)]>; -def CMP16ri : Pseudo<(outs), (ins GR16:$src1, i16imm:$src2), - "cmp.w\t{$src2, $src1}", - [(MSP430cmp GR16:$src1, imm:$src2), (implicit SRW)]>; - -def CMP8mi : Pseudo<(outs), (ins memsrc:$src1, i8imm:$src2), - "cmp.b\t{$src2, $src1}", - [(MSP430cmp (load addr:$src1), - (i8 imm:$src2)), (implicit SRW)]>; -def CMP16mi : Pseudo<(outs), (ins memsrc:$src1, i16imm:$src2), - "cmp.w\t{$src2, $src1}", - [(MSP430cmp (load addr:$src1), - (i16 imm:$src2)), (implicit SRW)]>; - -def CMP8rm : Pseudo<(outs), (ins GR8:$src1, memsrc:$src2), - "cmp.b\t{$src2, $src1}", - [(MSP430cmp GR8:$src1, (load addr:$src2)), (implicit SRW)]>; -def CMP16rm : Pseudo<(outs), (ins GR16:$src1, memsrc:$src2), - "cmp.w\t{$src2, $src1}", - [(MSP430cmp GR16:$src1, (load addr:$src2)), (implicit SRW)]>; - -def CMP8mr : Pseudo<(outs), (ins memsrc:$src1, GR8:$src2), - "cmp.b\t{$src2, $src1}", - [(MSP430cmp (load addr:$src1), GR8:$src2), (implicit SRW)]>; -def CMP16mr : Pseudo<(outs), (ins memsrc:$src1, GR16:$src2), - "cmp.w\t{$src2, $src1}", - [(MSP430cmp (load addr:$src1), GR16:$src2), (implicit SRW)]>; +def CMP16ri : I16ri<0x0, + (outs), (ins GR16:$src1, i16imm:$src2), + "cmp.w\t{$src2, $src1}", + [(MSP430cmp GR16:$src1, imm:$src2), (implicit SRW)]>; + +def CMP8mi : I8mi<0x0, + (outs), (ins memsrc:$src1, i8imm:$src2), + "cmp.b\t{$src2, $src1}", + [(MSP430cmp (load addr:$src1), + (i8 imm:$src2)), (implicit SRW)]>; +def CMP16mi : I16mi<0x0, + (outs), (ins memsrc:$src1, i16imm:$src2), + "cmp.w\t{$src2, $src1}", + [(MSP430cmp (load addr:$src1), + (i16 imm:$src2)), (implicit SRW)]>; + +def CMP8rm : I8rm<0x0, + (outs), (ins GR8:$src1, memsrc:$src2), + "cmp.b\t{$src2, $src1}", + [(MSP430cmp GR8:$src1, (load addr:$src2)), + (implicit SRW)]>; +def CMP16rm : I16rm<0x0, + (outs), (ins GR16:$src1, memsrc:$src2), + "cmp.w\t{$src2, $src1}", + [(MSP430cmp GR16:$src1, (load addr:$src2)), + (implicit SRW)]>; + +def CMP8mr : I8mr<0x0, + (outs), (ins memsrc:$src1, GR8:$src2), + "cmp.b\t{$src2, $src1}", + [(MSP430cmp (load addr:$src1), GR8:$src2), + (implicit SRW)]>; +def CMP16mr : I16mr<0x0, + (outs), (ins memsrc:$src1, GR16:$src2), + "cmp.w\t{$src2, $src1}", + [(MSP430cmp (load addr:$src1), GR16:$src2), + (implicit SRW)]>; // BIT TESTS, just sets condition codes // Note that the C condition is set differently than when using CMP. let isCommutable = 1 in { -def BIT8rr : Pseudo<(outs), (ins GR8:$src1, GR8:$src2), - "bit.b\t{$src2, $src1}", - [(MSP430cmp 0, (and_su GR8:$src1, GR8:$src2)), - (implicit SRW)]>; -def BIT16rr : Pseudo<(outs), (ins GR16:$src1, GR16:$src2), - "bit.w\t{$src2, $src1}", - [(MSP430cmp 0, (and_su GR16:$src1, GR16:$src2)), - (implicit SRW)]>; +def BIT8rr : I8rr<0x0, + (outs), (ins GR8:$src1, GR8:$src2), + "bit.b\t{$src2, $src1}", + [(MSP430cmp (and_su GR8:$src1, GR8:$src2), 0), + (implicit SRW)]>; +def BIT16rr : I16rr<0x0, + (outs), (ins GR16:$src1, GR16:$src2), + "bit.w\t{$src2, $src1}", + [(MSP430cmp (and_su GR16:$src1, GR16:$src2), 0), + (implicit SRW)]>; } -def BIT8ri : Pseudo<(outs), (ins GR8:$src1, i8imm:$src2), - "bit.b\t{$src2, $src1}", - [(MSP430cmp 0, (and_su GR8:$src1, imm:$src2)), - (implicit SRW)]>; -def BIT16ri : Pseudo<(outs), (ins GR16:$src1, i16imm:$src2), - "bit.w\t{$src2, $src1}", - [(MSP430cmp 0, (and_su GR16:$src1, imm:$src2)), - (implicit SRW)]>; - -def BIT8rm : Pseudo<(outs), (ins GR8:$src1, memdst:$src2), - "bit.b\t{$src2, $src1}", - [(MSP430cmp 0, (and_su GR8:$src1, (load addr:$src2))), - (implicit SRW)]>; -def BIT16rm : Pseudo<(outs), (ins GR16:$src1, memdst:$src2), - "bit.w\t{$src2, $src1}", - [(MSP430cmp 0, (and_su GR16:$src1, (load addr:$src2))), - (implicit SRW)]>; - -def BIT8mr : Pseudo<(outs), (ins memsrc:$src1, GR8:$src2), - "bit.b\t{$src2, $src1}", - [(MSP430cmp 0, (and_su (load addr:$src1), GR8:$src2)), - (implicit SRW)]>; -def BIT16mr : Pseudo<(outs), (ins memsrc:$src1, GR16:$src2), - "bit.w\t{$src2, $src1}", - [(MSP430cmp 0, (and_su (load addr:$src1), GR16:$src2)), - (implicit SRW)]>; - -def BIT8mi : Pseudo<(outs), (ins memsrc:$src1, i8imm:$src2), - "bit.b\t{$src2, $src1}", - [(MSP430cmp 0, (and_su (load addr:$src1), (i8 imm:$src2))), - (implicit SRW)]>; -def BIT16mi : Pseudo<(outs), (ins memsrc:$src1, i16imm:$src2), - "bit.w\t{$src2, $src1}", - [(MSP430cmp 0, (and_su (load addr:$src1), (i16 imm:$src2))), - (implicit SRW)]>; - -def BIT8mm : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2), - "bit.b\t{$src2, $src1}", - [(MSP430cmp 0, (and_su (i8 (load addr:$src1)), - (load addr:$src2))), - (implicit SRW)]>; -def BIT16mm : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2), - "bit.w\t{$src2, $src1}", - [(MSP430cmp 0, (and_su (i16 (load addr:$src1)), - (load addr:$src2))), +def BIT8ri : I8ri<0x0, + (outs), (ins GR8:$src1, i8imm:$src2), + "bit.b\t{$src2, $src1}", + [(MSP430cmp (and_su GR8:$src1, imm:$src2), 0), + (implicit SRW)]>; +def BIT16ri : I16ri<0x0, + (outs), (ins GR16:$src1, i16imm:$src2), + "bit.w\t{$src2, $src1}", + [(MSP430cmp (and_su GR16:$src1, imm:$src2), 0), + (implicit SRW)]>; + +def BIT8rm : I8rm<0x0, + (outs), (ins GR8:$src1, memdst:$src2), + "bit.b\t{$src2, $src1}", + [(MSP430cmp (and_su GR8:$src1, (load addr:$src2)), 0), + (implicit SRW)]>; +def BIT16rm : I16rm<0x0, + (outs), (ins GR16:$src1, memdst:$src2), + "bit.w\t{$src2, $src1}", + [(MSP430cmp (and_su GR16:$src1, (load addr:$src2)), 0), + (implicit SRW)]>; + +def BIT8mr : I8mr<0x0, + (outs), (ins memsrc:$src1, GR8:$src2), + "bit.b\t{$src2, $src1}", + [(MSP430cmp (and_su (load addr:$src1), GR8:$src2), 0), + (implicit SRW)]>; +def BIT16mr : I16mr<0x0, + (outs), (ins memsrc:$src1, GR16:$src2), + "bit.w\t{$src2, $src1}", + [(MSP430cmp (and_su (load addr:$src1), GR16:$src2), 0), + (implicit SRW)]>; + +def BIT8mi : I8mi<0x0, + (outs), (ins memsrc:$src1, i8imm:$src2), + "bit.b\t{$src2, $src1}", + [(MSP430cmp (and_su (load addr:$src1), (i8 imm:$src2)), 0), + (implicit SRW)]>; +def BIT16mi : I16mi<0x0, + (outs), (ins memsrc:$src1, i16imm:$src2), + "bit.w\t{$src2, $src1}", + [(MSP430cmp (and_su (load addr:$src1), (i16 imm:$src2)), 0), + (implicit SRW)]>; + +def BIT8mm : I8mm<0x0, + (outs), (ins memsrc:$src1, memsrc:$src2), + "bit.b\t{$src2, $src1}", + [(MSP430cmp (and_su (i8 (load addr:$src1)), + (load addr:$src2)), + 0), (implicit SRW)]>; +def BIT16mm : I16mm<0x0, + (outs), (ins memsrc:$src1, memsrc:$src2), + "bit.w\t{$src2, $src1}", + [(MSP430cmp (and_su (i16 (load addr:$src1)), + (load addr:$src2)), + 0), + (implicit SRW)]>; } // Defs = [SRW] //===----------------------------------------------------------------------===// @@ -923,7 +1116,8 @@ def BIT16mm : Pseudo<(outs), (ins memsrc:$src1, memsrc:$src2), def : Pat<(extloadi16i8 addr:$src), (MOVZX16rm8 addr:$src)>; // anyext -def : Pat<(anyext addr:$src), (MOVZX16rr8 GR8:$src)>; +def : Pat<(i16 (anyext GR8:$src)), + (SUBREG_TO_REG (i16 0), GR8:$src, subreg_8bit)>; // truncs def : Pat<(i8 (trunc GR16:$src)), @@ -996,6 +1190,6 @@ def : Pat<(store (subc (load addr:$dst), (i8 (load addr:$src))), addr:$dst), // peephole patterns def : Pat<(and GR16:$src, 255), (ZEXT16r GR16:$src)>; -def : Pat<(MSP430cmp 0, (trunc (and_su GR16:$src1, GR16:$src2))), +def : Pat<(MSP430cmp (trunc (and_su GR16:$src1, GR16:$src2)), 0), (BIT8rr (EXTRACT_SUBREG GR16:$src1, subreg_8bit), (EXTRACT_SUBREG GR16:$src2, subreg_8bit))>; diff --git a/lib/Target/MSP430/MSP430TargetMachine.cpp b/lib/Target/MSP430/MSP430TargetMachine.cpp index 14db406..a0dbac2 100644 --- a/lib/Target/MSP430/MSP430TargetMachine.cpp +++ b/lib/Target/MSP430/MSP430TargetMachine.cpp @@ -44,3 +44,9 @@ bool MSP430TargetMachine::addInstSelector(PassManagerBase &PM, return false; } +bool MSP430TargetMachine::addPreEmitPass(PassManagerBase &PM, + CodeGenOpt::Level OptLevel) { + // Must run branch selection immediately preceding the asm printer. + PM.add(createMSP430BranchSelectionPass()); + return false; +} diff --git a/lib/Target/MSP430/MSP430TargetMachine.h b/lib/Target/MSP430/MSP430TargetMachine.h index d386140..d93ac5c 100644 --- a/lib/Target/MSP430/MSP430TargetMachine.h +++ b/lib/Target/MSP430/MSP430TargetMachine.h @@ -55,6 +55,7 @@ public: } virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel); }; // MSP430TargetMachine. } // end namespace llvm diff --git a/lib/Target/MSP430/Makefile b/lib/Target/MSP430/Makefile index 4b18bc9..11195a4 100644 --- a/lib/Target/MSP430/Makefile +++ b/lib/Target/MSP430/Makefile @@ -6,9 +6,11 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## + LEVEL = ../../.. LIBRARYNAME = LLVMMSP430CodeGen TARGET = MSP430 +CXXFLAGS = -fno-rtti # Make sure that tblgen is run, first thing. BUILT_SOURCES = MSP430GenRegisterInfo.h.inc MSP430GenRegisterNames.inc \ diff --git a/lib/Target/MSP430/TargetInfo/Makefile b/lib/Target/MSP430/TargetInfo/Makefile index abb08f2..d17fa7b 100644 --- a/lib/Target/MSP430/TargetInfo/Makefile +++ b/lib/Target/MSP430/TargetInfo/Makefile @@ -8,6 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../../.. LIBRARYNAME = LLVMMSP430Info +CXXFLAGS = -fno-rtti # Hack: we need to include 'main' target directory to grab private headers CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. |