mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-17 06:33:21 +00:00
13a949071c
1. A delay slot filler that searches for valid instructions to fill the delay slot with. Previously NOPs would always be inserted into delay slots. 2. Support for MC based instruction printer added. 3. Support for MC based machine code generation and ELF file generation. ELF file generation does not yet completely work as much of the ELF support infrastructure is still x86/x86-64 specific. 4. General clean up of the MBlaze backend code. Much of the tablegen code has been cleanup and simplified. Bug Fixes: 1. Removed duplicate periods from subtarget feature descriptions. 2. Many of the instructions had bad machine code information in the tablegen files. Much of this has been fixed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116986 91177308-0d34-0410-b5e6-96231b3b80d8
670 lines
28 KiB
TableGen
670 lines
28 KiB
TableGen
//===- MBlazeInstrInfo.td - MBlaze Instruction defs --------*- tablegen -*-===//
|
|
//
|
|
// 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 "MBlazeInstrFormats.td"
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MBlaze type profiles
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// def SDTMBlazeSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>]>;
|
|
def SDT_MBlazeRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
|
|
def SDT_MBlazeJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
|
|
def SDT_MBCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
|
|
def SDT_MBCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MBlaze specific nodes
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
def MBlazeRet : SDNode<"MBlazeISD::Ret", SDT_MBlazeRet,
|
|
[SDNPHasChain, SDNPOptInFlag]>;
|
|
|
|
def MBlazeJmpLink : SDNode<"MBlazeISD::JmpLink",SDT_MBlazeJmpLink,
|
|
[SDNPHasChain,SDNPOptInFlag,SDNPOutFlag]>;
|
|
|
|
def MBWrapper : SDNode<"MBlazeISD::Wrap", SDTIntUnaryOp>;
|
|
|
|
def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MBCallSeqStart,
|
|
[SDNPHasChain, SDNPOutFlag]>;
|
|
|
|
def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MBCallSeqEnd,
|
|
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MBlaze Instruction Predicate Definitions.
|
|
//===----------------------------------------------------------------------===//
|
|
def HasPipe3 : Predicate<"Subtarget.hasPipe3()">;
|
|
def HasBarrel : Predicate<"Subtarget.hasBarrel()">;
|
|
def NoBarrel : Predicate<"!Subtarget.hasBarrel()">;
|
|
def HasDiv : Predicate<"Subtarget.hasDiv()">;
|
|
def HasMul : Predicate<"Subtarget.hasMul()">;
|
|
def HasFSL : Predicate<"Subtarget.hasFSL()">;
|
|
def HasEFSL : Predicate<"Subtarget.hasEFSL()">;
|
|
def HasMSRSet : Predicate<"Subtarget.hasMSRSet()">;
|
|
def HasException : Predicate<"Subtarget.hasException()">;
|
|
def HasPatCmp : Predicate<"Subtarget.hasPatCmp()">;
|
|
def HasFPU : Predicate<"Subtarget.hasFPU()">;
|
|
def HasESR : Predicate<"Subtarget.hasESR()">;
|
|
def HasPVR : Predicate<"Subtarget.hasPVR()">;
|
|
def HasMul64 : Predicate<"Subtarget.hasMul64()">;
|
|
def HasSqrt : Predicate<"Subtarget.hasSqrt()">;
|
|
def HasMMU : Predicate<"Subtarget.hasMMU()">;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MBlaze Operand, Complex Patterns and Transformations Definitions.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Instruction operand types
|
|
def brtarget : Operand<OtherVT>;
|
|
def calltarget : Operand<i32>;
|
|
def simm16 : Operand<i32>;
|
|
def uimm5 : Operand<i32>;
|
|
def fimm : Operand<f32>;
|
|
|
|
// Unsigned Operand
|
|
def uimm16 : Operand<i32> {
|
|
let PrintMethod = "printUnsignedImm";
|
|
}
|
|
|
|
// FSL Operand
|
|
def fslimm : Operand<i32> {
|
|
let PrintMethod = "printFSLImm";
|
|
}
|
|
|
|
// Address operand
|
|
def memri : Operand<i32> {
|
|
let PrintMethod = "printMemOperand";
|
|
let MIOperandInfo = (ops simm16, CPURegs);
|
|
}
|
|
|
|
def memrr : Operand<i32> {
|
|
let PrintMethod = "printMemOperand";
|
|
let MIOperandInfo = (ops CPURegs, CPURegs);
|
|
}
|
|
|
|
// Node immediate fits as 16-bit sign extended on target immediate.
|
|
def immSExt16 : PatLeaf<(imm), [{
|
|
return (N->getZExtValue() >> 16) == 0;
|
|
}]>;
|
|
|
|
// Node immediate fits as 16-bit zero extended on target immediate.
|
|
// The LO16 param means that only the lower 16 bits of the node
|
|
// immediate are caught.
|
|
// e.g. addiu, sltiu
|
|
def immZExt16 : PatLeaf<(imm), [{
|
|
return (N->getZExtValue() >> 16) == 0;
|
|
}]>;
|
|
|
|
// FSL immediate field must fit in 4 bits.
|
|
def immZExt4 : PatLeaf<(imm), [{
|
|
return N->getZExtValue() == ((N->getZExtValue()) & 0xf) ;
|
|
}]>;
|
|
|
|
// shamt field must fit in 5 bits.
|
|
def immZExt5 : PatLeaf<(imm), [{
|
|
return N->getZExtValue() == ((N->getZExtValue()) & 0x1f) ;
|
|
}]>;
|
|
|
|
// MBlaze Address Mode. SDNode frameindex could possibily be a match
|
|
// since load and store instructions from stack used it.
|
|
def iaddr : ComplexPattern<i32, 2, "SelectAddrRegImm", [frameindex], []>;
|
|
def xaddr : ComplexPattern<i32, 2, "SelectAddrRegReg", [], []>;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Pseudo instructions
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// As stack alignment is always done with addiu, we need a 16-bit immediate
|
|
let Defs = [R1], Uses = [R1] in {
|
|
def ADJCALLSTACKDOWN : MBlazePseudo<(outs), (ins simm16:$amt),
|
|
"#ADJCALLSTACKDOWN $amt",
|
|
[(callseq_start timm:$amt)]>;
|
|
def ADJCALLSTACKUP : MBlazePseudo<(outs),
|
|
(ins uimm16:$amt1, simm16:$amt2),
|
|
"#ADJCALLSTACKUP $amt1",
|
|
[(callseq_end timm:$amt1, timm:$amt2)]>;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Instructions specific format
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Arithmetic Instructions
|
|
//===----------------------------------------------------------------------===//
|
|
class Arith<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode,
|
|
InstrItinClass itin> :
|
|
TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c),
|
|
!strconcat(instr_asm, " $dst, $b, $c"),
|
|
[(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>;
|
|
|
|
class ArithI<bits<6> op, string instr_asm, SDNode OpNode,
|
|
Operand Od, PatLeaf imm_type> :
|
|
TB<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c),
|
|
!strconcat(instr_asm, " $dst, $b, $c"),
|
|
[(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))], IIAlu>;
|
|
|
|
class ArithR<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode,
|
|
InstrItinClass itin> :
|
|
TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$c, CPURegs:$b),
|
|
!strconcat(instr_asm, " $dst, $c, $b"),
|
|
[(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], itin>;
|
|
|
|
class ArithRI<bits<6> op, string instr_asm, SDNode OpNode,
|
|
Operand Od, PatLeaf imm_type> :
|
|
TBR<op, (outs CPURegs:$dst), (ins Od:$b, CPURegs:$c),
|
|
!strconcat(instr_asm, " $dst, $c, $b"),
|
|
[(set CPURegs:$dst, (OpNode imm_type:$b, CPURegs:$c))], IIAlu>;
|
|
|
|
class ArithN<bits<6> op, bits<11> flags, string instr_asm,
|
|
InstrItinClass itin> :
|
|
TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c),
|
|
!strconcat(instr_asm, " $dst, $b, $c"),
|
|
[], itin>;
|
|
|
|
class ArithNI<bits<6> op, string instr_asm,Operand Od, PatLeaf imm_type> :
|
|
TB<op, (outs CPURegs:$dst), (ins CPURegs:$b, Od:$c),
|
|
!strconcat(instr_asm, " $dst, $b, $c"),
|
|
[], IIAlu>;
|
|
|
|
class ArithRN<bits<6> op, bits<11> flags, string instr_asm,
|
|
InstrItinClass itin> :
|
|
TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$c, CPURegs:$b),
|
|
!strconcat(instr_asm, " $dst, $b, $c"),
|
|
[], itin>;
|
|
|
|
class ArithRNI<bits<6> op, string instr_asm,Operand Od, PatLeaf imm_type> :
|
|
TB<op, (outs CPURegs:$dst), (ins Od:$c, CPURegs:$b),
|
|
!strconcat(instr_asm, " $dst, $b, $c"),
|
|
[], IIAlu>;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Misc Arithmetic Instructions
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
class Logic<bits<6> op, bits<11> flags, string instr_asm, SDNode OpNode> :
|
|
TA<op, flags, (outs CPURegs:$dst), (ins CPURegs:$b, CPURegs:$c),
|
|
!strconcat(instr_asm, " $dst, $b, $c"),
|
|
[(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))], IIAlu>;
|
|
|
|
class LogicI<bits<6> op, string instr_asm, SDNode OpNode> :
|
|
TB<op, (outs CPURegs:$dst), (ins CPURegs:$b, uimm16:$c),
|
|
!strconcat(instr_asm, " $dst, $b, $c"),
|
|
[(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt16:$c))],
|
|
IIAlu>;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Memory Access Instructions
|
|
//===----------------------------------------------------------------------===//
|
|
class LoadM<bits<6> op, string instr_asm, PatFrag OpNode> :
|
|
TA<op, 0x000, (outs CPURegs:$dst), (ins memrr:$addr),
|
|
!strconcat(instr_asm, " $dst, $addr"),
|
|
[(set CPURegs:$dst, (OpNode xaddr:$addr))], IILoad>;
|
|
|
|
class LoadMI<bits<6> op, string instr_asm, PatFrag OpNode> :
|
|
TBR<op, (outs CPURegs:$dst), (ins memri:$addr),
|
|
!strconcat(instr_asm, " $dst, $addr"),
|
|
[(set CPURegs:$dst, (OpNode iaddr:$addr))], IILoad>;
|
|
|
|
class StoreM<bits<6> op, string instr_asm, PatFrag OpNode> :
|
|
TA<op, 0x000, (outs), (ins CPURegs:$dst, memrr:$addr),
|
|
!strconcat(instr_asm, " $dst, $addr"),
|
|
[(OpNode CPURegs:$dst, xaddr:$addr)], IIStore>;
|
|
|
|
class StoreMI<bits<6> op, string instr_asm, PatFrag OpNode> :
|
|
TBR<op, (outs), (ins CPURegs:$dst, memri:$addr),
|
|
!strconcat(instr_asm, " $dst, $addr"),
|
|
[(OpNode CPURegs:$dst, iaddr:$addr)], IIStore>;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Branch Instructions
|
|
//===----------------------------------------------------------------------===//
|
|
class Branch<bits<6> op, bits<5> br, bits<11> flags, string instr_asm> :
|
|
TA<op, flags, (outs), (ins CPURegs:$target),
|
|
!strconcat(instr_asm, " $target"),
|
|
[], IIBranch> {
|
|
let rd = 0x0;
|
|
let ra = br;
|
|
}
|
|
|
|
class BranchI<bits<6> op, bits<5> br, string instr_asm> :
|
|
TB<op, (outs), (ins brtarget:$target),
|
|
!strconcat(instr_asm, " $target"),
|
|
[], IIBranch> {
|
|
let rd = 0;
|
|
let ra = br;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Branch and Link Instructions
|
|
//===----------------------------------------------------------------------===//
|
|
class BranchL<bits<6> op, bits<5> br, bits<11> flags, string instr_asm> :
|
|
TA<op, flags, (outs), (ins CPURegs:$target),
|
|
!strconcat(instr_asm, " r15, $target"),
|
|
[], IIBranch> {
|
|
let rd = 15;
|
|
let ra = br;
|
|
}
|
|
|
|
class BranchLI<bits<6> op, bits<5> br, string instr_asm> :
|
|
TB<op, (outs), (ins calltarget:$target),
|
|
!strconcat(instr_asm, " r15, $target"),
|
|
[], IIBranch> {
|
|
let rd = 15;
|
|
let ra = br;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Conditional Branch Instructions
|
|
//===----------------------------------------------------------------------===//
|
|
class BranchC<bits<6> op, bits<5> br, bits<11> flags, string instr_asm,
|
|
PatFrag cond_op> :
|
|
TA<op, flags, (outs),
|
|
(ins CPURegs:$a, CPURegs:$b, brtarget:$offset),
|
|
!strconcat(instr_asm, " $a, $b, $offset"),
|
|
[], IIBranch> {
|
|
let rd = br;
|
|
}
|
|
|
|
class BranchCI<bits<6> op, bits<5> br, string instr_asm, PatFrag cond_op> :
|
|
TB<op, (outs), (ins CPURegs:$a, brtarget:$offset),
|
|
!strconcat(instr_asm, " $a, $offset"),
|
|
[], IIBranch> {
|
|
let rd = br;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MBlaze arithmetic instructions
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
let isCommutable = 1, isAsCheapAsAMove = 1 in {
|
|
def ADD : Arith<0x00, 0x000, "add ", add, IIAlu>;
|
|
def ADDC : Arith<0x02, 0x000, "addc ", adde, IIAlu>;
|
|
def ADDK : Arith<0x04, 0x000, "addk ", addc, IIAlu>;
|
|
def ADDKC : ArithN<0x06, 0x000, "addkc ", IIAlu>;
|
|
def AND : Logic<0x21, 0x000, "and ", and>;
|
|
def OR : Logic<0x20, 0x000, "or ", or>;
|
|
def XOR : Logic<0x22, 0x000, "xor ", xor>;
|
|
}
|
|
|
|
let isAsCheapAsAMove = 1 in {
|
|
def ANDN : ArithN<0x23, 0x000, "andn ", IIAlu>;
|
|
def CMP : ArithN<0x05, 0x001, "cmp ", IIAlu>;
|
|
def CMPU : ArithN<0x05, 0x003, "cmpu ", IIAlu>;
|
|
def RSUB : ArithR<0x01, 0x000, "rsub ", sub, IIAlu>;
|
|
def RSUBC : ArithR<0x03, 0x000, "rsubc ", sube, IIAlu>;
|
|
def RSUBK : ArithR<0x05, 0x000, "rsubk ", subc, IIAlu>;
|
|
def RSUBKC : ArithRN<0x07, 0x000, "rsubkc ", IIAlu>;
|
|
}
|
|
|
|
let isCommutable = 1, Predicates=[HasMul] in {
|
|
def MUL : Arith<0x10, 0x000, "mul ", mul, IIAlu>;
|
|
}
|
|
|
|
let isCommutable = 1, Predicates=[HasMul,HasMul64] in {
|
|
def MULH : Arith<0x10, 0x001, "mulh ", mulhs, IIAlu>;
|
|
def MULHU : Arith<0x10, 0x003, "mulhu ", mulhu, IIAlu>;
|
|
}
|
|
|
|
let Predicates=[HasMul,HasMul64] in {
|
|
def MULHSU : ArithN<0x10, 0x002, "mulhsu ", IIAlu>;
|
|
}
|
|
|
|
let Predicates=[HasBarrel] in {
|
|
def BSRL : Arith<0x11, 0x000, "bsrl ", srl, IIAlu>;
|
|
def BSRA : Arith<0x11, 0x200, "bsra ", sra, IIAlu>;
|
|
def BSLL : Arith<0x11, 0x400, "bsll ", shl, IIAlu>;
|
|
def BSRLI : ArithI<0x11, "bsrli ", srl, uimm5, immZExt5>;
|
|
def BSRAI : ArithI<0x11, "bsrai ", sra, uimm5, immZExt5>;
|
|
def BSLLI : ArithI<0x11, "bslli ", shl, uimm5, immZExt5>;
|
|
}
|
|
|
|
let Predicates=[HasDiv] in {
|
|
def IDIV : Arith<0x12, 0x000, "idiv ", sdiv, IIAlu>;
|
|
def IDIVU : Arith<0x12, 0x002, "idivu ", udiv, IIAlu>;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MBlaze immediate mode arithmetic instructions
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
let isAsCheapAsAMove = 1 in {
|
|
def ADDI : ArithI<0x08, "addi ", add, simm16, immSExt16>;
|
|
def ADDIC : ArithNI<0x0A, "addic ", simm16, immSExt16>;
|
|
def ADDIK : ArithNI<0x0C, "addik ", simm16, immSExt16>;
|
|
def ADDIKC : ArithI<0x0E, "addikc ", addc, simm16, immSExt16>;
|
|
def RSUBI : ArithRI<0x09, "rsubi ", sub, simm16, immSExt16>;
|
|
def RSUBIC : ArithRNI<0x0B, "rsubi ", simm16, immSExt16>;
|
|
def RSUBIK : ArithRNI<0x0E, "rsubic ", simm16, immSExt16>;
|
|
def RSUBIKC : ArithRI<0x0F, "rsubikc", subc, simm16, immSExt16>;
|
|
def ANDNI : ArithNI<0x2B, "andni ", uimm16, immZExt16>;
|
|
def ANDI : LogicI<0x29, "andi ", and>;
|
|
def ORI : LogicI<0x28, "ori ", or>;
|
|
def XORI : LogicI<0x2A, "xori ", xor>;
|
|
}
|
|
|
|
let Predicates=[HasMul] in {
|
|
def MULI : ArithI<0x18, "muli ", mul, simm16, immSExt16>;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MBlaze memory access instructions
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
let canFoldAsLoad = 1, isReMaterializable = 1 in {
|
|
def LBU : LoadM<0x30, "lbu ", zextloadi8>;
|
|
def LHU : LoadM<0x31, "lhu ", zextloadi16>;
|
|
def LW : LoadM<0x32, "lw ", load>;
|
|
|
|
def LBUI : LoadMI<0x38, "lbui ", zextloadi8>;
|
|
def LHUI : LoadMI<0x39, "lhui ", zextloadi16>;
|
|
def LWI : LoadMI<0x3A, "lwi ", load>;
|
|
}
|
|
|
|
def SB : StoreM<0x34, "sb ", truncstorei8>;
|
|
def SH : StoreM<0x35, "sh ", truncstorei16>;
|
|
def SW : StoreM<0x36, "sw ", store>;
|
|
|
|
def SBI : StoreMI<0x3C, "sbi ", truncstorei8>;
|
|
def SHI : StoreMI<0x3D, "shi ", truncstorei16>;
|
|
def SWI : StoreMI<0x3E, "swi ", store>;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MBlaze branch instructions
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, isBarrier = 1,
|
|
Form = FI in {
|
|
def BRI : BranchI<0x2E, 0x00, "bri ">;
|
|
def BRAI : BranchI<0x2E, 0x08, "brai ">;
|
|
}
|
|
|
|
let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, Form = FRI in {
|
|
def BEQI : BranchCI<0x2F, 0x00, "beqi ", seteq>;
|
|
def BNEI : BranchCI<0x2F, 0x01, "bnei ", setne>;
|
|
def BLTI : BranchCI<0x2F, 0x02, "blti ", setlt>;
|
|
def BLEI : BranchCI<0x2F, 0x03, "blei ", setle>;
|
|
def BGTI : BranchCI<0x2F, 0x04, "bgti ", setgt>;
|
|
def BGEI : BranchCI<0x2F, 0x05, "bgei ", setge>;
|
|
}
|
|
|
|
let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, hasCtrlDep = 1,
|
|
isBarrier = 1, Form = FR in {
|
|
def BR : Branch<0x26, 0x00, 0x000, "br ">;
|
|
def BRA : Branch<0x26, 0x08, 0x000, "bra ">;
|
|
}
|
|
|
|
let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, hasCtrlDep = 1,
|
|
Form = FRR in {
|
|
def BEQ : BranchC<0x27, 0x00, 0x000, "beq ", seteq>;
|
|
def BNE : BranchC<0x27, 0x01, 0x000, "bne ", setne>;
|
|
def BLT : BranchC<0x27, 0x02, 0x000, "blt ", setlt>;
|
|
def BLE : BranchC<0x27, 0x03, 0x000, "ble ", setle>;
|
|
def BGT : BranchC<0x27, 0x04, 0x000, "bgt ", setgt>;
|
|
def BGE : BranchC<0x27, 0x05, 0x000, "bge ", setge>;
|
|
}
|
|
|
|
let isBranch = 1, isTerminator = 1, hasDelaySlot = 1, hasCtrlDep = 1,
|
|
isBarrier = 1, Form = FI in {
|
|
def BRID : BranchI<0x2E, 0x10, "brid ">;
|
|
def BRAID : BranchI<0x2E, 0x18, "braid ">;
|
|
}
|
|
|
|
let isBranch = 1, isTerminator = 1, hasDelaySlot = 1, hasCtrlDep = 1,
|
|
Form = FRI in {
|
|
def BEQID : BranchCI<0x2F, 0x10, "beqid ", seteq>;
|
|
def BNEID : BranchCI<0x2F, 0x11, "bneid ", setne>;
|
|
def BLTID : BranchCI<0x2F, 0x12, "bltid ", setlt>;
|
|
def BLEID : BranchCI<0x2F, 0x13, "bleid ", setle>;
|
|
def BGTID : BranchCI<0x2F, 0x14, "bgtid ", setgt>;
|
|
def BGEID : BranchCI<0x2F, 0x15, "bgeid ", setge>;
|
|
}
|
|
|
|
let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, Form = FR,
|
|
hasDelaySlot = 1, hasCtrlDep = 1, isBarrier = 1 in {
|
|
def BRD : Branch<0x26, 0x10, 0x000, "brd ">;
|
|
def BRAD : Branch<0x26, 0x18, 0x000, "brad ">;
|
|
}
|
|
|
|
let isBranch = 1, isIndirectBranch = 1, isTerminator = 1,
|
|
hasDelaySlot = 1, hasCtrlDep = 1, Form = FRR in {
|
|
def BEQD : BranchC<0x27, 0x10, 0x000, "beqd ", seteq>;
|
|
def BNED : BranchC<0x27, 0x11, 0x000, "bned ", setne>;
|
|
def BLTD : BranchC<0x27, 0x12, 0x000, "bltd ", setlt>;
|
|
def BLED : BranchC<0x27, 0x13, 0x000, "bled ", setle>;
|
|
def BGTD : BranchC<0x27, 0x14, 0x000, "bgtd ", setgt>;
|
|
def BGED : BranchC<0x27, 0x15, 0x000, "bged ", setge>;
|
|
}
|
|
|
|
let isCall = 1, hasDelaySlot = 1, hasCtrlDep = 1, isBarrier = 1, Form = FI,
|
|
Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12],
|
|
Uses = [R1,R5,R6,R7,R8,R9,R10] in {
|
|
def BRLID : BranchLI<0x2E, 0x14, "brlid ">;
|
|
def BRALID : BranchLI<0x2E, 0x1C, "bralid ">;
|
|
}
|
|
|
|
let isCall = 1, hasDelaySlot = 1, hasCtrlDep = 1, isIndirectBranch = 1,
|
|
isBarrier = 1, Form = FR,
|
|
Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12],
|
|
Uses = [R1,R5,R6,R7,R8,R9,R10] in {
|
|
def BRLD : BranchL<0x26, 0x14, 0x000, "brld ">;
|
|
def BRALD : BranchL<0x26, 0x1C, 0x000, "brald ">;
|
|
}
|
|
|
|
let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1,
|
|
hasCtrlDep=1, rd=0x10, imm16=0x8, Form=FR in {
|
|
def RTSD : TB<0x2D, (outs), (ins CPURegs:$target),
|
|
"rtsd $target, 8",
|
|
[(MBlazeRet CPURegs:$target)],
|
|
IIBranch>;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// MBlaze misc instructions
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
let neverHasSideEffects = 1 in {
|
|
def NOP : MBlazeInst< 0x20, FRRR, (outs), (ins), "nop ", [], IIAlu>;
|
|
}
|
|
|
|
let usesCustomInserter = 1 in {
|
|
def Select_CC : MBlazePseudo<(outs CPURegs:$dst),
|
|
(ins CPURegs:$T, CPURegs:$F, CPURegs:$CMP, i32imm:$CC),
|
|
"; SELECT_CC PSEUDO!",
|
|
[]>;
|
|
|
|
def ShiftL : MBlazePseudo<(outs CPURegs:$dst),
|
|
(ins CPURegs:$L, CPURegs:$R),
|
|
"; ShiftL PSEUDO!",
|
|
[]>;
|
|
|
|
def ShiftRA : MBlazePseudo<(outs CPURegs:$dst),
|
|
(ins CPURegs:$L, CPURegs:$R),
|
|
"; ShiftRA PSEUDO!",
|
|
[]>;
|
|
|
|
def ShiftRL : MBlazePseudo<(outs CPURegs:$dst),
|
|
(ins CPURegs:$L, CPURegs:$R),
|
|
"; ShiftRL PSEUDO!",
|
|
[]>;
|
|
}
|
|
|
|
|
|
let rb = 0 in {
|
|
def SEXT16 : TA<0x24, 0x061, (outs CPURegs:$dst), (ins CPURegs:$src),
|
|
"sext16 $dst, $src", [], IIAlu>;
|
|
def SEXT8 : TA<0x24, 0x060, (outs CPURegs:$dst), (ins CPURegs:$src),
|
|
"sext8 $dst, $src", [], IIAlu>;
|
|
def SRL : TA<0x24, 0x041, (outs CPURegs:$dst), (ins CPURegs:$src),
|
|
"srl $dst, $src", [], IIAlu>;
|
|
def SRA : TA<0x24, 0x001, (outs CPURegs:$dst), (ins CPURegs:$src),
|
|
"sra $dst, $src", [], IIAlu>;
|
|
def SRC : TA<0x24, 0x021, (outs CPURegs:$dst), (ins CPURegs:$src),
|
|
"src $dst, $src", [], IIAlu>;
|
|
}
|
|
|
|
let opcode=0x08 in {
|
|
def LEA_ADDI : TB<0x08, (outs CPURegs:$dst), (ins memri:$addr),
|
|
"addi $dst, ${addr:stackloc}",
|
|
[(set CPURegs:$dst, iaddr:$addr)], IIAlu>;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Arbitrary patterns that map to one or more instructions
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Small immediates
|
|
def : Pat<(i32 0), (ADD R0, R0)>;
|
|
def : Pat<(i32 immSExt16:$imm), (ADDI R0, imm:$imm)>;
|
|
def : Pat<(i32 immZExt16:$imm), (ORI R0, imm:$imm)>;
|
|
|
|
// Arbitrary immediates
|
|
def : Pat<(i32 imm:$imm), (ADDI R0, imm:$imm)>;
|
|
|
|
// In register sign extension
|
|
def : Pat<(sext_inreg CPURegs:$src, i16), (SEXT16 CPURegs:$src)>;
|
|
def : Pat<(sext_inreg CPURegs:$src, i8), (SEXT8 CPURegs:$src)>;
|
|
|
|
// Call
|
|
def : Pat<(MBlazeJmpLink (i32 tglobaladdr:$dst)), (BRLID tglobaladdr:$dst)>;
|
|
def : Pat<(MBlazeJmpLink (i32 texternalsym:$dst)),(BRLID texternalsym:$dst)>;
|
|
def : Pat<(MBlazeJmpLink CPURegs:$dst), (BRLD CPURegs:$dst)>;
|
|
|
|
// Shift Instructions
|
|
def : Pat<(shl CPURegs:$L, CPURegs:$R), (ShiftL CPURegs:$L, CPURegs:$R)>;
|
|
def : Pat<(sra CPURegs:$L, CPURegs:$R), (ShiftRA CPURegs:$L, CPURegs:$R)>;
|
|
def : Pat<(srl CPURegs:$L, CPURegs:$R), (ShiftRL CPURegs:$L, CPURegs:$R)>;
|
|
|
|
// SET_CC operations
|
|
def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETEQ),
|
|
(Select_CC (ADDI R0, 1), (ADDI R0, 0),
|
|
(CMP CPURegs:$L, CPURegs:$R), 1)>;
|
|
def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETNE),
|
|
(Select_CC (ADDI R0, 1), (ADDI R0, 0),
|
|
(CMP CPURegs:$L, CPURegs:$R), 2)>;
|
|
def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETGT),
|
|
(Select_CC (ADDI R0, 1), (ADDI R0, 0),
|
|
(CMP CPURegs:$L, CPURegs:$R), 3)>;
|
|
def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETLT),
|
|
(Select_CC (ADDI R0, 1), (ADDI R0, 0),
|
|
(CMP CPURegs:$L, CPURegs:$R), 4)>;
|
|
def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETGE),
|
|
(Select_CC (ADDI R0, 1), (ADDI R0, 0),
|
|
(CMP CPURegs:$L, CPURegs:$R), 5)>;
|
|
def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETLE),
|
|
(Select_CC (ADDI R0, 1), (ADDI R0, 0),
|
|
(CMP CPURegs:$L, CPURegs:$R), 6)>;
|
|
def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETUGT),
|
|
(Select_CC (ADDI R0, 1), (ADDI R0, 0),
|
|
(CMPU CPURegs:$L, CPURegs:$R), 3)>;
|
|
def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETULT),
|
|
(Select_CC (ADDI R0, 1), (ADDI R0, 0),
|
|
(CMPU CPURegs:$L, CPURegs:$R), 4)>;
|
|
def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETUGE),
|
|
(Select_CC (ADDI R0, 1), (ADDI R0, 0),
|
|
(CMPU CPURegs:$L, CPURegs:$R), 5)>;
|
|
def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETULE),
|
|
(Select_CC (ADDI R0, 1), (ADDI R0, 0),
|
|
(CMPU CPURegs:$L, CPURegs:$R), 6)>;
|
|
|
|
// SELECT operations
|
|
def : Pat<(select CPURegs:$C, CPURegs:$T, CPURegs:$F),
|
|
(Select_CC CPURegs:$T, CPURegs:$F, CPURegs:$C, 2)>;
|
|
|
|
// SELECT_CC
|
|
def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETEQ),
|
|
(Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 1)>;
|
|
def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETNE),
|
|
(Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 2)>;
|
|
def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETGT),
|
|
(Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 3)>;
|
|
def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETLT),
|
|
(Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 4)>;
|
|
def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETGE),
|
|
(Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 5)>;
|
|
def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETLE),
|
|
(Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 6)>;
|
|
def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETUGT),
|
|
(Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 3)>;
|
|
def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETULT),
|
|
(Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 4)>;
|
|
def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETUGE),
|
|
(Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 5)>;
|
|
def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETULE),
|
|
(Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 6)>;
|
|
|
|
// BR instructions
|
|
def : Pat<(br bb:$T), (BRID bb:$T)>;
|
|
def : Pat<(brind CPURegs:$T), (BRD CPURegs:$T)>;
|
|
|
|
// BRCOND instructions
|
|
def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETEQ), bb:$T),
|
|
(BEQID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>;
|
|
def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETNE), bb:$T),
|
|
(BNEID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>;
|
|
def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETGT), bb:$T),
|
|
(BGTID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>;
|
|
def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETLT), bb:$T),
|
|
(BLTID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>;
|
|
def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETGE), bb:$T),
|
|
(BGEID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>;
|
|
def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETLE), bb:$T),
|
|
(BLEID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>;
|
|
def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETUGT), bb:$T),
|
|
(BGTID (CMPU CPURegs:$R, CPURegs:$L), bb:$T)>;
|
|
def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETULT), bb:$T),
|
|
(BLTID (CMPU CPURegs:$R, CPURegs:$L), bb:$T)>;
|
|
def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETUGE), bb:$T),
|
|
(BGEID (CMPU CPURegs:$R, CPURegs:$L), bb:$T)>;
|
|
def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETULE), bb:$T),
|
|
(BLEID (CMPU CPURegs:$R, CPURegs:$L), bb:$T)>;
|
|
def : Pat<(brcond CPURegs:$C, bb:$T),
|
|
(BNEID CPURegs:$C, bb:$T)>;
|
|
|
|
// Jump tables, global addresses, and constant pools
|
|
def : Pat<(MBWrapper tglobaladdr:$in), (ORI R0, tglobaladdr:$in)>;
|
|
def : Pat<(MBWrapper tjumptable:$in), (ORI R0, tjumptable:$in)>;
|
|
def : Pat<(MBWrapper tconstpool:$in), (ORI R0, tconstpool:$in)>;
|
|
|
|
// Misc instructions
|
|
def : Pat<(and CPURegs:$lh, (not CPURegs:$rh)),(ANDN CPURegs:$lh, CPURegs:$rh)>;
|
|
|
|
// Arithmetic with immediates
|
|
def : Pat<(add CPURegs:$in, imm:$imm),(ADDI CPURegs:$in, imm:$imm)>;
|
|
def : Pat<(or CPURegs:$in, imm:$imm),(ORI CPURegs:$in, imm:$imm)>;
|
|
def : Pat<(xor CPURegs:$in, imm:$imm),(XORI CPURegs:$in, imm:$imm)>;
|
|
|
|
// extended load and stores
|
|
def : Pat<(extloadi1 iaddr:$src), (LBUI iaddr:$src)>;
|
|
def : Pat<(extloadi8 iaddr:$src), (LBUI iaddr:$src)>;
|
|
def : Pat<(extloadi16 iaddr:$src), (LHUI iaddr:$src)>;
|
|
def : Pat<(extloadi1 xaddr:$src), (LBU xaddr:$src)>;
|
|
def : Pat<(extloadi8 xaddr:$src), (LBU xaddr:$src)>;
|
|
def : Pat<(extloadi16 xaddr:$src), (LHU xaddr:$src)>;
|
|
|
|
def : Pat<(sextloadi1 iaddr:$src), (SEXT8 (LBUI iaddr:$src))>;
|
|
def : Pat<(sextloadi8 iaddr:$src), (SEXT8 (LBUI iaddr:$src))>;
|
|
def : Pat<(sextloadi16 iaddr:$src), (SEXT16 (LHUI iaddr:$src))>;
|
|
def : Pat<(sextloadi1 xaddr:$src), (SEXT8 (LBU xaddr:$src))>;
|
|
def : Pat<(sextloadi8 xaddr:$src), (SEXT8 (LBU xaddr:$src))>;
|
|
def : Pat<(sextloadi16 xaddr:$src), (SEXT16 (LHU xaddr:$src))>;
|
|
|
|
// peepholes
|
|
def : Pat<(store (i32 0), iaddr:$dst), (SWI R0, iaddr:$dst)>;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Floating Point Support
|
|
//===----------------------------------------------------------------------===//
|
|
include "MBlazeInstrFSL.td"
|
|
include "MBlazeInstrFPU.td"
|