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