diff options
Diffstat (limited to 'lib/Target/PIC16/PIC16InstrInfo.td')
-rw-r--r-- | lib/Target/PIC16/PIC16InstrInfo.td | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/lib/Target/PIC16/PIC16InstrInfo.td b/lib/Target/PIC16/PIC16InstrInfo.td new file mode 100644 index 0000000..34c9f06 --- /dev/null +++ b/lib/Target/PIC16/PIC16InstrInfo.td @@ -0,0 +1,302 @@ +//===- PIC16InstrInfo.td - PIC16 Register defs ----------------*- tblgen-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instruction format superclass +//===----------------------------------------------------------------------===// + +include "PIC16InstrFormats.td" + +//===----------------------------------------------------------------------===// +// PIC16 profiles and nodes +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// PIC16 addressing mode. +//===----------------------------------------------------------------------===// +// It matches address of globals as well as the stack slots +// that are created for locals and temporaries. This addressing mode +// converts the GlobalAddress and FrameIndex nodes to TargetGlobalAddress +// and TargetFrameIndex nodes. +def diraddrmode : ComplexPattern<i16, 2, "SelectDirectAM", [frameindex], []>; +def dirloadmode : ComplexPattern<i16, 2, "LoadNothing", [frameindex], []>; +def indirloadmode : ComplexPattern<i16, 2, "LoadFSR", [frameindex], []>; + + +// Address operand. +def mem : Operand<i16> { + let PrintMethod = "printAddrModeOperand"; + let MIOperandInfo = (ops i16imm, PTRRegs); +} + +// Instruction operand types +def simm8 : Operand<i8>; + + +// These are target-independent nodes, but have target-specific formats. +def SDT_PIC16CallSeq : SDTypeProfile<0, 1, [ SDTCisVT<0, i8> ]>; +def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PIC16CallSeq, + [SDNPHasChain, SDNPOutFlag]>; +def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PIC16CallSeq, + [SDNPHasChain, SDNPOutFlag]>; + +def PIC16Wrapper : SDNode<"PIC16ISD::Wrapper", SDTIntUnaryOp>; + +// so_imm_XFORM - Return a so_imm value packed into the format described for +// so_imm def below. +def so_imm_XFORM : SDNodeXForm<imm, [{ + return CurDAG->getTargetConstant((int8_t)N->getValue(), MVT::i32); +}]>; + +def so_imm : Operand<i8>, + PatLeaf<(imm), [{}]> { + let PrintMethod = "printSOImmOperand"; +} + + + +// PIC16 Address Mode! SDNode frameindex could possibily be a match +// since load and store instructions from stack used it. +def addr : Operand<i16>; + +// Arithmetic 2 register operands +class ArithI<bits<6> op, string instr_asm, SDNode OpNode, + Operand Od> : + LiteralFormat< op, + (outs CPURegs:$dst), + (ins CPURegs:$b, Od:$c), + !strconcat(instr_asm, " $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c))]>; + +// Memory Load/Store +class LoadDirect<bits<6> op, string instr_asm, PatFrag OpNode>: + ByteFormat< op, + (outs CPURegs:$dst), + (ins mem:$addr), + !strconcat(instr_asm, " $addr"), + [(set CPURegs:$dst, (OpNode diraddrmode:$addr))]>; + +class LoadInDirect<bits<6> op, string instr_asm, PatFrag OpNode>: + ByteFormat< op, + (outs PTRRegs:$dst), + (ins mem:$addr), + !strconcat(instr_asm, " $addr, $dst"), + [(set PTRRegs:$dst, (OpNode indirloadmode:$addr))]>; + +class StoreDirect<bits<6> op, string instr_asm, PatFrag OpNode>: + ByteFormat< op, + (outs), + (ins CPURegs:$src, mem:$addr), + !strconcat(instr_asm, " $addr"), + [(OpNode CPURegs:$src, diraddrmode:$addr)]>; + +class StoreInDirect<bits<6> op, string instr_asm, PatFrag OpNode>: + ByteFormat< op, + (outs), + (ins CPURegs:$src, PTRRegs:$fsr), + !strconcat(instr_asm, " $fsr"), + [(OpNode CPURegs:$src, PTRRegs:$fsr)]>; + +// Move +class MovLit<bits<6> op, string instr_asm>: + LiteralFormat< op, + (outs CPURegs:$dst), + (ins i8imm:$src), + !strconcat(instr_asm, " $src"), + [(set CPURegs:$dst, imm:$src)]>; + + +// Arithmetic with memory store. +// Arithmetic instrunctions involving W and memory location. +// Since W is implicit, we only print the memory operand. +class Arith1M<bits<6> op, string instr_asm, SDNode OpNode>: + ByteFormat< op, + (outs), + (ins CPURegs:$b, mem:$dst), + !strconcat(instr_asm, " $dst"), + [(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst), + (store (OpNode CPURegs:$b, (load diraddrmode:$dst)), diraddrmode:$dst)]>; + +// Arithmetic with memory load. +// Arithmetic instrunctions involving W and memory location. +// Since W is implicit, we only print the memory operand. +class Arith1R<bits<6> op, string instr_asm, SDNode OpNode>: + ByteFormat< op, + (outs CPURegs:$dst), + (ins mem:$src1, CPURegs:$src2), + !strconcat(instr_asm, " $src1"), + [(set CPURegs:$dst, (OpNode (load diraddrmode:$src1), CPURegs:$src2))]>; + +// Arithmetic with memory load. +// Arithmetic instrunctions involving W and memory location. +// Since W is implicit, we only print the memory operand. +class Arith2R<bits<6> op, string instr_asm, SDNode OpNode>: + ByteFormat< op, + (outs CPURegs:$dst), + (ins mem:$src1, CPURegs:$src2), + !strconcat(instr_asm, " $src1"), + [(set CPURegs:$dst, (OpNode CPURegs:$src2, (load diraddrmode:$src1)))]>; + +//===----------------------------------------------------------------------===// +// Instruction definition +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// PIC16I Instructions +//===----------------------------------------------------------------------===// + +// Arithmetic + +// ADDiu just accept 16-bit immediates but we handle this on Pat's. +// immZExt32 is used here so it can match GlobalAddress immediates. +// def ADDLW : ArithI<0x09, "addlw", add, so_imm>; + +let isReMaterializable = 1 in { +def MOVLW : MovLit<0x24, "movlw">; +} + +// Load/Store +def LFSR1 : LoadInDirect <0x4, "lfsr", load>; + +let isReMaterializable = 1 in { +def MOVF : LoadDirect <0x23, "movf", load>; +} + +def MOVWF : StoreDirect <0x2b, "movwf", store>; + +def MOVFSRINC : StoreInDirect <0x5, "movfsrinc", store>; + +def RETURN : ControlFormat<0x03, (outs), (ins), "return", []>; + +def ADDWF : Arith1M<0x01, "addwf", add>; +def ADDFW : Arith1R<0x02, "addfw", add>; + +def ADDWFE : Arith1M<0x03, "addwfe", adde>; +def ADDFWE : Arith1R<0x04, "addfwe", adde>; + +def ADDWFC : Arith1M<0x05, "addwfc", addc>; +def ADDFWC : Arith1R<0x06, "addfwc", addc>; + +def SUBWF : Arith1M<0x07, "subwf", sub>; +def SUBFW : Arith1R<0x08, "subfw", sub>; + +def SUBWFE : Arith1M<0x09, "subwfe", sube>; +def SUBFWE : Arith1R<0x0a, "subfwe", sube>; + +def SUBWFC : Arith1M<0x0b, "subwfc", subc>; +def SUBFWC : Arith1R<0x0d, "subfwc", subc>; + +def SUBRFW : Arith2R<0x08, "subfw", sub>; + +def SUBRFWE : Arith2R<0x0a, "subfwe", sube>; + +def SUBRFWC : Arith2R<0x0d, "subfwc", subc>; + +def brtarget : Operand<OtherVT>; + +class UncondJump< bits<4> op, string instr_asm>: + BitFormat< op, + (outs), + (ins brtarget:$target), + !strconcat(instr_asm, " $target"), + [(br bb:$target)]>; + +def GOTO : UncondJump<0x1, "goto">; + +class LogicM<bits<6> op, string instr_asm, SDNode OpNode> : + ByteFormat< op, + (outs), + (ins CPURegs:$b, mem:$dst), + !strconcat(instr_asm, " $dst"), + [(store (OpNode (load diraddrmode:$dst), CPURegs:$b), diraddrmode:$dst)]>; + +class LogicR<bits<6> op, string instr_asm, SDNode OpNode> : + ByteFormat< op, + (outs CPURegs:$dst), + (ins CPURegs:$b, mem:$c), + !strconcat(instr_asm, " $c"), + [(set CPURegs:$dst, (OpNode (load diraddrmode:$c), CPURegs:$b))]>; + +class LogicI<bits<6> op, string instr_asm, SDNode OpNode, Operand Od> : + LiteralFormat< op, + (outs CPURegs:$dst), + (ins CPURegs:$b, Od:$c), + !strconcat(instr_asm, " $c"), + [(set CPURegs:$dst, (OpNode CPURegs:$b, Od:$c ))]>; + +def XORWF : LogicM<0x1,"xorwf",xor>; +def XORFW : LogicR<0x1,"xorfw",xor>; +def XORLW : LogicI<0x1,"xorlw",xor, so_imm>; + +def ANDWF : LogicM<0x1,"andwf",and>; +def ANDFW : LogicR<0x1,"andfw",and>; +def ANDLW : LogicI<0x1,"andlw",and, so_imm>; + +def IORWF : LogicM<0x1,"iorwf",or>; +def IORFW : LogicR<0x1,"iorfw",or>; +def IORLW : LogicI<0x1,"iorlw",or, so_imm>; + + +/* For comparison before branch */ +def SDT_PIC16Cmp : SDTypeProfile<1, 3, [SDTCisSameAs<0,1>]>; +def SDTIntBinOpPIC16 : SDTypeProfile<1, 2, [SDTCisSameAs<0,1>, + SDTCisSameAs<1,2>, SDTCisInt<1>]>; + +def PIC16Cmp : SDNode<"PIC16ISD::Cmp",SDTIntBinOpPIC16, [SDNPOutFlag]>; +def PIC16XORCC : SDNode<"PIC16ISD::XORCC",SDTIntBinOpPIC16, [SDNPOutFlag]>; +def PIC16SUBCC : SDNode<"PIC16ISD::SUBCC",SDTIntBinOpPIC16, [SDNPOutFlag]>; + +def XORFWCC : LogicR<0x1,"xorfw",PIC16XORCC>; +def XORLWCC : LogicI<0x1,"xorlw",PIC16XORCC, so_imm>; +def SUBFWCC : Arith1R<0x1,"subfw",PIC16SUBCC>; +def SUBLWCC : ArithI<0x1,"sublw",PIC16SUBCC, so_imm>; + + +/* For branch conditions */ +def SDT_PIC16Branch : SDTypeProfile<0, 3, [SDTCisVT<0, OtherVT>, + SDTCisVT<1,i8>, SDTCisVT<2,i8>]>; + +def PIC16Branch : SDNode<"PIC16ISD::Branch",SDT_PIC16Branch, + [SDNPHasChain, SDNPInFlag]>; + +def PIC16BTFSS : SDNode<"PIC16ISD::BTFSS",SDT_PIC16Branch, + [SDNPHasChain, SDNPInFlag]>; + +def PIC16BTFSC : SDNode<"PIC16ISD::BTFSC",SDT_PIC16Branch, + [SDNPHasChain, SDNPInFlag]>; + +class InstrBitTestCC<bits<4> op, string instr_asm,SDNode OpNode>: + BitFormat< op, + (outs), + (ins brtarget:$target ,so_imm:$i, STATUSRegs:$s ), + !strconcat(instr_asm, " $s, $i, $target"), + [(OpNode bb:$target, so_imm:$i, STATUSRegs:$s )]>; + +def BTFSS : InstrBitTestCC<0x1,"btfss",PIC16BTFSS>; +def BTFSC : InstrBitTestCC<0x1,"btfsc",PIC16BTFSC>; + + +//===----------------------------------------------------------------------===// +// Pseudo instructions +//===----------------------------------------------------------------------===// + +let Defs = [STKPTR], Uses = [STKPTR] in { +def ADJCALLSTACKDOWN : Pseudo<255, (outs), (ins i8imm:$amt), + "!ADJCALLSTACKDOWN $amt", + [(callseq_start imm:$amt)]>; +def ADJCALLSTACKUP : Pseudo<254, (outs), (ins i8imm:$amt), + "!ADJCALLSTACKUP $amt", + [(callseq_end imm:$amt)]>; +} + + +//===----------------------------------------------------------------------===// +// Arbitrary patterns that map to one or more instructions +//===----------------------------------------------------------------------===// +def : Pat<(ret), (RETURN)>; |