| //===- 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)>; |