You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
27
external/llvm/lib/Target/MSP430/CMakeLists.txt
vendored
27
external/llvm/lib/Target/MSP430/CMakeLists.txt
vendored
@ -1,27 +0,0 @@
|
||||
set(LLVM_TARGET_DEFINITIONS MSP430.td)
|
||||
|
||||
tablegen(LLVM MSP430GenRegisterInfo.inc -gen-register-info)
|
||||
tablegen(LLVM MSP430GenInstrInfo.inc -gen-instr-info)
|
||||
tablegen(LLVM MSP430GenAsmWriter.inc -gen-asm-writer)
|
||||
tablegen(LLVM MSP430GenDAGISel.inc -gen-dag-isel)
|
||||
tablegen(LLVM MSP430GenCallingConv.inc -gen-callingconv)
|
||||
tablegen(LLVM MSP430GenSubtargetInfo.inc -gen-subtarget)
|
||||
add_public_tablegen_target(MSP430CommonTableGen)
|
||||
|
||||
add_llvm_target(MSP430CodeGen
|
||||
MSP430BranchSelector.cpp
|
||||
MSP430ISelDAGToDAG.cpp
|
||||
MSP430ISelLowering.cpp
|
||||
MSP430InstrInfo.cpp
|
||||
MSP430FrameLowering.cpp
|
||||
MSP430MachineFunctionInfo.cpp
|
||||
MSP430RegisterInfo.cpp
|
||||
MSP430Subtarget.cpp
|
||||
MSP430TargetMachine.cpp
|
||||
MSP430AsmPrinter.cpp
|
||||
MSP430MCInstLower.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(InstPrinter)
|
||||
add_subdirectory(TargetInfo)
|
||||
add_subdirectory(MCTargetDesc)
|
@ -1,3 +0,0 @@
|
||||
add_llvm_library(LLVMMSP430AsmPrinter
|
||||
MSP430InstPrinter.cpp
|
||||
)
|
@ -1,23 +0,0 @@
|
||||
;===- ./lib/Target/MSP430/InstPrinter/LLVMBuild.txt ------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Library
|
||||
name = MSP430AsmPrinter
|
||||
parent = MSP430
|
||||
required_libraries = MC Support
|
||||
add_to_library_groups = MSP430
|
@ -1,116 +0,0 @@
|
||||
//===-- MSP430InstPrinter.cpp - Convert MSP430 MCInst to assembly syntax --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class prints an MSP430 MCInst to a .s file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MSP430InstPrinter.h"
|
||||
#include "MSP430.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "asm-printer"
|
||||
|
||||
|
||||
// Include the auto-generated portion of the assembly writer.
|
||||
#include "MSP430GenAsmWriter.inc"
|
||||
|
||||
void MSP430InstPrinter::printInst(const MCInst *MI, raw_ostream &O,
|
||||
StringRef Annot, const MCSubtargetInfo &STI) {
|
||||
printInstruction(MI, O);
|
||||
printAnnotation(O, Annot);
|
||||
}
|
||||
|
||||
void MSP430InstPrinter::printPCRelImmOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
const MCOperand &Op = MI->getOperand(OpNo);
|
||||
if (Op.isImm())
|
||||
O << Op.getImm();
|
||||
else {
|
||||
assert(Op.isExpr() && "unknown pcrel immediate operand");
|
||||
Op.getExpr()->print(O, &MAI);
|
||||
}
|
||||
}
|
||||
|
||||
void MSP430InstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O, const char *Modifier) {
|
||||
assert((Modifier == nullptr || Modifier[0] == 0) && "No modifiers supported");
|
||||
const MCOperand &Op = MI->getOperand(OpNo);
|
||||
if (Op.isReg()) {
|
||||
O << getRegisterName(Op.getReg());
|
||||
} else if (Op.isImm()) {
|
||||
O << '#' << Op.getImm();
|
||||
} else {
|
||||
assert(Op.isExpr() && "unknown operand kind in printOperand");
|
||||
O << '#';
|
||||
Op.getExpr()->print(O, &MAI);
|
||||
}
|
||||
}
|
||||
|
||||
void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O,
|
||||
const char *Modifier) {
|
||||
const MCOperand &Base = MI->getOperand(OpNo);
|
||||
const MCOperand &Disp = MI->getOperand(OpNo+1);
|
||||
|
||||
// Print displacement first
|
||||
|
||||
// If the global address expression is a part of displacement field with a
|
||||
// register base, we should not emit any prefix symbol here, e.g.
|
||||
// mov.w &foo, r1
|
||||
// vs
|
||||
// mov.w glb(r1), r2
|
||||
// Otherwise (!) msp430-as will silently miscompile the output :(
|
||||
if (!Base.getReg())
|
||||
O << '&';
|
||||
|
||||
if (Disp.isExpr())
|
||||
Disp.getExpr()->print(O, &MAI);
|
||||
else {
|
||||
assert(Disp.isImm() && "Expected immediate in displacement field");
|
||||
O << Disp.getImm();
|
||||
}
|
||||
|
||||
// Print register base field
|
||||
if (Base.getReg())
|
||||
O << '(' << getRegisterName(Base.getReg()) << ')';
|
||||
}
|
||||
|
||||
void MSP430InstPrinter::printCCOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
unsigned CC = MI->getOperand(OpNo).getImm();
|
||||
|
||||
switch (CC) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported CC code");
|
||||
case MSP430CC::COND_E:
|
||||
O << "eq";
|
||||
break;
|
||||
case MSP430CC::COND_NE:
|
||||
O << "ne";
|
||||
break;
|
||||
case MSP430CC::COND_HS:
|
||||
O << "hs";
|
||||
break;
|
||||
case MSP430CC::COND_LO:
|
||||
O << "lo";
|
||||
break;
|
||||
case MSP430CC::COND_GE:
|
||||
O << "ge";
|
||||
break;
|
||||
case MSP430CC::COND_L:
|
||||
O << 'l';
|
||||
break;
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
//= MSP430InstPrinter.h - Convert MSP430 MCInst to assembly syntax -*- C++ -*-//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This class prints a MSP430 MCInst to a .s file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_MSP430_INSTPRINTER_MSP430INSTPRINTER_H
|
||||
#define LLVM_LIB_TARGET_MSP430_INSTPRINTER_MSP430INSTPRINTER_H
|
||||
|
||||
#include "llvm/MC/MCInstPrinter.h"
|
||||
|
||||
namespace llvm {
|
||||
class MSP430InstPrinter : public MCInstPrinter {
|
||||
public:
|
||||
MSP430InstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
|
||||
const MCRegisterInfo &MRI)
|
||||
: MCInstPrinter(MAI, MII, MRI) {}
|
||||
|
||||
void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot,
|
||||
const MCSubtargetInfo &STI) override;
|
||||
|
||||
// Autogenerated by tblgen.
|
||||
void printInstruction(const MCInst *MI, raw_ostream &O);
|
||||
static const char *getRegisterName(unsigned RegNo);
|
||||
|
||||
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
|
||||
const char *Modifier = nullptr);
|
||||
void printPCRelImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||
void printSrcMemOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O,
|
||||
const char *Modifier = nullptr);
|
||||
void printCCOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
32
external/llvm/lib/Target/MSP430/LLVMBuild.txt
vendored
32
external/llvm/lib/Target/MSP430/LLVMBuild.txt
vendored
@ -1,32 +0,0 @@
|
||||
;===- ./lib/Target/MSP430/LLVMBuild.txt ------------------------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[common]
|
||||
subdirectories = InstPrinter MCTargetDesc TargetInfo
|
||||
|
||||
[component_0]
|
||||
type = TargetGroup
|
||||
name = MSP430
|
||||
parent = Target
|
||||
has_asmprinter = 1
|
||||
|
||||
[component_1]
|
||||
type = Library
|
||||
name = MSP430CodeGen
|
||||
parent = MSP430
|
||||
required_libraries = AsmPrinter CodeGen Core MC MSP430AsmPrinter MSP430Desc MSP430Info SelectionDAG Support Target
|
||||
add_to_library_groups = MSP430
|
@ -1,4 +0,0 @@
|
||||
add_llvm_library(LLVMMSP430Desc
|
||||
MSP430MCTargetDesc.cpp
|
||||
MSP430MCAsmInfo.cpp
|
||||
)
|
@ -1,23 +0,0 @@
|
||||
;===- ./lib/Target/MSP430/MCTargetDesc/LLVMBuild.txt -----------*- Conf -*--===;
|
||||
;
|
||||
; The LLVM Compiler Infrastructure
|
||||
;
|
||||
; This file is distributed under the University of Illinois Open Source
|
||||
; License. See LICENSE.TXT for details.
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
;
|
||||
; This is an LLVMBuild description file for the components in this subdirectory.
|
||||
;
|
||||
; For more information on the LLVMBuild system, please see:
|
||||
;
|
||||
; http://llvm.org/docs/LLVMBuild.html
|
||||
;
|
||||
;===------------------------------------------------------------------------===;
|
||||
|
||||
[component_0]
|
||||
type = Library
|
||||
name = MSP430Desc
|
||||
parent = MSP430
|
||||
required_libraries = MC MSP430AsmPrinter MSP430Info Support
|
||||
add_to_library_groups = MSP430
|
@ -1,26 +0,0 @@
|
||||
//===-- MSP430MCAsmInfo.cpp - MSP430 asm properties -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the declarations of the MSP430MCAsmInfo properties.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MSP430MCAsmInfo.h"
|
||||
using namespace llvm;
|
||||
|
||||
void MSP430MCAsmInfo::anchor() { }
|
||||
|
||||
MSP430MCAsmInfo::MSP430MCAsmInfo(const Triple &TT) {
|
||||
CodePointerSize = CalleeSaveStackSlotSize = 2;
|
||||
|
||||
CommentString = ";";
|
||||
|
||||
AlignmentIsInBytes = false;
|
||||
UsesELFSectionDirectiveForBSS = true;
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
//===-- MSP430MCAsmInfo.h - MSP430 asm properties --------------*- 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 the declaration of the MSP430MCAsmInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_MSP430_MCTARGETDESC_MSP430MCASMINFO_H
|
||||
#define LLVM_LIB_TARGET_MSP430_MCTARGETDESC_MSP430MCASMINFO_H
|
||||
|
||||
#include "llvm/MC/MCAsmInfoELF.h"
|
||||
|
||||
namespace llvm {
|
||||
class Triple;
|
||||
|
||||
class MSP430MCAsmInfo : public MCAsmInfoELF {
|
||||
void anchor() override;
|
||||
|
||||
public:
|
||||
explicit MSP430MCAsmInfo(const Triple &TT);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
@ -1,79 +0,0 @@
|
||||
//===-- MSP430MCTargetDesc.cpp - MSP430 Target Descriptions ---------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides MSP430 specific target descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MSP430MCTargetDesc.h"
|
||||
#include "InstPrinter/MSP430InstPrinter.h"
|
||||
#include "MSP430MCAsmInfo.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
#define GET_INSTRINFO_MC_DESC
|
||||
#include "MSP430GenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_MC_DESC
|
||||
#include "MSP430GenSubtargetInfo.inc"
|
||||
|
||||
#define GET_REGINFO_MC_DESC
|
||||
#include "MSP430GenRegisterInfo.inc"
|
||||
|
||||
static MCInstrInfo *createMSP430MCInstrInfo() {
|
||||
MCInstrInfo *X = new MCInstrInfo();
|
||||
InitMSP430MCInstrInfo(X);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCRegisterInfo *createMSP430MCRegisterInfo(const Triple &TT) {
|
||||
MCRegisterInfo *X = new MCRegisterInfo();
|
||||
InitMSP430MCRegisterInfo(X, MSP430::PC);
|
||||
return X;
|
||||
}
|
||||
|
||||
static MCSubtargetInfo *
|
||||
createMSP430MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) {
|
||||
return createMSP430MCSubtargetInfoImpl(TT, CPU, FS);
|
||||
}
|
||||
|
||||
static MCInstPrinter *createMSP430MCInstPrinter(const Triple &T,
|
||||
unsigned SyntaxVariant,
|
||||
const MCAsmInfo &MAI,
|
||||
const MCInstrInfo &MII,
|
||||
const MCRegisterInfo &MRI) {
|
||||
if (SyntaxVariant == 0)
|
||||
return new MSP430InstPrinter(MAI, MII, MRI);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" void LLVMInitializeMSP430TargetMC() {
|
||||
// Register the MC asm info.
|
||||
RegisterMCAsmInfo<MSP430MCAsmInfo> X(getTheMSP430Target());
|
||||
|
||||
// Register the MC instruction info.
|
||||
TargetRegistry::RegisterMCInstrInfo(getTheMSP430Target(),
|
||||
createMSP430MCInstrInfo);
|
||||
|
||||
// Register the MC register info.
|
||||
TargetRegistry::RegisterMCRegInfo(getTheMSP430Target(),
|
||||
createMSP430MCRegisterInfo);
|
||||
|
||||
// Register the MC subtarget info.
|
||||
TargetRegistry::RegisterMCSubtargetInfo(getTheMSP430Target(),
|
||||
createMSP430MCSubtargetInfo);
|
||||
|
||||
// Register the MCInstPrinter.
|
||||
TargetRegistry::RegisterMCInstPrinter(getTheMSP430Target(),
|
||||
createMSP430MCInstPrinter);
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
//===-- MSP430MCTargetDesc.h - MSP430 Target Descriptions -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file provides MSP430 specific target descriptions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_MSP430_MCTARGETDESC_MSP430MCTARGETDESC_H
|
||||
#define LLVM_LIB_TARGET_MSP430_MCTARGETDESC_MSP430MCTARGETDESC_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
class Target;
|
||||
|
||||
Target &getTheMSP430Target();
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
// Defines symbolic names for MSP430 registers.
|
||||
// This defines a mapping from register name to register number.
|
||||
#define GET_REGINFO_ENUM
|
||||
#include "MSP430GenRegisterInfo.inc"
|
||||
|
||||
// Defines symbolic names for the MSP430 instructions.
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#include "MSP430GenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_ENUM
|
||||
#include "MSP430GenSubtargetInfo.inc"
|
||||
|
||||
#endif
|
47
external/llvm/lib/Target/MSP430/MSP430.h
vendored
47
external/llvm/lib/Target/MSP430/MSP430.h
vendored
@ -1,47 +0,0 @@
|
||||
//==-- MSP430.h - Top-level interface for MSP430 representation --*- 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 the entry points for global functions defined in
|
||||
// the LLVM MSP430 backend.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_MSP430_MSP430_H
|
||||
#define LLVM_LIB_TARGET_MSP430_MSP430_H
|
||||
|
||||
#include "MCTargetDesc/MSP430MCTargetDesc.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
namespace MSP430CC {
|
||||
// MSP430 specific condition code.
|
||||
enum CondCodes {
|
||||
COND_E = 0, // aka COND_Z
|
||||
COND_NE = 1, // aka COND_NZ
|
||||
COND_HS = 2, // aka COND_C
|
||||
COND_LO = 3, // aka COND_NC
|
||||
COND_GE = 4,
|
||||
COND_L = 5,
|
||||
|
||||
COND_INVALID = -1
|
||||
};
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
class MSP430TargetMachine;
|
||||
class FunctionPass;
|
||||
class formatted_raw_ostream;
|
||||
|
||||
FunctionPass *createMSP430ISelDag(MSP430TargetMachine &TM,
|
||||
CodeGenOpt::Level OptLevel);
|
||||
|
||||
FunctionPass *createMSP430BranchSelectionPass();
|
||||
|
||||
} // end namespace llvm;
|
||||
|
||||
#endif
|
74
external/llvm/lib/Target/MSP430/MSP430.td
vendored
74
external/llvm/lib/Target/MSP430/MSP430.td
vendored
@ -1,74 +0,0 @@
|
||||
//===-- MSP430.td - Describe the MSP430 Target Machine -----*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This is the top level entry point for the MSP430 target.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Target-independent interfaces
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "llvm/Target/Target.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Subtarget Features.
|
||||
//===----------------------------------------------------------------------===//
|
||||
def FeatureX
|
||||
: SubtargetFeature<"ext", "ExtendedInsts", "true",
|
||||
"Enable MSP430-X extensions">;
|
||||
|
||||
def FeatureHWMult16
|
||||
: SubtargetFeature<"hwmult16", "HWMultMode", "HWMult16",
|
||||
"Enable 16-bit hardware multiplier">;
|
||||
|
||||
def FeatureHWMult32
|
||||
: SubtargetFeature<"hwmult32", "HWMultMode", "HWMult32",
|
||||
"Enable 32-bit hardware multiplier">;
|
||||
|
||||
def FeatureHWMultF5
|
||||
: SubtargetFeature<"hwmultf5", "HWMultMode", "HWMultF5",
|
||||
"Enable F5 series hardware multiplier">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MSP430 supported processors.
|
||||
//===----------------------------------------------------------------------===//
|
||||
class Proc<string Name, list<SubtargetFeature> Features>
|
||||
: Processor<Name, NoItineraries, Features>;
|
||||
|
||||
def : Proc<"generic", []>;
|
||||
def : Proc<"msp430", []>;
|
||||
def : Proc<"msp430x", [FeatureX]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Register File Description
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "MSP430RegisterInfo.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Calling Convention Description
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "MSP430CallingConv.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction Descriptions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "MSP430InstrInfo.td"
|
||||
|
||||
def MSP430InstrInfo : InstrInfo;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Target Declaration
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def MSP430 : Target {
|
||||
let InstructionSet = MSP430InstrInfo;
|
||||
}
|
||||
|
159
external/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp
vendored
159
external/llvm/lib/Target/MSP430/MSP430AsmPrinter.cpp
vendored
@ -1,159 +0,0 @@
|
||||
//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//
|
||||
//
|
||||
// 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 printer that converts from our internal representation
|
||||
// of machine-dependent LLVM code to the MSP430 assembly language.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "InstPrinter/MSP430InstPrinter.h"
|
||||
#include "MSP430.h"
|
||||
#include "MSP430InstrInfo.h"
|
||||
#include "MSP430MCInstLower.h"
|
||||
#include "MSP430TargetMachine.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Mangler.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "asm-printer"
|
||||
|
||||
namespace {
|
||||
class MSP430AsmPrinter : public AsmPrinter {
|
||||
public:
|
||||
MSP430AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
|
||||
: AsmPrinter(TM, std::move(Streamer)) {}
|
||||
|
||||
StringRef getPassName() const override { return "MSP430 Assembly Printer"; }
|
||||
|
||||
void printOperand(const MachineInstr *MI, int OpNum,
|
||||
raw_ostream &O, const char* Modifier = nullptr);
|
||||
void printSrcMemOperand(const MachineInstr *MI, int OpNum,
|
||||
raw_ostream &O);
|
||||
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &O) override;
|
||||
bool PrintAsmMemoryOperand(const MachineInstr *MI,
|
||||
unsigned OpNo, unsigned AsmVariant,
|
||||
const char *ExtraCode, raw_ostream &O) override;
|
||||
void EmitInstruction(const MachineInstr *MI) override;
|
||||
};
|
||||
} // end of anonymous namespace
|
||||
|
||||
|
||||
void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
|
||||
raw_ostream &O, const char *Modifier) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNum);
|
||||
switch (MO.getType()) {
|
||||
default: llvm_unreachable("Not implemented yet!");
|
||||
case MachineOperand::MO_Register:
|
||||
O << MSP430InstPrinter::getRegisterName(MO.getReg());
|
||||
return;
|
||||
case MachineOperand::MO_Immediate:
|
||||
if (!Modifier || strcmp(Modifier, "nohash"))
|
||||
O << '#';
|
||||
O << MO.getImm();
|
||||
return;
|
||||
case MachineOperand::MO_MachineBasicBlock:
|
||||
MO.getMBB()->getSymbol()->print(O, MAI);
|
||||
return;
|
||||
case MachineOperand::MO_GlobalAddress: {
|
||||
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
|
||||
uint64_t Offset = MO.getOffset();
|
||||
|
||||
// If the global address expression is a part of displacement field with a
|
||||
// register base, we should not emit any prefix symbol here, e.g.
|
||||
// mov.w &foo, r1
|
||||
// vs
|
||||
// mov.w glb(r1), r2
|
||||
// Otherwise (!) msp430-as will silently miscompile the output :(
|
||||
if (!Modifier || strcmp(Modifier, "nohash"))
|
||||
O << (isMemOp ? '&' : '#');
|
||||
if (Offset)
|
||||
O << '(' << Offset << '+';
|
||||
|
||||
getSymbol(MO.getGlobal())->print(O, MAI);
|
||||
|
||||
if (Offset)
|
||||
O << ')';
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &Base = MI->getOperand(OpNum);
|
||||
const MachineOperand &Disp = MI->getOperand(OpNum+1);
|
||||
|
||||
// Print displacement first
|
||||
|
||||
// Imm here is in fact global address - print extra modifier.
|
||||
if (Disp.isImm() && !Base.getReg())
|
||||
O << '&';
|
||||
printOperand(MI, OpNum+1, O, "nohash");
|
||||
|
||||
// Print register base field
|
||||
if (Base.getReg()) {
|
||||
O << '(';
|
||||
printOperand(MI, OpNum, O);
|
||||
O << ')';
|
||||
}
|
||||
}
|
||||
|
||||
/// PrintAsmOperand - Print out an operand for an inline asm expression.
|
||||
///
|
||||
bool MSP430AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant,
|
||||
const char *ExtraCode, raw_ostream &O) {
|
||||
// Does this asm operand have a single letter operand modifier?
|
||||
if (ExtraCode && ExtraCode[0])
|
||||
return true; // Unknown modifier.
|
||||
|
||||
printOperand(MI, OpNo, O);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
|
||||
unsigned OpNo, unsigned AsmVariant,
|
||||
const char *ExtraCode,
|
||||
raw_ostream &O) {
|
||||
if (ExtraCode && ExtraCode[0]) {
|
||||
return true; // Unknown modifier.
|
||||
}
|
||||
printSrcMemOperand(MI, OpNo, O);
|
||||
return false;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
void MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
MSP430MCInstLower MCInstLowering(OutContext, *this);
|
||||
|
||||
MCInst TmpInst;
|
||||
MCInstLowering.Lower(MI, TmpInst);
|
||||
EmitToStreamer(*OutStreamer, TmpInst);
|
||||
}
|
||||
|
||||
// Force static initialization.
|
||||
extern "C" void LLVMInitializeMSP430AsmPrinter() {
|
||||
RegisterAsmPrinter<MSP430AsmPrinter> X(getTheMSP430Target());
|
||||
}
|
@ -1,257 +0,0 @@
|
||||
//===-- MSP430BranchSelector.cpp - Emit long conditional branches ---------===//
|
||||
//
|
||||
// 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 pseudo op to machine branch opcode pass. This
|
||||
// pass should be run last, just before the assembly printer.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MSP430.h"
|
||||
#include "MSP430InstrInfo.h"
|
||||
#include "MSP430Subtarget.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "msp430-branch-select"
|
||||
|
||||
static cl::opt<bool>
|
||||
BranchSelectEnabled("msp430-branch-select", cl::Hidden, cl::init(true),
|
||||
cl::desc("Expand out of range branches"));
|
||||
|
||||
STATISTIC(NumSplit, "Number of machine basic blocks split");
|
||||
STATISTIC(NumExpanded, "Number of branches expanded to long format");
|
||||
|
||||
namespace {
|
||||
class MSP430BSel : public MachineFunctionPass {
|
||||
|
||||
typedef SmallVector<int, 16> OffsetVector;
|
||||
|
||||
MachineFunction *MF;
|
||||
const MSP430InstrInfo *TII;
|
||||
|
||||
unsigned measureFunction(OffsetVector &BlockOffsets,
|
||||
MachineBasicBlock *FromBB = nullptr);
|
||||
bool expandBranches(OffsetVector &BlockOffsets);
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
MSP430BSel() : MachineFunctionPass(ID) {}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF) override;
|
||||
|
||||
MachineFunctionProperties getRequiredProperties() const override {
|
||||
return MachineFunctionProperties().set(
|
||||
MachineFunctionProperties::Property::NoVRegs);
|
||||
}
|
||||
|
||||
StringRef getPassName() const override { return "MSP430 Branch Selector"; }
|
||||
};
|
||||
char MSP430BSel::ID = 0;
|
||||
}
|
||||
|
||||
static bool isInRage(int DistanceInBytes) {
|
||||
// According to CC430 Family User's Guide, Section 4.5.1.3, branch
|
||||
// instructions have the signed 10-bit word offset field, so first we need to
|
||||
// convert the distance from bytes to words, then check if it fits in 10-bit
|
||||
// signed integer.
|
||||
const int WordSize = 2;
|
||||
|
||||
assert((DistanceInBytes % WordSize == 0) &&
|
||||
"Branch offset should be word aligned!");
|
||||
|
||||
int Words = DistanceInBytes / WordSize;
|
||||
return isInt<10>(Words);
|
||||
}
|
||||
|
||||
/// Measure each basic block, fill the BlockOffsets, and return the size of
|
||||
/// the function, starting with BB
|
||||
unsigned MSP430BSel::measureFunction(OffsetVector &BlockOffsets,
|
||||
MachineBasicBlock *FromBB) {
|
||||
// Give the blocks of the function a dense, in-order, numbering.
|
||||
MF->RenumberBlocks(FromBB);
|
||||
|
||||
MachineFunction::iterator Begin;
|
||||
if (FromBB == nullptr) {
|
||||
Begin = MF->begin();
|
||||
} else {
|
||||
Begin = FromBB->getIterator();
|
||||
}
|
||||
|
||||
BlockOffsets.resize(MF->getNumBlockIDs());
|
||||
|
||||
unsigned TotalSize = BlockOffsets[Begin->getNumber()];
|
||||
for (auto &MBB : make_range(Begin, MF->end())) {
|
||||
BlockOffsets[MBB.getNumber()] = TotalSize;
|
||||
for (MachineInstr &MI : MBB) {
|
||||
TotalSize += TII->getInstSizeInBytes(MI);
|
||||
}
|
||||
}
|
||||
return TotalSize;
|
||||
}
|
||||
|
||||
/// Do expand branches and split the basic blocks if necessary.
|
||||
/// Returns true if made any change.
|
||||
bool MSP430BSel::expandBranches(OffsetVector &BlockOffsets) {
|
||||
// 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 = false;
|
||||
for (auto MBB = MF->begin(), E = MF->end(); MBB != E; ++MBB) {
|
||||
unsigned MBBStartOffset = 0;
|
||||
for (auto MI = MBB->begin(), EE = MBB->end(); MI != EE; ++MI) {
|
||||
MBBStartOffset += TII->getInstSizeInBytes(*MI);
|
||||
|
||||
// If this instruction is not a short branch then skip it.
|
||||
if (MI->getOpcode() != MSP430::JCC && MI->getOpcode() != MSP430::JMP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MachineBasicBlock *DestBB = MI->getOperand(0).getMBB();
|
||||
// Determine the distance from the current branch to the destination
|
||||
// block. MBBStartOffset already includes the size of the current branch
|
||||
// instruction.
|
||||
int BlockDistance =
|
||||
BlockOffsets[DestBB->getNumber()] - BlockOffsets[MBB->getNumber()];
|
||||
int BranchDistance = BlockDistance - MBBStartOffset;
|
||||
|
||||
// If this branch is in range, ignore it.
|
||||
if (isInRage(BranchDistance)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG(dbgs() << " Found a branch that needs expanding, "
|
||||
<< printMBBReference(*DestBB) << ", Distance "
|
||||
<< BranchDistance << "\n");
|
||||
|
||||
// If JCC is not the last instruction we need to split the MBB.
|
||||
if (MI->getOpcode() == MSP430::JCC && std::next(MI) != EE) {
|
||||
|
||||
DEBUG(dbgs() << " Found a basic block that needs to be split, "
|
||||
<< printMBBReference(*MBB) << "\n");
|
||||
|
||||
// Create a new basic block.
|
||||
MachineBasicBlock *NewBB =
|
||||
MF->CreateMachineBasicBlock(MBB->getBasicBlock());
|
||||
MF->insert(std::next(MBB), NewBB);
|
||||
|
||||
// Splice the instructions following MI over to the NewBB.
|
||||
NewBB->splice(NewBB->end(), &*MBB, std::next(MI), MBB->end());
|
||||
|
||||
// Update the successor lists.
|
||||
for (MachineBasicBlock *Succ : MBB->successors()) {
|
||||
if (Succ == DestBB) {
|
||||
continue;
|
||||
}
|
||||
MBB->replaceSuccessor(Succ, NewBB);
|
||||
NewBB->addSuccessor(Succ);
|
||||
}
|
||||
|
||||
// We introduced a new MBB so all following blocks should be numbered
|
||||
// and measured again.
|
||||
measureFunction(BlockOffsets, &*MBB);
|
||||
|
||||
++NumSplit;
|
||||
|
||||
// It may be not necessary to start all over at this point, but it's
|
||||
// safer do this anyway.
|
||||
return true;
|
||||
}
|
||||
|
||||
MachineInstr &OldBranch = *MI;
|
||||
DebugLoc dl = OldBranch.getDebugLoc();
|
||||
int InstrSizeDiff = -TII->getInstSizeInBytes(OldBranch);
|
||||
|
||||
if (MI->getOpcode() == MSP430::JCC) {
|
||||
MachineBasicBlock *NextMBB = &*std::next(MBB);
|
||||
assert(MBB->isSuccessor(NextMBB) &&
|
||||
"This block must have a layout successor!");
|
||||
|
||||
// The BCC operands are:
|
||||
// 0. Target MBB
|
||||
// 1. MSP430 branch predicate
|
||||
SmallVector<MachineOperand, 1> Cond;
|
||||
Cond.push_back(MI->getOperand(1));
|
||||
|
||||
// Jump over the long branch on the opposite condition
|
||||
TII->reverseBranchCondition(Cond);
|
||||
MI = BuildMI(*MBB, MI, dl, TII->get(MSP430::JCC))
|
||||
.addMBB(NextMBB)
|
||||
.add(Cond[0]);
|
||||
InstrSizeDiff += TII->getInstSizeInBytes(*MI);
|
||||
++MI;
|
||||
}
|
||||
|
||||
// Unconditional branch to the real destination.
|
||||
MI = BuildMI(*MBB, MI, dl, TII->get(MSP430::Bi)).addMBB(DestBB);
|
||||
InstrSizeDiff += TII->getInstSizeInBytes(*MI);
|
||||
|
||||
// Remove the old branch from the function.
|
||||
OldBranch.eraseFromParent();
|
||||
|
||||
// The size of a new instruction is different from the old one, so we need
|
||||
// to correct all block offsets.
|
||||
for (int i = MBB->getNumber() + 1, e = BlockOffsets.size(); i < e; ++i) {
|
||||
BlockOffsets[i] += InstrSizeDiff;
|
||||
}
|
||||
MBBStartOffset += InstrSizeDiff;
|
||||
|
||||
++NumExpanded;
|
||||
MadeChange = true;
|
||||
}
|
||||
}
|
||||
return MadeChange;
|
||||
}
|
||||
|
||||
bool MSP430BSel::runOnMachineFunction(MachineFunction &mf) {
|
||||
MF = &mf;
|
||||
TII = static_cast<const MSP430InstrInfo *>(MF->getSubtarget().getInstrInfo());
|
||||
|
||||
// If the pass is disabled, just bail early.
|
||||
if (!BranchSelectEnabled)
|
||||
return false;
|
||||
|
||||
DEBUG(dbgs() << "\n********** " << getPassName() << " **********\n");
|
||||
|
||||
// BlockOffsets - Contains the distance from the beginning of the function to
|
||||
// the beginning of each basic block.
|
||||
OffsetVector BlockOffsets;
|
||||
|
||||
unsigned FunctionSize = measureFunction(BlockOffsets);
|
||||
// If the entire function is smaller than the displacement of a branch field,
|
||||
// we know we don't need to expand any branches in this
|
||||
// function. This is a common case.
|
||||
if (isInRage(FunctionSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Iteratively expand branches until we reach a fixed point.
|
||||
bool MadeChange = false;
|
||||
while (expandBranches(BlockOffsets))
|
||||
MadeChange = true;
|
||||
|
||||
return MadeChange;
|
||||
}
|
||||
|
||||
/// Returns an instance of the Branch Selection Pass
|
||||
FunctionPass *llvm::createMSP430BranchSelectionPass() {
|
||||
return new MSP430BSel();
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
//==- MSP430CallingConv.td - Calling Conventions for MSP430 -*- tablegen -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This describes the calling conventions for MSP430 architecture.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MSP430 Return Value Calling Convention
|
||||
//===----------------------------------------------------------------------===//
|
||||
def RetCC_MSP430 : CallingConv<[
|
||||
// i8 are returned in registers R12B, R13B, R14B, R15B
|
||||
CCIfType<[i8], CCAssignToReg<[R12B, R13B, R14B, R15B]>>,
|
||||
|
||||
// i16 are returned in registers R12, R13, R14, R15
|
||||
CCIfType<[i16], CCAssignToReg<[R12, R13, R14, R15]>>
|
||||
]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MSP430 Argument Calling Conventions
|
||||
//===----------------------------------------------------------------------===//
|
||||
def CC_MSP430_AssignStack : CallingConv<[
|
||||
// Pass by value if the byval attribute is given
|
||||
CCIfByVal<CCPassByVal<2, 2>>,
|
||||
|
||||
// Promote i8 arguments to i16.
|
||||
CCIfType<[i8], CCPromoteToType<i16>>,
|
||||
|
||||
// Integer values get stored in stack slots that are 2 bytes in
|
||||
// size and 2-byte aligned.
|
||||
CCIfType<[i16], CCAssignToStack<2, 2>>
|
||||
]>;
|
||||
|
@ -1,300 +0,0 @@
|
||||
//===-- MSP430FrameLowering.cpp - MSP430 Frame Information ----------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the MSP430 implementation of TargetFrameLowering class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MSP430FrameLowering.h"
|
||||
#include "MSP430InstrInfo.h"
|
||||
#include "MSP430MachineFunctionInfo.h"
|
||||
#include "MSP430Subtarget.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
bool MSP430FrameLowering::hasFP(const MachineFunction &MF) const {
|
||||
const MachineFrameInfo &MFI = MF.getFrameInfo();
|
||||
|
||||
return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
|
||||
MF.getFrameInfo().hasVarSizedObjects() ||
|
||||
MFI.isFrameAddressTaken());
|
||||
}
|
||||
|
||||
bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
|
||||
return !MF.getFrameInfo().hasVarSizedObjects();
|
||||
}
|
||||
|
||||
void MSP430FrameLowering::emitPrologue(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB) const {
|
||||
assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
|
||||
MachineFrameInfo &MFI = MF.getFrameInfo();
|
||||
MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
|
||||
const MSP430InstrInfo &TII =
|
||||
*static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
|
||||
|
||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||
|
||||
// Get the number of bytes to allocate from the FrameInfo.
|
||||
uint64_t StackSize = MFI.getStackSize();
|
||||
|
||||
uint64_t NumBytes = 0;
|
||||
if (hasFP(MF)) {
|
||||
// Calculate required stack adjustment
|
||||
uint64_t FrameSize = StackSize - 2;
|
||||
NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
|
||||
|
||||
// Get the offset of the stack slot for the EBP register... which is
|
||||
// guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
|
||||
// Update the frame offset adjustment.
|
||||
MFI.setOffsetAdjustment(-NumBytes);
|
||||
|
||||
// Save FP into the appropriate stack slot...
|
||||
BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
|
||||
.addReg(MSP430::FP, RegState::Kill);
|
||||
|
||||
// Update FP with the new base value...
|
||||
BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::FP)
|
||||
.addReg(MSP430::SP);
|
||||
|
||||
// Mark the FramePtr as live-in in every block except the entry.
|
||||
for (MachineFunction::iterator I = std::next(MF.begin()), E = MF.end();
|
||||
I != E; ++I)
|
||||
I->addLiveIn(MSP430::FP);
|
||||
|
||||
} else
|
||||
NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
|
||||
|
||||
// Skip the callee-saved push instructions.
|
||||
while (MBBI != MBB.end() && (MBBI->getOpcode() == MSP430::PUSH16r))
|
||||
++MBBI;
|
||||
|
||||
if (MBBI != MBB.end())
|
||||
DL = MBBI->getDebugLoc();
|
||||
|
||||
if (NumBytes) { // adjust stack pointer: SP -= numbytes
|
||||
// If there is an SUB16ri of SP immediately before this instruction, merge
|
||||
// the two.
|
||||
//NumBytes -= mergeSPUpdates(MBB, MBBI, true);
|
||||
// If there is an ADD16ri or SUB16ri of SP immediately after this
|
||||
// instruction, merge the two instructions.
|
||||
// mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
|
||||
|
||||
if (NumBytes) {
|
||||
MachineInstr *MI =
|
||||
BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
|
||||
.addReg(MSP430::SP).addImm(NumBytes);
|
||||
// The SRW implicit def is dead.
|
||||
MI->getOperand(3).setIsDead();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB) const {
|
||||
const MachineFrameInfo &MFI = MF.getFrameInfo();
|
||||
MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();
|
||||
const MSP430InstrInfo &TII =
|
||||
*static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
|
||||
|
||||
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||
unsigned RetOpcode = MBBI->getOpcode();
|
||||
DebugLoc DL = MBBI->getDebugLoc();
|
||||
|
||||
switch (RetOpcode) {
|
||||
case MSP430::RET:
|
||||
case MSP430::RETI: break; // These are ok
|
||||
default:
|
||||
llvm_unreachable("Can only insert epilog into returning blocks");
|
||||
}
|
||||
|
||||
// Get the number of bytes to allocate from the FrameInfo
|
||||
uint64_t StackSize = MFI.getStackSize();
|
||||
unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
|
||||
uint64_t NumBytes = 0;
|
||||
|
||||
if (hasFP(MF)) {
|
||||
// Calculate required stack adjustment
|
||||
uint64_t FrameSize = StackSize - 2;
|
||||
NumBytes = FrameSize - CSSize;
|
||||
|
||||
// pop FP.
|
||||
BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::FP);
|
||||
} else
|
||||
NumBytes = StackSize - CSSize;
|
||||
|
||||
// Skip the callee-saved pop instructions.
|
||||
while (MBBI != MBB.begin()) {
|
||||
MachineBasicBlock::iterator PI = std::prev(MBBI);
|
||||
unsigned Opc = PI->getOpcode();
|
||||
if (Opc != MSP430::POP16r && !PI->isTerminator())
|
||||
break;
|
||||
--MBBI;
|
||||
}
|
||||
|
||||
DL = MBBI->getDebugLoc();
|
||||
|
||||
// If there is an ADD16ri or SUB16ri of SP immediately before this
|
||||
// instruction, merge the two instructions.
|
||||
//if (NumBytes || MFI.hasVarSizedObjects())
|
||||
// mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
|
||||
|
||||
if (MFI.hasVarSizedObjects()) {
|
||||
BuildMI(MBB, MBBI, DL,
|
||||
TII.get(MSP430::MOV16rr), MSP430::SP).addReg(MSP430::FP);
|
||||
if (CSSize) {
|
||||
MachineInstr *MI =
|
||||
BuildMI(MBB, MBBI, DL,
|
||||
TII.get(MSP430::SUB16ri), MSP430::SP)
|
||||
.addReg(MSP430::SP).addImm(CSSize);
|
||||
// The SRW implicit def is dead.
|
||||
MI->getOperand(3).setIsDead();
|
||||
}
|
||||
} else {
|
||||
// adjust stack pointer back: SP += numbytes
|
||||
if (NumBytes) {
|
||||
MachineInstr *MI =
|
||||
BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
|
||||
.addReg(MSP430::SP).addImm(NumBytes);
|
||||
// The SRW implicit def is dead.
|
||||
MI->getOperand(3).setIsDead();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Can we eleminate these in favour of generic code?
|
||||
bool
|
||||
MSP430FrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
if (CSI.empty())
|
||||
return false;
|
||||
|
||||
DebugLoc DL;
|
||||
if (MI != MBB.end()) DL = MI->getDebugLoc();
|
||||
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
|
||||
MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>();
|
||||
MFI->setCalleeSavedFrameSize(CSI.size() * 2);
|
||||
|
||||
for (unsigned i = CSI.size(); i != 0; --i) {
|
||||
unsigned Reg = CSI[i-1].getReg();
|
||||
// Add the callee-saved register as live-in. It's killed at the spill.
|
||||
MBB.addLiveIn(Reg);
|
||||
BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
|
||||
.addReg(Reg, RegState::Kill);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MSP430FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
std::vector<CalleeSavedInfo> &CSI,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
if (CSI.empty())
|
||||
return false;
|
||||
|
||||
DebugLoc DL;
|
||||
if (MI != MBB.end()) DL = MI->getDebugLoc();
|
||||
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
|
||||
|
||||
for (unsigned i = 0, e = CSI.size(); i != e; ++i)
|
||||
BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), CSI[i].getReg());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MachineBasicBlock::iterator MSP430FrameLowering::eliminateCallFramePseudoInstr(
|
||||
MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const {
|
||||
const MSP430InstrInfo &TII =
|
||||
*static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
|
||||
unsigned StackAlign = getStackAlignment();
|
||||
|
||||
if (!hasReservedCallFrame(MF)) {
|
||||
// If the stack pointer can be changed after prologue, turn the
|
||||
// adjcallstackup instruction into a 'sub SP, <amt>' and the
|
||||
// adjcallstackdown instruction into 'add SP, <amt>'
|
||||
// TODO: consider using push / pop instead of sub + store / add
|
||||
MachineInstr &Old = *I;
|
||||
uint64_t Amount = TII.getFrameSize(Old);
|
||||
if (Amount != 0) {
|
||||
// We need to keep the stack aligned properly. To do this, we round the
|
||||
// amount of space needed for the outgoing arguments up to the next
|
||||
// alignment boundary.
|
||||
Amount = (Amount+StackAlign-1)/StackAlign*StackAlign;
|
||||
|
||||
MachineInstr *New = nullptr;
|
||||
if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
|
||||
New =
|
||||
BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
|
||||
.addReg(MSP430::SP)
|
||||
.addImm(Amount);
|
||||
} else {
|
||||
assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
|
||||
// factor out the amount the callee already popped.
|
||||
Amount -= TII.getFramePoppedByCallee(Old);
|
||||
if (Amount)
|
||||
New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),
|
||||
MSP430::SP)
|
||||
.addReg(MSP430::SP)
|
||||
.addImm(Amount);
|
||||
}
|
||||
|
||||
if (New) {
|
||||
// The SRW implicit def is dead.
|
||||
New->getOperand(3).setIsDead();
|
||||
|
||||
// Replace the pseudo instruction with a new instruction...
|
||||
MBB.insert(I, New);
|
||||
}
|
||||
}
|
||||
} else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {
|
||||
// If we are performing frame pointer elimination and if the callee pops
|
||||
// something off the stack pointer, add it back.
|
||||
if (uint64_t CalleeAmt = TII.getFramePoppedByCallee(*I)) {
|
||||
MachineInstr &Old = *I;
|
||||
MachineInstr *New =
|
||||
BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
|
||||
.addReg(MSP430::SP)
|
||||
.addImm(CalleeAmt);
|
||||
// The SRW implicit def is dead.
|
||||
New->getOperand(3).setIsDead();
|
||||
|
||||
MBB.insert(I, New);
|
||||
}
|
||||
}
|
||||
|
||||
return MBB.erase(I);
|
||||
}
|
||||
|
||||
void
|
||||
MSP430FrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,
|
||||
RegScavenger *) const {
|
||||
// Create a frame entry for the FP register that must be saved.
|
||||
if (hasFP(MF)) {
|
||||
int FrameIdx = MF.getFrameInfo().CreateFixedObject(2, -4, true);
|
||||
(void)FrameIdx;
|
||||
assert(FrameIdx == MF.getFrameInfo().getObjectIndexBegin() &&
|
||||
"Slot for FP register must be last in order to be found!");
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
//==- MSP430FrameLowering.h - Define frame lowering for MSP430 --*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TARGET_MSP430_MSP430FRAMELOWERING_H
|
||||
#define LLVM_LIB_TARGET_MSP430_MSP430FRAMELOWERING_H
|
||||
|
||||
#include "MSP430.h"
|
||||
#include "llvm/CodeGen/TargetFrameLowering.h"
|
||||
|
||||
namespace llvm {
|
||||
class MSP430FrameLowering : public TargetFrameLowering {
|
||||
protected:
|
||||
|
||||
public:
|
||||
explicit MSP430FrameLowering()
|
||||
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 2, -2, 2) {}
|
||||
|
||||
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||
/// the function.
|
||||
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
|
||||
|
||||
MachineBasicBlock::iterator
|
||||
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const override;
|
||||
|
||||
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI,
|
||||
const TargetRegisterInfo *TRI) const override;
|
||||
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
std::vector<CalleeSavedInfo> &CSI,
|
||||
const TargetRegisterInfo *TRI) const override;
|
||||
|
||||
bool hasFP(const MachineFunction &MF) const override;
|
||||
bool hasReservedCallFrame(const MachineFunction &MF) const override;
|
||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF,
|
||||
RegScavenger *RS = nullptr) const override;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -1,471 +0,0 @@
|
||||
//===-- MSP430ISelDAGToDAG.cpp - A dag to dag inst selector for MSP430 ----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines an instruction selector for the MSP430 target.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MSP430.h"
|
||||
#include "MSP430TargetMachine.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
||||
#include "llvm/CodeGen/TargetLowering.h"
|
||||
#include "llvm/IR/CallingConv.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define DEBUG_TYPE "msp430-isel"
|
||||
|
||||
namespace {
|
||||
struct MSP430ISelAddressMode {
|
||||
enum {
|
||||
RegBase,
|
||||
FrameIndexBase
|
||||
} BaseType;
|
||||
|
||||
struct { // This is really a union, discriminated by BaseType!
|
||||
SDValue Reg;
|
||||
int FrameIndex;
|
||||
} Base;
|
||||
|
||||
int16_t Disp;
|
||||
const GlobalValue *GV;
|
||||
const Constant *CP;
|
||||
const BlockAddress *BlockAddr;
|
||||
const char *ES;
|
||||
int JT;
|
||||
unsigned Align; // CP alignment.
|
||||
|
||||
MSP430ISelAddressMode()
|
||||
: BaseType(RegBase), Disp(0), GV(nullptr), CP(nullptr),
|
||||
BlockAddr(nullptr), ES(nullptr), JT(-1), Align(0) {
|
||||
}
|
||||
|
||||
bool hasSymbolicDisplacement() const {
|
||||
return GV != nullptr || CP != nullptr || ES != nullptr || JT != -1;
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
LLVM_DUMP_METHOD void dump() {
|
||||
errs() << "MSP430ISelAddressMode " << this << '\n';
|
||||
if (BaseType == RegBase && Base.Reg.getNode() != nullptr) {
|
||||
errs() << "Base.Reg ";
|
||||
Base.Reg.getNode()->dump();
|
||||
} else if (BaseType == FrameIndexBase) {
|
||||
errs() << " Base.FrameIndex " << Base.FrameIndex << '\n';
|
||||
}
|
||||
errs() << " Disp " << Disp << '\n';
|
||||
if (GV) {
|
||||
errs() << "GV ";
|
||||
GV->dump();
|
||||
} else if (CP) {
|
||||
errs() << " CP ";
|
||||
CP->dump();
|
||||
errs() << " Align" << Align << '\n';
|
||||
} else if (ES) {
|
||||
errs() << "ES ";
|
||||
errs() << ES << '\n';
|
||||
} else if (JT != -1)
|
||||
errs() << " JT" << JT << " Align" << Align << '\n';
|
||||
}
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
/// MSP430DAGToDAGISel - MSP430 specific code to select MSP430 machine
|
||||
/// instructions for SelectionDAG operations.
|
||||
///
|
||||
namespace {
|
||||
class MSP430DAGToDAGISel : public SelectionDAGISel {
|
||||
public:
|
||||
MSP430DAGToDAGISel(MSP430TargetMachine &TM, CodeGenOpt::Level OptLevel)
|
||||
: SelectionDAGISel(TM, OptLevel) {}
|
||||
|
||||
StringRef getPassName() const override {
|
||||
return "MSP430 DAG->DAG Pattern Instruction Selection";
|
||||
}
|
||||
|
||||
bool MatchAddress(SDValue N, MSP430ISelAddressMode &AM);
|
||||
bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM);
|
||||
bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM);
|
||||
|
||||
bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
|
||||
std::vector<SDValue> &OutOps) override;
|
||||
|
||||
// Include the pieces autogenerated from the target description.
|
||||
#include "MSP430GenDAGISel.inc"
|
||||
|
||||
private:
|
||||
void Select(SDNode *N) override;
|
||||
bool tryIndexedLoad(SDNode *Op);
|
||||
bool tryIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2, unsigned Opc8,
|
||||
unsigned Opc16);
|
||||
|
||||
bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Disp);
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
/// createMSP430ISelDag - This pass converts a legalized DAG into a
|
||||
/// MSP430-specific DAG, ready for instruction scheduling.
|
||||
///
|
||||
FunctionPass *llvm::createMSP430ISelDag(MSP430TargetMachine &TM,
|
||||
CodeGenOpt::Level OptLevel) {
|
||||
return new MSP430DAGToDAGISel(TM, OptLevel);
|
||||
}
|
||||
|
||||
|
||||
/// MatchWrapper - Try to match MSP430ISD::Wrapper node into an addressing mode.
|
||||
/// These wrap things that will resolve down into a symbol reference. If no
|
||||
/// match is possible, this returns true, otherwise it returns false.
|
||||
bool MSP430DAGToDAGISel::MatchWrapper(SDValue N, MSP430ISelAddressMode &AM) {
|
||||
// If the addressing mode already has a symbol as the displacement, we can
|
||||
// never match another symbol.
|
||||
if (AM.hasSymbolicDisplacement())
|
||||
return true;
|
||||
|
||||
SDValue N0 = N.getOperand(0);
|
||||
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
|
||||
AM.GV = G->getGlobal();
|
||||
AM.Disp += G->getOffset();
|
||||
//AM.SymbolFlags = G->getTargetFlags();
|
||||
} else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
|
||||
AM.CP = CP->getConstVal();
|
||||
AM.Align = CP->getAlignment();
|
||||
AM.Disp += CP->getOffset();
|
||||
//AM.SymbolFlags = CP->getTargetFlags();
|
||||
} else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(N0)) {
|
||||
AM.ES = S->getSymbol();
|
||||
//AM.SymbolFlags = S->getTargetFlags();
|
||||
} else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
|
||||
AM.JT = J->getIndex();
|
||||
//AM.SymbolFlags = J->getTargetFlags();
|
||||
} else {
|
||||
AM.BlockAddr = cast<BlockAddressSDNode>(N0)->getBlockAddress();
|
||||
//AM.SymbolFlags = cast<BlockAddressSDNode>(N0)->getTargetFlags();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// MatchAddressBase - Helper for MatchAddress. Add the specified node to the
|
||||
/// specified addressing mode without any further recursion.
|
||||
bool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) {
|
||||
// Is the base register already occupied?
|
||||
if (AM.BaseType != MSP430ISelAddressMode::RegBase || AM.Base.Reg.getNode()) {
|
||||
// If so, we cannot select it.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Default, generate it as a register.
|
||||
AM.BaseType = MSP430ISelAddressMode::RegBase;
|
||||
AM.Base.Reg = N;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) {
|
||||
DEBUG(errs() << "MatchAddress: "; AM.dump());
|
||||
|
||||
switch (N.getOpcode()) {
|
||||
default: break;
|
||||
case ISD::Constant: {
|
||||
uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
|
||||
AM.Disp += Val;
|
||||
return false;
|
||||
}
|
||||
|
||||
case MSP430ISD::Wrapper:
|
||||
if (!MatchWrapper(N, AM))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case ISD::FrameIndex:
|
||||
if (AM.BaseType == MSP430ISelAddressMode::RegBase
|
||||
&& AM.Base.Reg.getNode() == nullptr) {
|
||||
AM.BaseType = MSP430ISelAddressMode::FrameIndexBase;
|
||||
AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case ISD::ADD: {
|
||||
MSP430ISelAddressMode Backup = AM;
|
||||
if (!MatchAddress(N.getNode()->getOperand(0), AM) &&
|
||||
!MatchAddress(N.getNode()->getOperand(1), AM))
|
||||
return false;
|
||||
AM = Backup;
|
||||
if (!MatchAddress(N.getNode()->getOperand(1), AM) &&
|
||||
!MatchAddress(N.getNode()->getOperand(0), AM))
|
||||
return false;
|
||||
AM = Backup;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ISD::OR:
|
||||
// Handle "X | C" as "X + C" iff X is known to have C bits clear.
|
||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
|
||||
MSP430ISelAddressMode Backup = AM;
|
||||
uint64_t Offset = CN->getSExtValue();
|
||||
// Start with the LHS as an addr mode.
|
||||
if (!MatchAddress(N.getOperand(0), AM) &&
|
||||
// Address could not have picked a GV address for the displacement.
|
||||
AM.GV == nullptr &&
|
||||
// Check to see if the LHS & C is zero.
|
||||
CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
|
||||
AM.Disp += Offset;
|
||||
return false;
|
||||
}
|
||||
AM = Backup;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return MatchAddressBase(N, AM);
|
||||
}
|
||||
|
||||
/// SelectAddr - returns true if it is able pattern match an addressing mode.
|
||||
/// It returns the operands which make up the maximal addressing mode it can
|
||||
/// match by reference.
|
||||
bool MSP430DAGToDAGISel::SelectAddr(SDValue N,
|
||||
SDValue &Base, SDValue &Disp) {
|
||||
MSP430ISelAddressMode AM;
|
||||
|
||||
if (MatchAddress(N, AM))
|
||||
return false;
|
||||
|
||||
EVT VT = N.getValueType();
|
||||
if (AM.BaseType == MSP430ISelAddressMode::RegBase) {
|
||||
if (!AM.Base.Reg.getNode())
|
||||
AM.Base.Reg = CurDAG->getRegister(0, VT);
|
||||
}
|
||||
|
||||
Base = (AM.BaseType == MSP430ISelAddressMode::FrameIndexBase)
|
||||
? CurDAG->getTargetFrameIndex(
|
||||
AM.Base.FrameIndex,
|
||||
getTargetLowering()->getPointerTy(CurDAG->getDataLayout()))
|
||||
: AM.Base.Reg;
|
||||
|
||||
if (AM.GV)
|
||||
Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(N),
|
||||
MVT::i16, AM.Disp,
|
||||
0/*AM.SymbolFlags*/);
|
||||
else if (AM.CP)
|
||||
Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i16,
|
||||
AM.Align, AM.Disp, 0/*AM.SymbolFlags*/);
|
||||
else if (AM.ES)
|
||||
Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i16, 0/*AM.SymbolFlags*/);
|
||||
else if (AM.JT != -1)
|
||||
Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i16, 0/*AM.SymbolFlags*/);
|
||||
else if (AM.BlockAddr)
|
||||
Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, 0,
|
||||
0/*AM.SymbolFlags*/);
|
||||
else
|
||||
Disp = CurDAG->getTargetConstant(AM.Disp, SDLoc(N), MVT::i16);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MSP430DAGToDAGISel::
|
||||
SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
|
||||
std::vector<SDValue> &OutOps) {
|
||||
SDValue Op0, Op1;
|
||||
switch (ConstraintID) {
|
||||
default: return true;
|
||||
case InlineAsm::Constraint_m: // memory
|
||||
if (!SelectAddr(Op, Op0, Op1))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
OutOps.push_back(Op0);
|
||||
OutOps.push_back(Op1);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isValidIndexedLoad(const LoadSDNode *LD) {
|
||||
ISD::MemIndexedMode AM = LD->getAddressingMode();
|
||||
if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD)
|
||||
return false;
|
||||
|
||||
EVT VT = LD->getMemoryVT();
|
||||
|
||||
switch (VT.getSimpleVT().SimpleTy) {
|
||||
case MVT::i8:
|
||||
// Sanity check
|
||||
if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 1)
|
||||
return false;
|
||||
|
||||
break;
|
||||
case MVT::i16:
|
||||
// Sanity check
|
||||
if (cast<ConstantSDNode>(LD->getOffset())->getZExtValue() != 2)
|
||||
return false;
|
||||
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MSP430DAGToDAGISel::tryIndexedLoad(SDNode *N) {
|
||||
LoadSDNode *LD = cast<LoadSDNode>(N);
|
||||
if (!isValidIndexedLoad(LD))
|
||||
return false;
|
||||
|
||||
MVT VT = LD->getMemoryVT().getSimpleVT();
|
||||
|
||||
unsigned Opcode = 0;
|
||||
switch (VT.SimpleTy) {
|
||||
case MVT::i8:
|
||||
Opcode = MSP430::MOV8rm_POST;
|
||||
break;
|
||||
case MVT::i16:
|
||||
Opcode = MSP430::MOV16rm_POST;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
ReplaceNode(N,
|
||||
CurDAG->getMachineNode(Opcode, SDLoc(N), VT, MVT::i16, MVT::Other,
|
||||
LD->getBasePtr(), LD->getChain()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MSP430DAGToDAGISel::tryIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2,
|
||||
unsigned Opc8, unsigned Opc16) {
|
||||
if (N1.getOpcode() == ISD::LOAD &&
|
||||
N1.hasOneUse() &&
|
||||
IsLegalToFold(N1, Op, Op, OptLevel)) {
|
||||
LoadSDNode *LD = cast<LoadSDNode>(N1);
|
||||
if (!isValidIndexedLoad(LD))
|
||||
return false;
|
||||
|
||||
MVT VT = LD->getMemoryVT().getSimpleVT();
|
||||
unsigned Opc = (VT == MVT::i16 ? Opc16 : Opc8);
|
||||
MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1);
|
||||
MemRefs0[0] = cast<MemSDNode>(N1)->getMemOperand();
|
||||
SDValue Ops0[] = { N2, LD->getBasePtr(), LD->getChain() };
|
||||
SDNode *ResNode =
|
||||
CurDAG->SelectNodeTo(Op, Opc, VT, MVT::i16, MVT::Other, Ops0);
|
||||
cast<MachineSDNode>(ResNode)->setMemRefs(MemRefs0, MemRefs0 + 1);
|
||||
// Transfer chain.
|
||||
ReplaceUses(SDValue(N1.getNode(), 2), SDValue(ResNode, 2));
|
||||
// Transfer writeback.
|
||||
ReplaceUses(SDValue(N1.getNode(), 1), SDValue(ResNode, 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void MSP430DAGToDAGISel::Select(SDNode *Node) {
|
||||
SDLoc dl(Node);
|
||||
|
||||
// Dump information about the Node being selected
|
||||
DEBUG(errs() << "Selecting: ");
|
||||
DEBUG(Node->dump(CurDAG));
|
||||
DEBUG(errs() << "\n");
|
||||
|
||||
// If we have a custom node, we already have selected!
|
||||
if (Node->isMachineOpcode()) {
|
||||
DEBUG(errs() << "== ";
|
||||
Node->dump(CurDAG);
|
||||
errs() << "\n");
|
||||
Node->setNodeId(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Few custom selection stuff.
|
||||
switch (Node->getOpcode()) {
|
||||
default: break;
|
||||
case ISD::FrameIndex: {
|
||||
assert(Node->getValueType(0) == MVT::i16);
|
||||
int FI = cast<FrameIndexSDNode>(Node)->getIndex();
|
||||
SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i16);
|
||||
if (Node->hasOneUse()) {
|
||||
CurDAG->SelectNodeTo(Node, MSP430::ADDframe, MVT::i16, TFI,
|
||||
CurDAG->getTargetConstant(0, dl, MVT::i16));
|
||||
return;
|
||||
}
|
||||
ReplaceNode(Node, CurDAG->getMachineNode(
|
||||
MSP430::ADDframe, dl, MVT::i16, TFI,
|
||||
CurDAG->getTargetConstant(0, dl, MVT::i16)));
|
||||
return;
|
||||
}
|
||||
case ISD::LOAD:
|
||||
if (tryIndexedLoad(Node))
|
||||
return;
|
||||
// Other cases are autogenerated.
|
||||
break;
|
||||
case ISD::ADD:
|
||||
if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
|
||||
MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
|
||||
return;
|
||||
else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
|
||||
MSP430::ADD8rm_POST, MSP430::ADD16rm_POST))
|
||||
return;
|
||||
|
||||
// Other cases are autogenerated.
|
||||
break;
|
||||
case ISD::SUB:
|
||||
if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
|
||||
MSP430::SUB8rm_POST, MSP430::SUB16rm_POST))
|
||||
return;
|
||||
|
||||
// Other cases are autogenerated.
|
||||
break;
|
||||
case ISD::AND:
|
||||
if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
|
||||
MSP430::AND8rm_POST, MSP430::AND16rm_POST))
|
||||
return;
|
||||
else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
|
||||
MSP430::AND8rm_POST, MSP430::AND16rm_POST))
|
||||
return;
|
||||
|
||||
// Other cases are autogenerated.
|
||||
break;
|
||||
case ISD::OR:
|
||||
if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
|
||||
MSP430::OR8rm_POST, MSP430::OR16rm_POST))
|
||||
return;
|
||||
else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
|
||||
MSP430::OR8rm_POST, MSP430::OR16rm_POST))
|
||||
return;
|
||||
|
||||
// Other cases are autogenerated.
|
||||
break;
|
||||
case ISD::XOR:
|
||||
if (tryIndexedBinOp(Node, Node->getOperand(0), Node->getOperand(1),
|
||||
MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
|
||||
return;
|
||||
else if (tryIndexedBinOp(Node, Node->getOperand(1), Node->getOperand(0),
|
||||
MSP430::XOR8rm_POST, MSP430::XOR16rm_POST))
|
||||
return;
|
||||
|
||||
// Other cases are autogenerated.
|
||||
break;
|
||||
}
|
||||
|
||||
// Select the default instruction
|
||||
SelectCode(Node);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user