| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 1 | //===- MipsInstrInfo.td - Mips Register defs --------------------*- C++ -*-===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file was developed by Bruno Cardoso Lopes and is distributed under the | 
|  | 6 | // University of Illinois Open Source License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 |  | 
|  | 10 | //===----------------------------------------------------------------------===// | 
|  | 11 | // Instruction format superclass | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
|  | 14 | include "MipsInstrFormats.td" | 
|  | 15 |  | 
|  | 16 | //===----------------------------------------------------------------------===// | 
|  | 17 | // Mips profiles and nodes | 
|  | 18 | //===----------------------------------------------------------------------===// | 
|  | 19 |  | 
|  | 20 | // Call | 
|  | 21 | def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>; | 
|  | 22 | def MipsJmpLink     : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain, | 
|  | 23 | SDNPOutFlag]>; | 
|  | 24 |  | 
|  | 25 | // Hi and Lo nodes are created to let easy manipulation of 16-bit when | 
|  | 26 | // handling 32-bit immediates. They are used on MipsISelLowering to | 
|  | 27 | // lower stuff like GlobalAddress, ExternalSymbol, ... | 
|  | 28 | // This two nodes have nothing to do with Mips Registers Hi and Lo. | 
|  | 29 | def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp>; | 
|  | 30 | def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; | 
|  | 31 |  | 
|  | 32 | // Return | 
|  | 33 | def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; | 
|  | 34 | def MipsRet     : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain, | 
|  | 35 | SDNPOptInFlag]>; | 
|  | 36 |  | 
|  | 37 | // These are target-independent nodes, but have target-specific formats. | 
|  | 38 | def SDT_MipsCallSeq : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; | 
|  | 39 | def callseq_start   : SDNode<"ISD::CALLSEQ_START", SDT_MipsCallSeq, | 
|  | 40 | [SDNPHasChain, SDNPOutFlag]>; | 
|  | 41 | def callseq_end     : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeq, | 
|  | 42 | [SDNPHasChain, SDNPOutFlag]>; | 
|  | 43 |  | 
|  | 44 | // Instruction operand types | 
|  | 45 | def brtarget    : Operand<OtherVT>; | 
|  | 46 | def calltarget  : Operand<i32>; | 
|  | 47 | def uimm16      : Operand<i32>; | 
|  | 48 | def simm16      : Operand<i32>; | 
|  | 49 | def shamt       : Operand<i32>; | 
|  | 50 |  | 
|  | 51 | // Address operand | 
|  | 52 | def mem : Operand<i32> { | 
|  | 53 | let PrintMethod = "printMemOperand"; | 
|  | 54 | let MIOperandInfo = (ops simm16, CPURegs); | 
|  | 55 | } | 
|  | 56 |  | 
|  | 57 | //===----------------------------------------------------------------------===// | 
|  | 58 | // Mips Patterns and Transformations | 
|  | 59 | //===----------------------------------------------------------------------===// | 
|  | 60 |  | 
|  | 61 | // Transformation Function - get the lower 16 bits. | 
|  | 62 | def LO16 : SDNodeXForm<imm, [{ | 
|  | 63 | return getI32Imm((unsigned)N->getValue() & 0xFFFF); | 
|  | 64 | }]>; | 
|  | 65 |  | 
|  | 66 | // Transformation Function - get the higher 16 bits. | 
|  | 67 | def HI16 : SDNodeXForm<imm, [{ | 
|  | 68 | return getI32Imm((unsigned)N->getValue() >> 16); | 
|  | 69 | }]>; | 
|  | 70 |  | 
|  | 71 | // Node immediate fits as 16-bit sign extended on target immediate. | 
|  | 72 | // e.g. addi, andi | 
|  | 73 | def immSExt16  : PatLeaf<(imm), [{ | 
|  | 74 | if (N->getValueType(0) == MVT::i32) | 
|  | 75 | return (int32_t)N->getValue() == (short)N->getValue(); | 
| Bruno Cardoso Lopes | c5affec | 2007-07-11 22:47:02 +0000 | [diff] [blame] | 76 | else | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 77 | return (int64_t)N->getValue() == (short)N->getValue(); | 
|  | 78 | }]>; | 
|  | 79 |  | 
|  | 80 | // Node immediate fits as 16-bit zero extended on target immediate. | 
|  | 81 | // The LO16 param means that only the lower 16 bits of the node | 
|  | 82 | // immediate are caught. | 
|  | 83 | // e.g. addiu, sltiu | 
|  | 84 | def immZExt16  : PatLeaf<(imm), [{ | 
| Bruno Cardoso Lopes | c5affec | 2007-07-11 22:47:02 +0000 | [diff] [blame] | 85 | if (N->getValueType(0) == MVT::i32) | 
|  | 86 | return (uint32_t)N->getValue() == (unsigned short)N->getValue(); | 
|  | 87 | else | 
|  | 88 | return (uint64_t)N->getValue() == (unsigned short)N->getValue(); | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 89 | }], LO16>; | 
|  | 90 |  | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 91 | // shamt field must fit in 5 bits. | 
|  | 92 | def immZExt5 : PatLeaf<(imm), [{ | 
|  | 93 | return N->getValue() == ((N->getValue()) & 0x1f) ; | 
|  | 94 | }]>; | 
|  | 95 |  | 
|  | 96 | // Mips Address Mode! SDNode frameindex could possibily be a match | 
|  | 97 | // since load and store instructions from stack used it. | 
|  | 98 | def addr : ComplexPattern<i32, 2, "SelectAddr", [frameindex], []>; | 
|  | 99 |  | 
|  | 100 | //===----------------------------------------------------------------------===// | 
|  | 101 | // Instructions specific format | 
|  | 102 | //===----------------------------------------------------------------------===// | 
|  | 103 |  | 
|  | 104 | // Arithmetic 3 register operands | 
|  | 105 | let isCommutable = 1 in | 
|  | 106 | class ArithR< bits<6> op, bits<6> func, string instr_asm, SDNode OpNode>: | 
|  | 107 | FR< op, | 
|  | 108 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 109 | (outs CPURegs:$dst), | 
|  | 110 | (ins CPURegs:$b, CPURegs:$c), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 111 | !strconcat(instr_asm, " $dst, $b, $c"), | 
|  | 112 | [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))] >; | 
|  | 113 |  | 
|  | 114 | let isCommutable = 1 in | 
|  | 115 | class ArithOverflowR< bits<6> op, bits<6> func, string instr_asm>: | 
|  | 116 | FR< op, | 
|  | 117 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 118 | (outs CPURegs:$dst), | 
|  | 119 | (ins CPURegs:$b, CPURegs:$c), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 120 | !strconcat(instr_asm, " $dst, $b, $c"), | 
|  | 121 | []>; | 
|  | 122 |  | 
|  | 123 | // Arithmetic 2 register operands | 
|  | 124 | let isCommutable = 1 in | 
|  | 125 | class ArithI<bits<6> op, string instr_asm, SDNode OpNode, | 
|  | 126 | Operand Od, PatLeaf imm_type> : | 
|  | 127 | FI< op, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 128 | (outs CPURegs:$dst), | 
|  | 129 | (ins CPURegs:$b, Od:$c), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 130 | !strconcat(instr_asm, " $dst, $b, $c"), | 
|  | 131 | [(set CPURegs:$dst, (OpNode CPURegs:$b, imm_type:$c))] >; | 
|  | 132 |  | 
|  | 133 | // Arithmetic Multiply ADD/SUB | 
|  | 134 | let rd=0 in | 
|  | 135 | class MArithR<bits<6> func, string instr_asm> : | 
|  | 136 | FR< 0x1c, | 
|  | 137 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 138 | (outs CPURegs:$rs), | 
|  | 139 | (ins CPURegs:$rt), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 140 | !strconcat(instr_asm, " $rs, $rt"), | 
|  | 141 | []>; | 
|  | 142 |  | 
|  | 143 | //  Logical | 
|  | 144 | class LogicR<bits<6> func, string instr_asm, SDNode OpNode>: | 
|  | 145 | FR< 0x00, | 
|  | 146 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 147 | (outs CPURegs:$dst), | 
|  | 148 | (ins CPURegs:$b, CPURegs:$c), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 149 | !strconcat(instr_asm, " $dst, $b, $c"), | 
|  | 150 | [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))] >; | 
|  | 151 |  | 
|  | 152 | class LogicI<bits<6> op, string instr_asm, SDNode OpNode>: | 
|  | 153 | FI< op, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 154 | (outs CPURegs:$dst), | 
|  | 155 | (ins CPURegs:$b, uimm16:$c), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 156 | !strconcat(instr_asm, " $dst, $b, $c"), | 
|  | 157 | [(set CPURegs:$dst, (OpNode CPURegs:$b, immSExt16:$c))]>; | 
|  | 158 |  | 
|  | 159 | class LogicNOR<bits<6> op, bits<6> func, string instr_asm>: | 
|  | 160 | FR< op, | 
|  | 161 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 162 | (outs CPURegs:$dst), | 
|  | 163 | (ins CPURegs:$b, CPURegs:$c), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 164 | !strconcat(instr_asm, " $dst, $b, $c"), | 
|  | 165 | [(set CPURegs:$dst, (not (or CPURegs:$b, CPURegs:$c)))] >; | 
|  | 166 |  | 
|  | 167 | // Shifts | 
|  | 168 | let rt = 0 in | 
|  | 169 | class LogicR_shift_imm<bits<6> func, string instr_asm, SDNode OpNode>: | 
|  | 170 | FR< 0x00, | 
|  | 171 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 172 | (outs CPURegs:$dst), | 
|  | 173 | (ins CPURegs:$b, shamt:$c), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 174 | !strconcat(instr_asm, " $dst, $b, $c"), | 
|  | 175 | [(set CPURegs:$dst, (OpNode CPURegs:$b, immZExt5:$c))] >; | 
|  | 176 |  | 
|  | 177 | class LogicR_shift_reg<bits<6> func, string instr_asm, SDNode OpNode>: | 
|  | 178 | FR< 0x00, | 
|  | 179 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 180 | (outs CPURegs:$dst), | 
|  | 181 | (ins CPURegs:$b, CPURegs:$c), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 182 | !strconcat(instr_asm, " $dst, $b, $c"), | 
|  | 183 | [(set CPURegs:$dst, (OpNode CPURegs:$b, CPURegs:$c))] >; | 
|  | 184 |  | 
|  | 185 | // Load Upper Imediate | 
|  | 186 | class LoadUpper<bits<6> op, string instr_asm>: | 
|  | 187 | FI< op, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 188 | (outs CPURegs:$dst), | 
|  | 189 | (ins uimm16:$imm), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 190 | !strconcat(instr_asm, " $dst, $imm"), | 
| Bruno Cardoso Lopes | c5affec | 2007-07-11 22:47:02 +0000 | [diff] [blame] | 191 | []>; | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 192 |  | 
|  | 193 | // Memory Load/Store | 
|  | 194 | let isLoad = 1 in | 
|  | 195 | class LoadM<bits<6> op, string instr_asm, PatFrag OpNode>: | 
|  | 196 | FI< op, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 197 | (outs CPURegs:$dst), | 
|  | 198 | (ins mem:$addr), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 199 | !strconcat(instr_asm, " $dst, $addr"), | 
|  | 200 | [(set CPURegs:$dst, (OpNode addr:$addr))]>; | 
|  | 201 |  | 
|  | 202 | let isStore = 1 in | 
|  | 203 | class StoreM<bits<6> op, string instr_asm, PatFrag OpNode>: | 
|  | 204 | FI< op, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 205 | (outs), | 
|  | 206 | (ins CPURegs:$dst, mem:$addr), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 207 | !strconcat(instr_asm, " $dst, $addr"), | 
|  | 208 | [(OpNode CPURegs:$dst, addr:$addr)]>; | 
|  | 209 |  | 
|  | 210 | // Conditional Branch | 
| Evan Cheng | ac1591b | 2007-07-21 00:34:19 +0000 | [diff] [blame] | 211 | let isBranch = 1, isTerminator=1 in | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 212 | class CBranch<bits<6> op, string instr_asm, PatFrag cond_op>: | 
|  | 213 | FI< op, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 214 | (outs), | 
|  | 215 | (ins CPURegs:$a, CPURegs:$b, brtarget:$offset), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 216 | !strconcat(instr_asm, " $a, $b, $offset"), | 
|  | 217 | [(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)]>; | 
|  | 218 |  | 
|  | 219 | class SetCC_R<bits<6> op, bits<6> func, string instr_asm, | 
|  | 220 | PatFrag cond_op>: | 
|  | 221 | FR< op, | 
|  | 222 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 223 | (outs CPURegs:$dst), | 
|  | 224 | (ins CPURegs:$b, CPURegs:$c), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 225 | !strconcat(instr_asm, " $dst, $b, $c"), | 
|  | 226 | [(set CPURegs:$dst, (cond_op CPURegs:$b, CPURegs:$c))]>; | 
|  | 227 |  | 
|  | 228 | class SetCC_I<bits<6> op, string instr_asm, PatFrag cond_op, | 
|  | 229 | Operand Od, PatLeaf imm_type>: | 
|  | 230 | FI< op, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 231 | (outs CPURegs:$dst), | 
|  | 232 | (ins CPURegs:$b, Od:$c), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 233 | !strconcat(instr_asm, " $dst, $b, $c"), | 
|  | 234 | [(set CPURegs:$dst, (cond_op CPURegs:$b, imm_type:$c))]>; | 
|  | 235 |  | 
|  | 236 | // Unconditional branch | 
| Evan Cheng | ac1591b | 2007-07-21 00:34:19 +0000 | [diff] [blame] | 237 | let hasCtrlDep=1, isTerminator=1 in | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 238 | class JumpFJ<bits<6> op, string instr_asm>: | 
|  | 239 | FJ< op, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 240 | (outs), | 
|  | 241 | (ins brtarget:$target), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 242 | !strconcat(instr_asm, " $target"), | 
|  | 243 | [(br bb:$target)]>; | 
|  | 244 |  | 
| Evan Cheng | ac1591b | 2007-07-21 00:34:19 +0000 | [diff] [blame] | 245 | let hasCtrlDep=1, isTerminator=1, rd=0 in | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 246 | class JumpFR<bits<6> op, bits<6> func, string instr_asm>: | 
|  | 247 | FR< op, | 
|  | 248 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 249 | (outs), | 
|  | 250 | (ins CPURegs:$target), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 251 | !strconcat(instr_asm, " $target"), | 
|  | 252 | []>; | 
|  | 253 |  | 
|  | 254 | // Jump and Link (Call) | 
|  | 255 | let isCall=1 in | 
|  | 256 | class JumpLink<bits<6> op, string instr_asm>: | 
|  | 257 | FJ< op, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 258 | (outs), | 
|  | 259 | (ins calltarget:$target), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 260 | !strconcat(instr_asm, " $target"), | 
|  | 261 | [(MipsJmpLink imm:$target)]>; | 
|  | 262 |  | 
|  | 263 | let isCall=1 in | 
|  | 264 | class JumpLinkReg<bits<6> op, bits<6> func, string instr_asm>: | 
|  | 265 | FR< op, | 
|  | 266 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 267 | (outs), | 
|  | 268 | (ins CPURegs:$rd, CPURegs:$rs), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 269 | !strconcat(instr_asm, " $rs, $rd"), | 
|  | 270 | []>; | 
|  | 271 |  | 
|  | 272 | // Mul, Div | 
|  | 273 | class MulDiv<bits<6> func, string instr_asm>: | 
|  | 274 | FR< 0x00, | 
|  | 275 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 276 | (outs), | 
|  | 277 | (ins CPURegs:$a, CPURegs:$b), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 278 | !strconcat(instr_asm, " $a, $b"), | 
|  | 279 | []>; | 
|  | 280 |  | 
|  | 281 | // Move from Hi/Lo | 
|  | 282 | class MoveFromTo<bits<6> func, string instr_asm>: | 
|  | 283 | FR< 0x00, | 
|  | 284 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 285 | (outs CPURegs:$dst), | 
|  | 286 | (ins), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 287 | !strconcat(instr_asm, " $dst"), | 
|  | 288 | []>; | 
|  | 289 |  | 
|  | 290 | // Count Leading Ones/Zeros in Word | 
|  | 291 | class CountLeading<bits<6> func, string instr_asm>: | 
|  | 292 | FR< 0x1c, | 
|  | 293 | func, | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 294 | (outs CPURegs:$dst), | 
|  | 295 | (ins CPURegs:$src), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 296 | !strconcat(instr_asm, " $dst, $src"), | 
|  | 297 | []>; | 
|  | 298 |  | 
|  | 299 |  | 
|  | 300 | //===----------------------------------------------------------------------===// | 
|  | 301 | // Pseudo instructions | 
|  | 302 | //===----------------------------------------------------------------------===// | 
|  | 303 |  | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 304 | class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>: | 
|  | 305 | MipsInst<outs, ins, asmstr, pattern>; | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 306 |  | 
|  | 307 | // As stack alignment is always done with addiu, we need a 16-bit immediate | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 308 | def ADJCALLSTACKDOWN : Pseudo<(outs), (ins uimm16:$amt), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 309 | "!ADJCALLSTACKDOWN $amt", | 
|  | 310 | [(callseq_start imm:$amt)]>, Imp<[SP],[SP]>; | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 311 | def ADJCALLSTACKUP   : Pseudo<(outs), (ins uimm16:$amt), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 312 | "!ADJCALLSTACKUP $amt", | 
|  | 313 | [(callseq_end imm:$amt)]>, Imp<[SP],[SP]>; | 
|  | 314 |  | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 315 | def IMPLICIT_DEF_CPURegs : Pseudo<(outs CPURegs:$dst), (ins), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 316 | "!IMPLICIT_DEF $dst", | 
|  | 317 | [(set CPURegs:$dst, (undef))]>; | 
|  | 318 |  | 
|  | 319 | //===----------------------------------------------------------------------===// | 
|  | 320 | // Instruction definition | 
|  | 321 | //===----------------------------------------------------------------------===// | 
|  | 322 |  | 
|  | 323 | //===----------------------------------------------------------------------===// | 
|  | 324 | // Mips32 I | 
|  | 325 | //===----------------------------------------------------------------------===// | 
|  | 326 |  | 
|  | 327 | // Arithmetic | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 328 | def ADDiu   : ArithI<0x09, "addiu", add, uimm16, immSExt16>; | 
| Bruno Cardoso Lopes | c5affec | 2007-07-11 22:47:02 +0000 | [diff] [blame] | 329 | def ADDi    : ArithI<0x08, "addi",  add, simm16, immZExt16>; | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 330 | def MUL     : ArithR<0x1c, 0x02, "mul", mul>; | 
|  | 331 | def ADDu    : ArithR<0x00, 0x21, "addu", add>; | 
|  | 332 | def SUBu    : ArithR<0x00, 0x23, "subu", sub>; | 
|  | 333 | def ADD     : ArithOverflowR<0x00, 0x20, "add">; | 
|  | 334 | def SUB     : ArithOverflowR<0x00, 0x22, "sub">; | 
|  | 335 | def MADD    : MArithR<0x00, "madd">; | 
|  | 336 | def MADDU   : MArithR<0x01, "maddu">; | 
|  | 337 | def MSUB    : MArithR<0x04, "msub">; | 
|  | 338 | def MSUBU   : MArithR<0x05, "msubu">; | 
|  | 339 |  | 
|  | 340 | // Logical | 
|  | 341 | def AND     : LogicR<0x24, "and", and>; | 
|  | 342 | def OR      : LogicR<0x25, "or",  or>; | 
|  | 343 | def XOR     : LogicR<0x26, "xor", xor>; | 
|  | 344 | def ANDi    : LogicI<0x0c, "andi", and>; | 
|  | 345 | def ORi     : LogicI<0x0d, "ori",  or>; | 
|  | 346 | def XORi    : LogicI<0x0e, "xori",  xor>; | 
|  | 347 | def NOR     : LogicNOR<0x00, 0x27, "nor">; | 
|  | 348 |  | 
|  | 349 | // Shifts | 
|  | 350 | def SLL     : LogicR_shift_imm<0x00, "sll", shl>; | 
|  | 351 | def SRL     : LogicR_shift_imm<0x02, "srl", srl>; | 
|  | 352 | def SRA     : LogicR_shift_imm<0x03, "sra", sra>; | 
|  | 353 | def SLLV    : LogicR_shift_reg<0x04, "sllv", shl>; | 
|  | 354 | def SRLV    : LogicR_shift_reg<0x06, "srlv", srl>; | 
|  | 355 | def SRAV    : LogicR_shift_reg<0x07, "srav", sra>; | 
|  | 356 |  | 
|  | 357 | // Load Upper Immediate | 
|  | 358 | def LUi     : LoadUpper<0x0f, "lui">; | 
|  | 359 |  | 
|  | 360 | // Load/Store | 
|  | 361 | def LB      : LoadM<0x20, "lb",  sextloadi8>; | 
|  | 362 | def LBu     : LoadM<0x24, "lbu", zextloadi8>; | 
|  | 363 | def LH      : LoadM<0x21, "lh",  sextloadi16>; | 
|  | 364 | def LHu     : LoadM<0x25, "lhu", zextloadi16>; | 
|  | 365 | def LW      : LoadM<0x23, "lw",  load>; | 
|  | 366 | def SB      : StoreM<0x28, "sb", truncstorei8>; | 
|  | 367 | def SH      : StoreM<0x29, "sh", truncstorei16>; | 
|  | 368 | def SW      : StoreM<0x2b, "sw", store>; | 
|  | 369 |  | 
|  | 370 | // Conditional Branch | 
|  | 371 | def BEQ     : CBranch<0x04, "beq", seteq>; | 
|  | 372 | def BNE     : CBranch<0x05, "bne", setne>; | 
|  | 373 | def SLT     : SetCC_R<0x00, 0x2a, "slt", setlt>; | 
|  | 374 | def SLTu    : SetCC_R<0x00, 0x2b, "sltu", setult>; | 
|  | 375 | def SLTi    : SetCC_I<0x0a, "slti", setlt, simm16, immSExt16>; | 
|  | 376 | def SLTiu   : SetCC_I<0x0b, "sltiu", setult, uimm16, immZExt16>; | 
|  | 377 |  | 
|  | 378 | // Unconditional jump | 
|  | 379 | def J       : JumpFJ<0x02, "j">; | 
|  | 380 | def JR      : JumpFR<0x00, 0x08, "jr">; | 
|  | 381 |  | 
|  | 382 | // Jump and Link (Call) | 
|  | 383 | def JAL     : JumpLink<0x03, "jal">; | 
|  | 384 | def JALR    : JumpLinkReg<0x00, 0x09, "jalr">; | 
|  | 385 |  | 
|  | 386 | // MulDiv and Move From Hi/Lo operations, have | 
|  | 387 | // their correpondent SDNodes created on ISelDAG. | 
|  | 388 | // Special Mul, Div operations | 
|  | 389 | def MULT    : MulDiv<0x18, "mult">; | 
|  | 390 | def MULTu   : MulDiv<0x19, "multu">; | 
|  | 391 | def DIV     : MulDiv<0x1a, "div">; | 
|  | 392 | def DIVu    : MulDiv<0x1b, "divu">; | 
|  | 393 |  | 
|  | 394 | // Move From Hi/Lo | 
|  | 395 | def MFHI    : MoveFromTo<0x10, "mfhi">; | 
|  | 396 | def MFLO    : MoveFromTo<0x12, "mflo">; | 
|  | 397 | def MTHI    : MoveFromTo<0x11, "mthi">; | 
|  | 398 | def MTLO    : MoveFromTo<0x13, "mtlo">; | 
|  | 399 |  | 
|  | 400 | // Count Leading | 
|  | 401 | def CLO     : CountLeading<0x21, "clo">; | 
|  | 402 | def CLZ     : CountLeading<0x20, "clz">; | 
|  | 403 |  | 
|  | 404 | // No operation | 
|  | 405 | let addr=0 in | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 406 | def NOOP :  FJ<0, (outs), (ins), "nop", []>; | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 407 |  | 
|  | 408 | // Ret instruction - as mips does not have "ret" a | 
|  | 409 | // jr $ra must be generated. | 
| Evan Cheng | ac1591b | 2007-07-21 00:34:19 +0000 | [diff] [blame] | 410 | let isReturn=1, isTerminator=1, hasDelaySlot=1, | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 411 | isBarrier=1, hasCtrlDep=1, rs=0, rt=0, shamt=0 in | 
|  | 412 | { | 
| Evan Cheng | 94b5a80 | 2007-07-19 01:14:50 +0000 | [diff] [blame] | 413 | def RET : FR <0x00, 0x02, (outs), (ins CPURegs:$target), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 414 | "jr $target", [(MipsRet CPURegs:$target)]>; | 
|  | 415 | } | 
|  | 416 |  | 
|  | 417 | //===----------------------------------------------------------------------===// | 
|  | 418 | //  Arbitrary patterns that map to one or more instructions | 
|  | 419 | //===----------------------------------------------------------------------===// | 
|  | 420 |  | 
|  | 421 | // Small immediates | 
|  | 422 | def : Pat<(i32 immSExt16:$in), | 
| Bruno Cardoso Lopes | c5affec | 2007-07-11 22:47:02 +0000 | [diff] [blame] | 423 | (ADDiu ZERO, imm:$in)>; | 
|  | 424 | def : Pat<(i32 immZExt16:$in), | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 425 | (ORi ZERO, imm:$in)>; | 
|  | 426 |  | 
|  | 427 | // Arbitrary immediates | 
|  | 428 | def : Pat<(i32 imm:$imm), | 
|  | 429 | (ORi (LUi (HI16 imm:$imm)), (LO16 imm:$imm))>; | 
|  | 430 |  | 
|  | 431 | // Call | 
|  | 432 | def : Pat<(MipsJmpLink (i32 tglobaladdr:$dst)), | 
|  | 433 | (JAL tglobaladdr:$dst)>; | 
|  | 434 | def : Pat<(MipsJmpLink (i32 texternalsym:$dst)), | 
|  | 435 | (JAL texternalsym:$dst)>; | 
|  | 436 |  | 
|  | 437 | // GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable | 
|  | 438 | def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; | 
|  | 439 | def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>; | 
|  | 440 |  | 
|  | 441 | // When extracting the address from GlobalAddress we | 
|  | 442 | // need something of the form "addiu $reg, %lo(addr)" | 
|  | 443 | def : Pat<(add CPURegs:$a, (MipsLo tglobaladdr:$in)), | 
|  | 444 | (ADDiu CPURegs:$a, tglobaladdr:$in)>; | 
|  | 445 |  | 
|  | 446 | // Mips does not have not, so we increase the operation | 
|  | 447 | def : Pat<(not CPURegs:$in), | 
|  | 448 | (NOR CPURegs:$in, CPURegs:$in)>; | 
|  | 449 |  | 
|  | 450 | // extended load and stores | 
|  | 451 | def : Pat<(i32 (extloadi8  addr:$src)), (LBu addr:$src)>; | 
|  | 452 | def : Pat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>; | 
|  | 453 | def : Pat<(truncstorei1 CPURegs:$src, addr:$addr), | 
|  | 454 | (SB CPURegs:$src, addr:$src)>; | 
|  | 455 |  | 
| Bruno Cardoso Lopes | c5affec | 2007-07-11 22:47:02 +0000 | [diff] [blame] | 456 | def : Pat<(brcond (setne CPURegs:$lhs, (add ZERO, 0)), bb:$dst), | 
|  | 457 | (BNE CPURegs:$lhs, ZERO, bb:$dst)>; | 
|  | 458 |  | 
|  | 459 |  | 
| Bruno Cardoso Lopes | 35e43c4 | 2007-06-06 07:42:06 +0000 | [diff] [blame] | 460 | // Conditional branch patterns. | 
|  | 461 | // cond branches patterns, 2 register operands signed. | 
|  | 462 | def : Pat<(brcond (setlt CPURegs:$lhs, CPURegs:$rhs), bb:$dst), | 
|  | 463 | (BNE (SLT CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>; | 
|  | 464 | def : Pat<(brcond (setle CPURegs:$lhs, CPURegs:$rhs), bb:$dst), | 
|  | 465 | (BEQ (SLT CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>; | 
|  | 466 | def : Pat<(brcond (setgt CPURegs:$lhs, CPURegs:$rhs), bb:$dst), | 
|  | 467 | (BNE (SLT CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>; | 
|  | 468 | def : Pat<(brcond (setge CPURegs:$lhs, CPURegs:$rhs), bb:$dst), | 
|  | 469 | (BEQ (SLT CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>; | 
|  | 470 |  | 
|  | 471 | // cond branches patterns, 2 register operands unsigned. | 
|  | 472 | def : Pat<(brcond (setult CPURegs:$lhs, CPURegs:$rhs), bb:$dst), | 
|  | 473 | (BNE (SLTu CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>; | 
|  | 474 | def : Pat<(brcond (setule CPURegs:$lhs, CPURegs:$rhs), bb:$dst), | 
|  | 475 | (BEQ (SLTu CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>; | 
|  | 476 | def : Pat<(brcond (setugt CPURegs:$lhs, CPURegs:$rhs), bb:$dst), | 
|  | 477 | (BNE (SLTu CPURegs:$rhs, CPURegs:$lhs), ZERO, bb:$dst)>; | 
|  | 478 | def : Pat<(brcond (setuge CPURegs:$lhs, CPURegs:$rhs), bb:$dst), | 
|  | 479 | (BEQ (SLTu CPURegs:$lhs, CPURegs:$rhs), ZERO, bb:$dst)>; | 
|  | 480 |  | 
|  | 481 | // cond branches patterns, reg/imm operands signed. | 
|  | 482 | def : Pat<(brcond (setult CPURegs:$lhs, immSExt16:$rhs), bb:$dst), | 
|  | 483 | (BNE (SLTi CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; | 
|  | 484 | def : Pat<(brcond (setuge CPURegs:$lhs, immSExt16:$rhs), bb:$dst), | 
|  | 485 | (BEQ (SLTi CPURegs:$lhs, immSExt16:$rhs), ZERO, bb:$dst)>; | 
|  | 486 |  | 
|  | 487 | // cond branches patterns, reg/imm operands unsigned. | 
|  | 488 | def : Pat<(brcond (setult CPURegs:$lhs, immZExt16:$rhs), bb:$dst), | 
|  | 489 | (BNE (SLTiu CPURegs:$lhs, immZExt16:$rhs), ZERO, bb:$dst)>; | 
|  | 490 | def : Pat<(brcond (setuge CPURegs:$lhs, immZExt16:$rhs), bb:$dst), | 
|  | 491 | (BEQ (SLTiu CPURegs:$lhs, immZExt16:$rhs), ZERO, bb:$dst)>; |