ARMInstrThumb2.td revision 334c26473bba3ad8b88341bb0d25d0ac2008bb8d
1//===- ARMInstrThumb2.td - Thumb2 support for ARM -------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file describes the Thumb2 instruction set. 11// 12//===----------------------------------------------------------------------===// 13 14// Shifted operands. No register controlled shifts for Thumb2. 15// Note: We do not support rrx shifted operands yet. 16def t2_so_reg : Operand<i32>, // reg imm 17 ComplexPattern<i32, 2, "SelectT2ShifterOperandReg", 18 [shl,srl,sra,rotr]> { 19 let PrintMethod = "printT2SOOperand"; 20 let MIOperandInfo = (ops GPR, i32imm); 21} 22 23// t2_so_imm_XFORM - Return a t2_so_imm value packed into the format 24// described for t2_so_imm def below. 25def t2_so_imm_XFORM : SDNodeXForm<imm, [{ 26 return CurDAG->getTargetConstant( 27 ARM_AM::getT2SOImmVal(N->getZExtValue()), MVT::i32); 28}]>; 29 30// t2_so_imm_not_XFORM - Return the complement of a t2_so_imm value 31def t2_so_imm_not_XFORM : SDNodeXForm<imm, [{ 32 return CurDAG->getTargetConstant( 33 ARM_AM::getT2SOImmVal(~((uint32_t)N->getZExtValue())), MVT::i32); 34}]>; 35 36// t2_so_imm_neg_XFORM - Return the negation of a t2_so_imm value 37def t2_so_imm_neg_XFORM : SDNodeXForm<imm, [{ 38 return CurDAG->getTargetConstant( 39 ARM_AM::getT2SOImmVal(-((int)N->getZExtValue())), MVT::i32); 40}]>; 41 42// t2_so_imm - Match a 32-bit immediate operand, which is an 43// 8-bit immediate rotated by an arbitrary number of bits, or an 8-bit 44// immediate splatted into multiple bytes of the word. t2_so_imm values are 45// represented in the imm field in the same 12-bit form that they are encoded 46// into t2_so_imm instructions: the 8-bit immediate is the least significant bits 47// [bits 0-7], the 4-bit shift/splat amount is the next 4 bits [bits 8-11]. 48def t2_so_imm : Operand<i32>, 49 PatLeaf<(imm), [{ 50 return ARM_AM::getT2SOImmVal((uint32_t)N->getZExtValue()) != -1; 51 }], t2_so_imm_XFORM> { 52 let PrintMethod = "printT2SOImmOperand"; 53} 54 55// t2_so_imm_not - Match an immediate that is a complement 56// of a t2_so_imm. 57def t2_so_imm_not : Operand<i32>, 58 PatLeaf<(imm), [{ 59 return ARM_AM::getT2SOImmVal(~((uint32_t)N->getZExtValue())) != -1; 60 }], t2_so_imm_not_XFORM> { 61 let PrintMethod = "printT2SOImmOperand"; 62} 63 64// t2_so_imm_neg - Match an immediate that is a negation of a t2_so_imm. 65def t2_so_imm_neg : Operand<i32>, 66 PatLeaf<(imm), [{ 67 return ARM_AM::getT2SOImmVal(-((int)N->getZExtValue())) != -1; 68 }], t2_so_imm_neg_XFORM> { 69 let PrintMethod = "printT2SOImmOperand"; 70} 71 72/// imm1_31 predicate - True if the 32-bit immediate is in the range [1,31]. 73def imm1_31 : PatLeaf<(i32 imm), [{ 74 return (int32_t)N->getZExtValue() >= 1 && (int32_t)N->getZExtValue() < 32; 75}]>; 76 77/// imm0_4095 predicate - True if the 32-bit immediate is in the range [0.4095]. 78def imm0_4095 : PatLeaf<(i32 imm), [{ 79 return (uint32_t)N->getZExtValue() < 4096; 80}]>; 81 82def imm0_4095_neg : PatLeaf<(i32 imm), [{ 83 return (uint32_t)(-N->getZExtValue()) < 4096; 84}], imm_neg_XFORM>; 85 86/// imm0_65535 predicate - True if the 32-bit immediate is in the range 87/// [0.65535]. 88def imm0_65535 : PatLeaf<(i32 imm), [{ 89 return (uint32_t)N->getZExtValue() < 65536; 90}]>; 91 92/// Split a 32-bit immediate into two 16 bit parts. 93def t2_lo16 : SDNodeXForm<imm, [{ 94 return CurDAG->getTargetConstant((uint32_t)N->getZExtValue() & 0xffff, 95 MVT::i32); 96}]>; 97 98def t2_hi16 : SDNodeXForm<imm, [{ 99 return CurDAG->getTargetConstant((uint32_t)N->getZExtValue() >> 16, MVT::i32); 100}]>; 101 102def t2_lo16AllZero : PatLeaf<(i32 imm), [{ 103 // Returns true if all low 16-bits are 0. 104 return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0; 105 }], t2_hi16>; 106 107 108// Define Thumb2 specific addressing modes. 109 110// t2addrmode_imm12 := reg + imm12 111def t2addrmode_imm12 : Operand<i32>, 112 ComplexPattern<i32, 2, "SelectT2AddrModeImm12", []> { 113 let PrintMethod = "printT2AddrModeImm12Operand"; 114 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); 115} 116 117// t2addrmode_imm8 := reg - imm8 118def t2addrmode_imm8 : Operand<i32>, 119 ComplexPattern<i32, 2, "SelectT2AddrModeImm8", []> { 120 let PrintMethod = "printT2AddrModeImm8Operand"; 121 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); 122} 123 124def t2am_imm8_offset : Operand<i32>, 125 ComplexPattern<i32, 1, "SelectT2AddrModeImm8Offset", []>{ 126 let PrintMethod = "printT2AddrModeImm8OffsetOperand"; 127} 128 129// t2addrmode_imm8s4 := reg + (imm8 << 2) 130def t2addrmode_imm8s4 : Operand<i32>, 131 ComplexPattern<i32, 2, "SelectT2AddrModeImm8s4", []> { 132 let PrintMethod = "printT2AddrModeImm8Operand"; 133 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); 134} 135 136// t2addrmode_so_reg := reg + reg << imm2 137def t2addrmode_so_reg : Operand<i32>, 138 ComplexPattern<i32, 3, "SelectT2AddrModeSoReg", []> { 139 let PrintMethod = "printT2AddrModeSoRegOperand"; 140 let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); 141} 142 143 144//===----------------------------------------------------------------------===// 145// Multiclass helpers... 146// 147 148/// T2I_un_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a 149/// unary operation that produces a value. These are predicable and can be 150/// changed to modify CPSR. 151multiclass T2I_un_irs<string opc, PatFrag opnode, bit Cheap = 0, bit ReMat = 0>{ 152 // shifted imm 153 def i : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), 154 opc, " $dst, $src", 155 [(set GPR:$dst, (opnode t2_so_imm:$src))]> { 156 let isAsCheapAsAMove = Cheap; 157 let isReMaterializable = ReMat; 158 } 159 // register 160 def r : T2I<(outs GPR:$dst), (ins GPR:$src), 161 opc, " $dst, $src", 162 [(set GPR:$dst, (opnode GPR:$src))]>; 163 // shifted register 164 def s : T2I<(outs GPR:$dst), (ins t2_so_reg:$src), 165 opc, " $dst, $src", 166 [(set GPR:$dst, (opnode t2_so_reg:$src))]>; 167} 168 169/// T2I_bin_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a 170// binary operation that produces a value. These are predicable and can be 171/// changed to modify CPSR. 172multiclass T2I_bin_irs<string opc, PatFrag opnode, bit Commutable = 0> { 173 // shifted imm 174 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), 175 opc, " $dst, $lhs, $rhs", 176 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>; 177 // register 178 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), 179 opc, " $dst, $lhs, $rhs", 180 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> { 181 let isCommutable = Commutable; 182 } 183 // shifted register 184 def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), 185 opc, " $dst, $lhs, $rhs", 186 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>; 187} 188 189/// T2I_rbin_is - Same as T2I_bin_irs except the order of operands are 190/// reversed. It doesn't define the 'rr' form since it's handled by its 191/// T2I_bin_irs counterpart. 192multiclass T2I_rbin_is<string opc, PatFrag opnode> { 193 // shifted imm 194 def ri : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs), 195 opc, " $dst, $rhs, $lhs", 196 [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>; 197 // shifted register 198 def rs : T2I<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs), 199 opc, " $dst, $rhs, $lhs", 200 [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>; 201} 202 203/// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the 204/// instruction modifies the CPSR register. 205let Defs = [CPSR] in { 206multiclass T2I_bin_s_irs<string opc, PatFrag opnode, bit Commutable = 0> { 207 // shifted imm 208 def ri : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), 209 !strconcat(opc, "s"), " $dst, $lhs, $rhs", 210 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>; 211 // register 212 def rr : T2I<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), 213 !strconcat(opc, "s"), " $dst, $lhs, $rhs", 214 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> { 215 let isCommutable = Commutable; 216 } 217 // shifted register 218 def rs : T2I<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), 219 !strconcat(opc, "s"), " $dst, $lhs, $rhs", 220 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>; 221} 222} 223 224/// T2I_bin_ii12rs - Defines a set of (op reg, {so_imm|imm0_4095|r|so_reg}) 225/// patterns for a binary operation that produces a value. 226multiclass T2I_bin_ii12rs<string opc, PatFrag opnode, bit Commutable = 0> { 227 // shifted imm 228 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), 229 opc, " $dst, $lhs, $rhs", 230 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>; 231 // 12-bit imm 232 def ri12 : T2sI<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), 233 !strconcat(opc, "w"), " $dst, $lhs, $rhs", 234 [(set GPR:$dst, (opnode GPR:$lhs, imm0_4095:$rhs))]>; 235 // register 236 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), 237 opc, " $dst, $lhs, $rhs", 238 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]> { 239 let isCommutable = Commutable; 240 } 241 // shifted register 242 def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), 243 opc, " $dst, $lhs, $rhs", 244 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>; 245} 246 247/// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a 248/// binary operation that produces a value and use and define the carry bit. 249/// It's not predicable. 250let Uses = [CPSR] in { 251multiclass T2I_adde_sube_irs<string opc, PatFrag opnode, bit Commutable = 0> { 252 // shifted imm 253 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), 254 opc, " $dst, $lhs, $rhs", 255 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>, 256 Requires<[IsThumb2, CarryDefIsUnused]>; 257 // register 258 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), 259 opc, " $dst, $lhs, $rhs", 260 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>, 261 Requires<[IsThumb2, CarryDefIsUnused]> { 262 let isCommutable = Commutable; 263 } 264 // shifted register 265 def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), 266 opc, " $dst, $lhs, $rhs", 267 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>, 268 Requires<[IsThumb2, CarryDefIsUnused]>; 269 // Carry setting variants 270 // shifted imm 271 def Sri : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), 272 !strconcat(opc, "s $dst, $lhs, $rhs"), 273 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>, 274 Requires<[IsThumb2, CarryDefIsUsed]> { 275 let Defs = [CPSR]; 276 } 277 // register 278 def Srr : T2XI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), 279 !strconcat(opc, "s $dst, $lhs, $rhs"), 280 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>, 281 Requires<[IsThumb2, CarryDefIsUsed]> { 282 let Defs = [CPSR]; 283 let isCommutable = Commutable; 284 } 285 // shifted register 286 def Srs : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), 287 !strconcat(opc, "s $dst, $lhs, $rhs"), 288 [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>, 289 Requires<[IsThumb2, CarryDefIsUsed]> { 290 let Defs = [CPSR]; 291 } 292} 293} 294 295/// T2I_rsc_is - Same as T2I_adde_sube_irs except the order of operands are 296/// reversed. It doesn't define the 'rr' form since it's handled by its 297/// T2I_adde_sube_irs counterpart. 298let Defs = [CPSR], Uses = [CPSR] in { 299multiclass T2I_rsc_is<string opc, PatFrag opnode> { 300 // shifted imm 301 def ri : T2sI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs), 302 opc, " $dst, $rhs, $lhs", 303 [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>, 304 Requires<[IsThumb2, CarryDefIsUnused]>; 305 // shifted register 306 def rs : T2sI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs), 307 opc, " $dst, $rhs, $lhs", 308 [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>, 309 Requires<[IsThumb2, CarryDefIsUnused]>; 310 // shifted imm 311 def Sri : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs), 312 !strconcat(opc, "s $dst, $rhs, $lhs"), 313 [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>, 314 Requires<[IsThumb2, CarryDefIsUsed]> { 315 let Defs = [CPSR]; 316 } 317 // shifted register 318 def Srs : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs), 319 !strconcat(opc, "s $dst, $rhs, $lhs"), 320 [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>, 321 Requires<[IsThumb2, CarryDefIsUsed]> { 322 let Defs = [CPSR]; 323 } 324} 325} 326 327/// T2I_rbin_s_is - Same as T2I_bin_s_irs except the order of operands are 328/// reversed. It doesn't define the 'rr' form since it's handled by its 329/// T2I_bin_s_irs counterpart. 330let Defs = [CPSR] in { 331multiclass T2I_rbin_s_is<string opc, PatFrag opnode> { 332 // shifted imm 333 def ri : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_imm:$lhs, cc_out:$s), 334 !strconcat(opc, "${s} $dst, $rhs, $lhs"), 335 [(set GPR:$dst, (opnode t2_so_imm:$lhs, GPR:$rhs))]>; 336 // shifted register 337 def rs : T2XI<(outs GPR:$dst), (ins GPR:$rhs, t2_so_reg:$lhs, cc_out:$s), 338 !strconcat(opc, "${s} $dst, $rhs, $lhs"), 339 [(set GPR:$dst, (opnode t2_so_reg:$lhs, GPR:$rhs))]>; 340} 341} 342 343/// T2I_sh_ir - Defines a set of (op reg, {so_imm|r}) patterns for a shift / 344// rotate operation that produces a value. 345multiclass T2I_sh_ir<string opc, PatFrag opnode> { 346 // 5-bit imm 347 def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs), 348 opc, " $dst, $lhs, $rhs", 349 [(set GPR:$dst, (opnode GPR:$lhs, imm1_31:$rhs))]>; 350 // register 351 def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), 352 opc, " $dst, $lhs, $rhs", 353 [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>; 354} 355 356/// T21_cmp_irs - Defines a set of (op r, {so_imm|r|so_reg}) cmp / test 357/// patterns. Similar to T2I_bin_irs except the instruction does not produce 358/// a explicit result, only implicitly set CPSR. 359let Uses = [CPSR] in { 360multiclass T2I_cmp_is<string opc, PatFrag opnode> { 361 // shifted imm 362 def ri : T2I<(outs), (ins GPR:$lhs, t2_so_imm:$rhs), 363 opc, " $lhs, $rhs", 364 [(opnode GPR:$lhs, t2_so_imm:$rhs)]>; 365 // register 366 def rr : T2I<(outs), (ins GPR:$lhs, GPR:$rhs), 367 opc, " $lhs, $rhs", 368 [(opnode GPR:$lhs, GPR:$rhs)]>; 369 // shifted register 370 def rs : T2I<(outs), (ins GPR:$lhs, t2_so_reg:$rhs), 371 opc, " $lhs, $rhs", 372 [(opnode GPR:$lhs, t2_so_reg:$rhs)]>; 373} 374} 375 376/// T2I_ld - Defines a set of (op r, {imm12|imm8|so_reg}) load patterns. 377multiclass T2I_ld<string opc, PatFrag opnode> { 378 def i12 : T2Ii12<(outs GPR:$dst), (ins t2addrmode_imm12:$addr), 379 opc, " $dst, $addr", 380 [(set GPR:$dst, (opnode t2addrmode_imm12:$addr))]>; 381 def i8 : T2Ii8 <(outs GPR:$dst), (ins t2addrmode_imm8:$addr), 382 opc, " $dst, $addr", 383 [(set GPR:$dst, (opnode t2addrmode_imm8:$addr))]>; 384 def s : T2Iso <(outs GPR:$dst), (ins t2addrmode_so_reg:$addr), 385 opc, " $dst, $addr", 386 [(set GPR:$dst, (opnode t2addrmode_so_reg:$addr))]>; 387 def pci : T2Ipc <(outs GPR:$dst), (ins i32imm:$addr), 388 opc, " $dst, $addr", 389 [(set GPR:$dst, (opnode (ARMWrapper tconstpool:$addr)))]>; 390} 391 392/// T2I_st - Defines a set of (op r, {imm12|imm8|so_reg}) store patterns. 393multiclass T2I_st<string opc, PatFrag opnode> { 394 def i12 : T2Ii12<(outs), (ins GPR:$src, t2addrmode_imm12:$addr), 395 opc, " $src, $addr", 396 [(opnode GPR:$src, t2addrmode_imm12:$addr)]>; 397 def i8 : T2Ii8 <(outs), (ins GPR:$src, t2addrmode_imm8:$addr), 398 opc, " $src, $addr", 399 [(opnode GPR:$src, t2addrmode_imm8:$addr)]>; 400 def s : T2Iso <(outs), (ins GPR:$src, t2addrmode_so_reg:$addr), 401 opc, " $src, $addr", 402 [(opnode GPR:$src, t2addrmode_so_reg:$addr)]>; 403} 404 405/// T2I_picld - Defines the PIC load pattern. 406class T2I_picld<string opc, PatFrag opnode> : 407 T2I<(outs GPR:$dst), (ins addrmodepc:$addr), 408 !strconcat("${addr:label}:\n\t", opc), " $dst, $addr", 409 [(set GPR:$dst, (opnode addrmodepc:$addr))]>; 410 411/// T2I_picst - Defines the PIC store pattern. 412class T2I_picst<string opc, PatFrag opnode> : 413 T2I<(outs), (ins GPR:$src, addrmodepc:$addr), 414 !strconcat("${addr:label}:\n\t", opc), " $src, $addr", 415 [(opnode GPR:$src, addrmodepc:$addr)]>; 416 417 418/// T2I_unary_rrot - A unary operation with two forms: one whose operand is a 419/// register and one whose operand is a register rotated by 8/16/24. 420multiclass T2I_unary_rrot<string opc, PatFrag opnode> { 421 def r : T2I<(outs GPR:$dst), (ins GPR:$Src), 422 opc, " $dst, $Src", 423 [(set GPR:$dst, (opnode GPR:$Src))]>; 424 def r_rot : T2I<(outs GPR:$dst), (ins GPR:$Src, i32imm:$rot), 425 opc, " $dst, $Src, ror $rot", 426 [(set GPR:$dst, (opnode (rotr GPR:$Src, rot_imm:$rot)))]>; 427} 428 429/// T2I_bin_rrot - A binary operation with two forms: one whose operand is a 430/// register and one whose operand is a register rotated by 8/16/24. 431multiclass T2I_bin_rrot<string opc, PatFrag opnode> { 432 def rr : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS), 433 opc, " $dst, $LHS, $RHS", 434 [(set GPR:$dst, (opnode GPR:$LHS, GPR:$RHS))]>; 435 def rr_rot : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS, i32imm:$rot), 436 opc, " $dst, $LHS, $RHS, ror $rot", 437 [(set GPR:$dst, (opnode GPR:$LHS, 438 (rotr GPR:$RHS, rot_imm:$rot)))]>; 439} 440 441//===----------------------------------------------------------------------===// 442// Instructions 443//===----------------------------------------------------------------------===// 444 445//===----------------------------------------------------------------------===// 446// Miscellaneous Instructions. 447// 448 449let isNotDuplicable = 1 in 450def t2PICADD : T2XI<(outs tGPR:$dst), (ins tGPR:$lhs, pclabel:$cp), 451 "$cp:\n\tadd $dst, pc", 452 [(set tGPR:$dst, (ARMpic_add tGPR:$lhs, imm:$cp))]>; 453 454 455// LEApcrel - Load a pc-relative address into a register without offending the 456// assembler. 457def t2LEApcrel : T2XI<(outs GPR:$dst), (ins i32imm:$label, pred:$p), 458 !strconcat(!strconcat(".set PCRELV${:uid}, ($label-(", 459 "${:private}PCRELL${:uid}+8))\n"), 460 !strconcat("${:private}PCRELL${:uid}:\n\t", 461 "add$p $dst, pc, #PCRELV${:uid}")), 462 []>; 463 464def t2LEApcrelJT : T2XI<(outs GPR:$dst), 465 (ins i32imm:$label, i32imm:$id, pred:$p), 466 !strconcat(!strconcat(".set PCRELV${:uid}, (${label}_${id:no_hash}-(", 467 "${:private}PCRELL${:uid}+8))\n"), 468 !strconcat("${:private}PCRELL${:uid}:\n\t", 469 "add$p $dst, pc, #PCRELV${:uid}")), 470 []>; 471 472// ADD rd, sp, #so_imm 473def t2ADDrSPi : T2XI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm), 474 "add $dst, $sp, $imm", 475 []>; 476 477// ADD rd, sp, #imm12 478def t2ADDrSPi12 : T2XI<(outs GPR:$dst), (ins GPR:$sp, i32imm:$imm), 479 "addw $dst, $sp, $imm", 480 []>; 481 482def t2ADDrSPs : T2XI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs), 483 "addw $dst, $sp, $rhs", 484 []>; 485 486 487//===----------------------------------------------------------------------===// 488// Load / store Instructions. 489// 490 491// Load 492let canFoldAsLoad = 1 in 493defm t2LDR : T2I_ld<"ldr", UnOpFrag<(load node:$Src)>>; 494 495// Loads with zero extension 496defm t2LDRH : T2I_ld<"ldrh", UnOpFrag<(zextloadi16 node:$Src)>>; 497defm t2LDRB : T2I_ld<"ldrb", UnOpFrag<(zextloadi8 node:$Src)>>; 498 499// Loads with sign extension 500defm t2LDRSH : T2I_ld<"ldrsh", UnOpFrag<(sextloadi16 node:$Src)>>; 501defm t2LDRSB : T2I_ld<"ldrsb", UnOpFrag<(sextloadi8 node:$Src)>>; 502 503let mayLoad = 1 in { 504// Load doubleword 505def t2LDRDi8 : T2Ii8s4<(outs GPR:$dst), (ins t2addrmode_imm8s4:$addr), 506 "ldrd", " $dst, $addr", []>; 507def t2LDRDpci : T2Ii8s4<(outs GPR:$dst), (ins i32imm:$addr), 508 "ldrd", " $dst, $addr", []>; 509} 510 511// zextload i1 -> zextload i8 512def : T2Pat<(zextloadi1 t2addrmode_imm12:$addr), 513 (t2LDRBi12 t2addrmode_imm12:$addr)>; 514def : T2Pat<(zextloadi1 t2addrmode_imm8:$addr), 515 (t2LDRBi8 t2addrmode_imm8:$addr)>; 516def : T2Pat<(zextloadi1 t2addrmode_so_reg:$addr), 517 (t2LDRBs t2addrmode_so_reg:$addr)>; 518def : T2Pat<(zextloadi1 (ARMWrapper tconstpool:$addr)), 519 (t2LDRBpci tconstpool:$addr)>; 520 521// extload -> zextload 522// FIXME: Reduce the number of patterns by legalizing extload to zextload 523// earlier? 524def : T2Pat<(extloadi1 t2addrmode_imm12:$addr), 525 (t2LDRBi12 t2addrmode_imm12:$addr)>; 526def : T2Pat<(extloadi1 t2addrmode_imm8:$addr), 527 (t2LDRBi8 t2addrmode_imm8:$addr)>; 528def : T2Pat<(extloadi1 t2addrmode_so_reg:$addr), 529 (t2LDRBs t2addrmode_so_reg:$addr)>; 530def : T2Pat<(extloadi1 (ARMWrapper tconstpool:$addr)), 531 (t2LDRBpci tconstpool:$addr)>; 532 533def : T2Pat<(extloadi8 t2addrmode_imm12:$addr), 534 (t2LDRBi12 t2addrmode_imm12:$addr)>; 535def : T2Pat<(extloadi8 t2addrmode_imm8:$addr), 536 (t2LDRBi8 t2addrmode_imm8:$addr)>; 537def : T2Pat<(extloadi8 t2addrmode_so_reg:$addr), 538 (t2LDRBs t2addrmode_so_reg:$addr)>; 539def : T2Pat<(extloadi8 (ARMWrapper tconstpool:$addr)), 540 (t2LDRBpci tconstpool:$addr)>; 541 542def : T2Pat<(extloadi16 t2addrmode_imm12:$addr), 543 (t2LDRHi12 t2addrmode_imm12:$addr)>; 544def : T2Pat<(extloadi16 t2addrmode_imm8:$addr), 545 (t2LDRHi8 t2addrmode_imm8:$addr)>; 546def : T2Pat<(extloadi16 t2addrmode_so_reg:$addr), 547 (t2LDRHs t2addrmode_so_reg:$addr)>; 548def : T2Pat<(extloadi16 (ARMWrapper tconstpool:$addr)), 549 (t2LDRHpci tconstpool:$addr)>; 550 551// Indexed loads 552let mayLoad = 1 in { 553def t2LDR_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), 554 (ins t2addrmode_imm8:$addr), 555 AddrModeT2_i8, IndexModePre, 556 "ldr", " $dst, $addr!", "$addr.base = $base_wb", 557 []>; 558 559def t2LDR_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), 560 (ins GPR:$base, t2am_imm8_offset:$offset), 561 AddrModeT2_i8, IndexModePost, 562 "ldr", " $dst, [$base], $offset", "$base = $base_wb", 563 []>; 564 565def t2LDRB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), 566 (ins t2addrmode_imm8:$addr), 567 AddrModeT2_i8, IndexModePre, 568 "ldrb", " $dst, $addr!", "$addr.base = $base_wb", 569 []>; 570def t2LDRB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), 571 (ins GPR:$base, t2am_imm8_offset:$offset), 572 AddrModeT2_i8, IndexModePost, 573 "ldrb", " $dst, [$base], $offset", "$base = $base_wb", 574 []>; 575 576def t2LDRH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), 577 (ins t2addrmode_imm8:$addr), 578 AddrModeT2_i8, IndexModePre, 579 "ldrh", " $dst, $addr!", "$addr.base = $base_wb", 580 []>; 581def t2LDRH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), 582 (ins GPR:$base, t2am_imm8_offset:$offset), 583 AddrModeT2_i8, IndexModePost, 584 "ldrh", " $dst, [$base], $offset", "$base = $base_wb", 585 []>; 586 587def t2LDRSB_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), 588 (ins t2addrmode_imm8:$addr), 589 AddrModeT2_i8, IndexModePre, 590 "ldrsb", " $dst, $addr!", "$addr.base = $base_wb", 591 []>; 592def t2LDRSB_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), 593 (ins GPR:$base, t2am_imm8_offset:$offset), 594 AddrModeT2_i8, IndexModePost, 595 "ldrsb", " $dst, [$base], $offset", "$base = $base_wb", 596 []>; 597 598def t2LDRSH_PRE : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), 599 (ins t2addrmode_imm8:$addr), 600 AddrModeT2_i8, IndexModePre, 601 "ldrsh", " $dst, $addr!", "$addr.base = $base_wb", 602 []>; 603def t2LDRSH_POST : T2Iidxldst<(outs GPR:$dst, GPR:$base_wb), 604 (ins GPR:$base, t2am_imm8_offset:$offset), 605 AddrModeT2_i8, IndexModePost, 606 "ldrsh", " $dst, [$base], $offset", "$base = $base_wb", 607 []>; 608} 609 610// Store 611defm t2STR : T2I_st<"str", BinOpFrag<(store node:$LHS, node:$RHS)>>; 612defm t2STRB : T2I_st<"strb", BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>; 613defm t2STRH : T2I_st<"strh", BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; 614 615// Store doubleword 616let mayLoad = 1 in 617def t2STRDi8 : T2Ii8s4<(outs), (ins GPR:$src, t2addrmode_imm8s4:$addr), 618 "strd", " $src, $addr", []>; 619 620// Indexed stores 621def t2STR_PRE : T2Iidxldst<(outs GPR:$base_wb), 622 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), 623 AddrModeT2_i8, IndexModePre, 624 "str", " $src, [$base, $offset]!", "$base = $base_wb", 625 [(set GPR:$base_wb, 626 (pre_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; 627 628def t2STR_POST : T2Iidxldst<(outs GPR:$base_wb), 629 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), 630 AddrModeT2_i8, IndexModePost, 631 "str", " $src, [$base], $offset", "$base = $base_wb", 632 [(set GPR:$base_wb, 633 (post_store GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; 634 635def t2STRH_PRE : T2Iidxldst<(outs GPR:$base_wb), 636 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), 637 AddrModeT2_i8, IndexModePre, 638 "strh", " $src, [$base, $offset]!", "$base = $base_wb", 639 [(set GPR:$base_wb, 640 (pre_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; 641 642def t2STRH_POST : T2Iidxldst<(outs GPR:$base_wb), 643 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), 644 AddrModeT2_i8, IndexModePost, 645 "strh", " $src, [$base], $offset", "$base = $base_wb", 646 [(set GPR:$base_wb, 647 (post_truncsti16 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; 648 649def t2STRB_PRE : T2Iidxldst<(outs GPR:$base_wb), 650 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), 651 AddrModeT2_i8, IndexModePre, 652 "strb", " $src, [$base, $offset]!", "$base = $base_wb", 653 [(set GPR:$base_wb, 654 (pre_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; 655 656def t2STRB_POST : T2Iidxldst<(outs GPR:$base_wb), 657 (ins GPR:$src, GPR:$base, t2am_imm8_offset:$offset), 658 AddrModeT2_i8, IndexModePost, 659 "strb", " $src, [$base], $offset", "$base = $base_wb", 660 [(set GPR:$base_wb, 661 (post_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; 662 663 664// Address computation and loads and stores in PIC mode. 665let isNotDuplicable = 1, AddedComplexity = 10 in { 666let canFoldAsLoad = 1 in 667def t2PICLDR : T2I_picld<"ldr", UnOpFrag<(load node:$Src)>>; 668 669def t2PICLDRH : T2I_picld<"ldrh", UnOpFrag<(zextloadi16 node:$Src)>>; 670def t2PICLDRB : T2I_picld<"ldrb", UnOpFrag<(zextloadi8 node:$Src)>>; 671def t2PICLDRSH : T2I_picld<"ldrsh", UnOpFrag<(sextloadi16 node:$Src)>>; 672def t2PICLDRSB : T2I_picld<"ldrsb", UnOpFrag<(sextloadi8 node:$Src)>>; 673 674def t2PICSTR : T2I_picst<"str", BinOpFrag<(store node:$LHS, node:$RHS)>>; 675def t2PICSTRH : T2I_picst<"strh", BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; 676def t2PICSTRB : T2I_picst<"strb", BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>; 677} // isNotDuplicable = 1, AddedComplexity = 10 678 679 680//===----------------------------------------------------------------------===// 681// Load / store multiple Instructions. 682// 683 684let mayLoad = 1 in 685def t2LDM : T2XI<(outs), 686 (ins addrmode4:$addr, pred:$p, reglist:$dst1, variable_ops), 687 "ldm${p}${addr:submode} $addr, $dst1", []>; 688 689let mayStore = 1 in 690def t2STM : T2XI<(outs), 691 (ins addrmode4:$addr, pred:$p, reglist:$src1, variable_ops), 692 "stm${p}${addr:submode} $addr, $src1", []>; 693 694//===----------------------------------------------------------------------===// 695// Move Instructions. 696// 697 698let neverHasSideEffects = 1 in 699def t2MOVr : T2sI<(outs GPR:$dst), (ins GPR:$src), 700 "mov", " $dst, $src", []>; 701 702let isReMaterializable = 1, isAsCheapAsAMove = 1 in 703def t2MOVi : T2sI<(outs GPR:$dst), (ins t2_so_imm:$src), 704 "mov", " $dst, $src", 705 [(set GPR:$dst, t2_so_imm:$src)]>; 706 707let isReMaterializable = 1, isAsCheapAsAMove = 1 in 708def t2MOVi16 : T2I<(outs GPR:$dst), (ins i32imm:$src), 709 "movw", " $dst, $src", 710 [(set GPR:$dst, imm0_65535:$src)]>; 711 712// FIXME: Also available in ARM mode. 713let Constraints = "$src = $dst" in 714def t2MOVTi16 : T2sI<(outs GPR:$dst), (ins GPR:$src, i32imm:$imm), 715 "movt", " $dst, $imm", 716 [(set GPR:$dst, 717 (or (and GPR:$src, 0xffff), t2_lo16AllZero:$imm))]>; 718 719//===----------------------------------------------------------------------===// 720// Extend Instructions. 721// 722 723// Sign extenders 724 725defm t2SXTB : T2I_unary_rrot<"sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>; 726defm t2SXTH : T2I_unary_rrot<"sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>; 727 728defm t2SXTAB : T2I_bin_rrot<"sxtab", 729 BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>; 730defm t2SXTAH : T2I_bin_rrot<"sxtah", 731 BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>; 732 733// TODO: SXT(A){B|H}16 734 735// Zero extenders 736 737let AddedComplexity = 16 in { 738defm t2UXTB : T2I_unary_rrot<"uxtb" , UnOpFrag<(and node:$Src, 0x000000FF)>>; 739defm t2UXTH : T2I_unary_rrot<"uxth" , UnOpFrag<(and node:$Src, 0x0000FFFF)>>; 740defm t2UXTB16 : T2I_unary_rrot<"uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>; 741 742def : T2Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF), 743 (t2UXTB16r_rot GPR:$Src, 24)>; 744def : T2Pat<(and (srl GPR:$Src, (i32 8)), 0xFF00FF), 745 (t2UXTB16r_rot GPR:$Src, 8)>; 746 747defm t2UXTAB : T2I_bin_rrot<"uxtab", 748 BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>; 749defm t2UXTAH : T2I_bin_rrot<"uxtah", 750 BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>; 751} 752 753//===----------------------------------------------------------------------===// 754// Arithmetic Instructions. 755// 756 757defm t2ADD : T2I_bin_ii12rs<"add", BinOpFrag<(add node:$LHS, node:$RHS)>, 1>; 758defm t2SUB : T2I_bin_ii12rs<"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>; 759 760// ADD and SUB with 's' bit set. No 12-bit immediate (T4) variants. 761defm t2ADDS : T2I_bin_s_irs <"add", BinOpFrag<(addc node:$LHS, node:$RHS)>, 1>; 762defm t2SUBS : T2I_bin_s_irs <"sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>; 763 764defm t2ADC : T2I_adde_sube_irs<"adc",BinOpFrag<(adde node:$LHS, node:$RHS)>,1>; 765defm t2SBC : T2I_adde_sube_irs<"sbc",BinOpFrag<(sube node:$LHS, node:$RHS)>>; 766 767// RSB, RSC 768defm t2RSB : T2I_rbin_is <"rsb", BinOpFrag<(sub node:$LHS, node:$RHS)>>; 769defm t2RSBS : T2I_rbin_s_is <"rsb", BinOpFrag<(subc node:$LHS, node:$RHS)>>; 770defm t2RSC : T2I_rsc_is <"rsc", BinOpFrag<(sube node:$LHS, node:$RHS)>>; 771 772// (sub X, imm) gets canonicalized to (add X, -imm). Match this form. 773def : T2Pat<(add GPR:$src, t2_so_imm_neg:$imm), 774 (t2SUBri GPR:$src, t2_so_imm_neg:$imm)>; 775def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm), 776 (t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>; 777 778 779//===----------------------------------------------------------------------===// 780// Shift and rotate Instructions. 781// 782 783defm t2LSL : T2I_sh_ir<"lsl", BinOpFrag<(shl node:$LHS, node:$RHS)>>; 784defm t2LSR : T2I_sh_ir<"lsr", BinOpFrag<(srl node:$LHS, node:$RHS)>>; 785defm t2ASR : T2I_sh_ir<"asr", BinOpFrag<(sra node:$LHS, node:$RHS)>>; 786defm t2ROR : T2I_sh_ir<"ror", BinOpFrag<(rotr node:$LHS, node:$RHS)>>; 787 788def t2MOVrx : T2sI<(outs GPR:$dst), (ins GPR:$src), 789 "mov", " $dst, $src, rrx", 790 [(set GPR:$dst, (ARMrrx GPR:$src))]>; 791 792//===----------------------------------------------------------------------===// 793// Bitwise Instructions. 794// 795 796defm t2AND : T2I_bin_irs<"and", BinOpFrag<(and node:$LHS, node:$RHS)>, 1>; 797defm t2ORR : T2I_bin_irs<"orr", BinOpFrag<(or node:$LHS, node:$RHS)>, 1>; 798defm t2EOR : T2I_bin_irs<"eor", BinOpFrag<(xor node:$LHS, node:$RHS)>, 1>; 799 800defm t2BIC : T2I_bin_irs<"bic", BinOpFrag<(and node:$LHS, (not node:$RHS))>>; 801 802let Constraints = "$src = $dst" in 803def t2BFC : T2I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm), 804 "bfc", " $dst, $imm", 805 [(set GPR:$dst, (and GPR:$src, bf_inv_mask_imm:$imm))]>; 806 807// FIXME: A8.6.18 BFI - Bitfield insert (Encoding T1) 808 809defm t2ORN : T2I_bin_irs<"orn", BinOpFrag<(or node:$LHS, (not node:$RHS))>>; 810 811// Prefer over of t2EORri ra, rb, -1 because mvn has 16-bit version 812let AddedComplexity = 1 in 813defm t2MVN : T2I_un_irs <"mvn", UnOpFrag<(not node:$Src)>, 1, 1>; 814 815 816def : T2Pat<(and GPR:$src, t2_so_imm_not:$imm), 817 (t2BICri GPR:$src, t2_so_imm_not:$imm)>; 818 819def : T2Pat<(or GPR:$src, t2_so_imm_not:$imm), 820 (t2ORNri GPR:$src, t2_so_imm_not:$imm)>; 821 822def : T2Pat<(t2_so_imm_not:$src), 823 (t2MVNi t2_so_imm_not:$src)>; 824 825//===----------------------------------------------------------------------===// 826// Multiply Instructions. 827// 828let isCommutable = 1 in 829def t2MUL: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), 830 "mul", " $dst, $a, $b", 831 [(set GPR:$dst, (mul GPR:$a, GPR:$b))]>; 832 833def t2MLA: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), 834 "mla", " $dst, $a, $b, $c", 835 [(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>; 836 837def t2MLS: T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), 838 "mls", " $dst, $a, $b, $c", 839 [(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]>; 840 841// Extra precision multiplies with low / high results 842let neverHasSideEffects = 1 in { 843let isCommutable = 1 in { 844def t2SMULL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), 845 "smull", " $ldst, $hdst, $a, $b", []>; 846 847def t2UMULL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), 848 "umull", " $ldst, $hdst, $a, $b", []>; 849} 850 851// Multiply + accumulate 852def t2SMLAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), 853 "smlal", " $ldst, $hdst, $a, $b", []>; 854 855def t2UMLAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), 856 "umlal", " $ldst, $hdst, $a, $b", []>; 857 858def t2UMAAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), 859 "umaal", " $ldst, $hdst, $a, $b", []>; 860} // neverHasSideEffects 861 862// Most significant word multiply 863def t2SMMUL : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), 864 "smmul", " $dst, $a, $b", 865 [(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]>; 866 867def t2SMMLA : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), 868 "smmla", " $dst, $a, $b, $c", 869 [(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>; 870 871 872def t2SMMLS : T2I <(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), 873 "smmls", " $dst, $a, $b, $c", 874 [(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>; 875 876multiclass T2I_smul<string opc, PatFrag opnode> { 877 def BB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), 878 !strconcat(opc, "bb"), " $dst, $a, $b", 879 [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16), 880 (sext_inreg GPR:$b, i16)))]>; 881 882 def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), 883 !strconcat(opc, "bt"), " $dst, $a, $b", 884 [(set GPR:$dst, (opnode (sext_inreg GPR:$a, i16), 885 (sra GPR:$b, (i32 16))))]>; 886 887 def TB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), 888 !strconcat(opc, "tb"), " $dst, $a, $b", 889 [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)), 890 (sext_inreg GPR:$b, i16)))]>; 891 892 def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), 893 !strconcat(opc, "tt"), " $dst, $a, $b", 894 [(set GPR:$dst, (opnode (sra GPR:$a, (i32 16)), 895 (sra GPR:$b, (i32 16))))]>; 896 897 def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), 898 !strconcat(opc, "wb"), " $dst, $a, $b", 899 [(set GPR:$dst, (sra (opnode GPR:$a, 900 (sext_inreg GPR:$b, i16)), (i32 16)))]>; 901 902 def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), 903 !strconcat(opc, "wt"), " $dst, $a, $b", 904 [(set GPR:$dst, (sra (opnode GPR:$a, 905 (sra GPR:$b, (i32 16))), (i32 16)))]>; 906} 907 908 909multiclass T2I_smla<string opc, PatFrag opnode> { 910 def BB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), 911 !strconcat(opc, "bb"), " $dst, $a, $b, $acc", 912 [(set GPR:$dst, (add GPR:$acc, 913 (opnode (sext_inreg GPR:$a, i16), 914 (sext_inreg GPR:$b, i16))))]>; 915 916 def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), 917 !strconcat(opc, "bt"), " $dst, $a, $b, $acc", 918 [(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16), 919 (sra GPR:$b, (i32 16)))))]>; 920 921 def TB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), 922 !strconcat(opc, "tb"), " $dst, $a, $b, $acc", 923 [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)), 924 (sext_inreg GPR:$b, i16))))]>; 925 926 def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), 927 !strconcat(opc, "tt"), " $dst, $a, $b, $acc", 928 [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)), 929 (sra GPR:$b, (i32 16)))))]>; 930 931 def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), 932 !strconcat(opc, "wb"), " $dst, $a, $b, $acc", 933 [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a, 934 (sext_inreg GPR:$b, i16)), (i32 16))))]>; 935 936 def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), 937 !strconcat(opc, "wt"), " $dst, $a, $b, $acc", 938 [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a, 939 (sra GPR:$b, (i32 16))), (i32 16))))]>; 940} 941 942defm t2SMUL : T2I_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>; 943defm t2SMLA : T2I_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>; 944 945// TODO: Halfword multiple accumulate long: SMLAL<x><y> 946// TODO: Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD 947 948 949//===----------------------------------------------------------------------===// 950// Misc. Arithmetic Instructions. 951// 952 953def t2CLZ : T2I<(outs GPR:$dst), (ins GPR:$src), 954 "clz", " $dst, $src", 955 [(set GPR:$dst, (ctlz GPR:$src))]>; 956 957def t2REV : T2I<(outs GPR:$dst), (ins GPR:$src), 958 "rev", " $dst, $src", 959 [(set GPR:$dst, (bswap GPR:$src))]>; 960 961def t2REV16 : T2I<(outs GPR:$dst), (ins GPR:$src), 962 "rev16", " $dst, $src", 963 [(set GPR:$dst, 964 (or (and (srl GPR:$src, (i32 8)), 0xFF), 965 (or (and (shl GPR:$src, (i32 8)), 0xFF00), 966 (or (and (srl GPR:$src, (i32 8)), 0xFF0000), 967 (and (shl GPR:$src, (i32 8)), 0xFF000000)))))]>; 968 969def t2REVSH : T2I<(outs GPR:$dst), (ins GPR:$src), 970 "revsh", " $dst, $src", 971 [(set GPR:$dst, 972 (sext_inreg 973 (or (srl (and GPR:$src, 0xFFFF), (i32 8)), 974 (shl GPR:$src, (i32 8))), i16))]>; 975 976def t2PKHBT : T2I<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt), 977 "pkhbt", " $dst, $src1, $src2, LSL $shamt", 978 [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF), 979 (and (shl GPR:$src2, (i32 imm:$shamt)), 980 0xFFFF0000)))]>; 981 982// Alternate cases for PKHBT where identities eliminate some nodes. 983def : T2Pat<(or (and GPR:$src1, 0xFFFF), (and GPR:$src2, 0xFFFF0000)), 984 (t2PKHBT GPR:$src1, GPR:$src2, 0)>; 985def : T2Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)), 986 (t2PKHBT GPR:$src1, GPR:$src2, imm16_31:$shamt)>; 987 988def t2PKHTB : T2I<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt), 989 "pkhtb", " $dst, $src1, $src2, ASR $shamt", 990 [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000), 991 (and (sra GPR:$src2, imm16_31:$shamt), 992 0xFFFF)))]>; 993 994// Alternate cases for PKHTB where identities eliminate some nodes. Note that 995// a shift amount of 0 is *not legal* here, it is PKHBT instead. 996def : T2Pat<(or (and GPR:$src1, 0xFFFF0000), (srl GPR:$src2, (i32 16))), 997 (t2PKHTB GPR:$src1, GPR:$src2, 16)>; 998def : T2Pat<(or (and GPR:$src1, 0xFFFF0000), 999 (and (srl GPR:$src2, imm1_15:$shamt), 0xFFFF)), 1000 (t2PKHTB GPR:$src1, GPR:$src2, imm1_15:$shamt)>; 1001 1002//===----------------------------------------------------------------------===// 1003// Comparison Instructions... 1004// 1005 1006defm t2CMP : T2I_cmp_is<"cmp", 1007 BinOpFrag<(ARMcmp node:$LHS, node:$RHS)>>; 1008defm t2CMPz : T2I_cmp_is<"cmp", 1009 BinOpFrag<(ARMcmpZ node:$LHS, node:$RHS)>>; 1010 1011defm t2CMN : T2I_cmp_is<"cmn", 1012 BinOpFrag<(ARMcmp node:$LHS,(ineg node:$RHS))>>; 1013defm t2CMNz : T2I_cmp_is<"cmn", 1014 BinOpFrag<(ARMcmpZ node:$LHS,(ineg node:$RHS))>>; 1015 1016def : T2Pat<(ARMcmp GPR:$src, t2_so_imm_neg:$imm), 1017 (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>; 1018 1019def : T2Pat<(ARMcmpZ GPR:$src, t2_so_imm_neg:$imm), 1020 (t2CMNri GPR:$src, t2_so_imm_neg:$imm)>; 1021 1022defm t2TST : T2I_cmp_is<"tst", 1023 BinOpFrag<(ARMcmpZ (and node:$LHS, node:$RHS), 0)>>; 1024defm t2TEQ : T2I_cmp_is<"teq", 1025 BinOpFrag<(ARMcmpZ (xor node:$LHS, node:$RHS), 0)>>; 1026 1027// A8.6.27 CBNZ, CBZ - Compare and branch on (non)zero. 1028// Short range conditional branch. Looks awesome for loops. Need to figure 1029// out how to use this one. 1030 1031 1032// Conditional moves 1033// FIXME: should be able to write a pattern for ARMcmov, but can't use 1034// a two-value operand where a dag node expects two operands. :( 1035def t2MOVCCr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true), 1036 "mov", " $dst, $true", 1037 [/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>, 1038 RegConstraint<"$false = $dst">; 1039 1040def t2MOVCCs : T2I<(outs GPR:$dst), (ins GPR:$false, t2_so_reg:$true), 1041 "mov", " $dst, $true", 1042[/*(set GPR:$dst, (ARMcmov GPR:$false, t2_so_reg:$true, imm:$cc, CCR:$ccr))*/]>, 1043 RegConstraint<"$false = $dst">; 1044 1045def t2MOVCCi : T2I<(outs GPR:$dst), (ins GPR:$false, t2_so_imm:$true), 1046 "mov", " $dst, $true", 1047[/*(set GPR:$dst, (ARMcmov GPR:$false, t2_so_imm:$true, imm:$cc, CCR:$ccr))*/]>, 1048 RegConstraint<"$false = $dst">; 1049 1050//===----------------------------------------------------------------------===// 1051// TLS Instructions 1052// 1053 1054// __aeabi_read_tp preserves the registers r1-r3. 1055let isCall = 1, 1056 Defs = [R0, R12, LR, CPSR] in { 1057 def t2TPsoft : T2XI<(outs), (ins), 1058 "bl __aeabi_read_tp", 1059 [(set R0, ARMthread_pointer)]>; 1060} 1061 1062//===----------------------------------------------------------------------===// 1063// Control-Flow Instructions 1064// 1065 1066//let isReturn = 1, isTerminator = 1 in 1067// def t2BX_RET : T2XI<(outs), (ins), "bx lr", [(ARMretflag)]>; 1068// 1069// On non-Darwin platforms R9 is callee-saved. 1070//let isCall = 1, 1071// Defs = [R0, R1, R2, R3, R12, LR, 1072// D0, D1, D2, D3, D4, D5, D6, D7, CPSR] in { 1073//def t2BL : T2XI<(outs), (ins i32imm:$func, variable_ops), 1074// "bl ${func:call}", 1075// [(ARMcall tglobaladdr:$func)]>, Requires<[IsNotDarwin]>; 1076// 1077//def t2BLX : T2XI<(outs), (ins GPR:$func, variable_ops), 1078// "blx $func", 1079// [(ARMcall GPR:$func)]>, Requires<[IsNotDarwin]>; 1080//} 1081 1082// On Darwin R9 is call-clobbered. 1083//let isCall = 1, 1084// Defs = [R0, R1, R2, R3, R9, R12, LR, 1085// D0, D1, D2, D3, D4, D5, D6, D7, CPSR] in { 1086//def t2BLr9 : T2XI<(outs), (ins i32imm:$func, variable_ops), 1087// "bl ${func:call}", 1088// [(ARMcall tglobaladdr:$func)]>, Requires<[IsDarwin]>; 1089// 1090//def t2BLXr9 : T2XI<(outs), (ins GPR:$func, variable_ops), 1091// "blx $func", 1092// [(ARMcall GPR:$func)]>, Requires<[IsDarwin]>; 1093//} 1094 1095let isBranch = 1, isTerminator = 1, isBarrier = 1 in { 1096let isPredicable = 1 in 1097def t2B : T2XI<(outs), (ins brtarget:$target), 1098 "b $target", 1099 [(br bb:$target)]>; 1100 1101let isNotDuplicable = 1, isIndirectBranch = 1 in { 1102def t2BR_JTr : T2JTI<(outs), (ins GPR:$target, jtblock_operand:$jt, i32imm:$id), 1103 "mov pc, $target \n$jt", 1104 [(ARMbrjt GPR:$target, tjumptable:$jt, imm:$id)]>; 1105 1106def t2BR_JTm : 1107 T2JTI<(outs), 1108 (ins t2addrmode_so_reg:$target, jtblock_operand:$jt, i32imm:$id), 1109 "ldr pc, $target \n$jt", 1110 [(ARMbrjt (i32 (load t2addrmode_so_reg:$target)), tjumptable:$jt, 1111 imm:$id)]>; 1112 1113def t2BR_JTadd : 1114 T2JTI<(outs), 1115 (ins GPR:$target, GPR:$idx, jtblock_operand:$jt, i32imm:$id), 1116 "add pc, $target, $idx \n$jt", 1117 [(ARMbrjt (add GPR:$target, GPR:$idx), tjumptable:$jt, imm:$id)]>; 1118} // isNotDuplicate, isIndirectBranch 1119} // isBranch, isTerminator, isBarrier 1120 1121// FIXME: should be able to write a pattern for ARMBrcond, but can't use 1122// a two-value operand where a dag node expects two operands. :( 1123let isBranch = 1, isTerminator = 1 in 1124def t2Bcc : T2I<(outs), (ins brtarget:$target), 1125 "b", " $target", 1126 [/*(ARMbrcond bb:$target, imm:$cc)*/]>; 1127 1128//===----------------------------------------------------------------------===// 1129// Non-Instruction Patterns 1130// 1131 1132// ConstantPool, GlobalAddress, and JumpTable 1133def : T2Pat<(ARMWrapper tglobaladdr :$dst), (t2LEApcrel tglobaladdr :$dst)>; 1134def : T2Pat<(ARMWrapper tconstpool :$dst), (t2LEApcrel tconstpool :$dst)>; 1135def : T2Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), 1136 (t2LEApcrelJT tjumptable:$dst, imm:$id)>; 1137 1138// Large immediate handling. 1139 1140def : T2Pat<(i32 imm:$src), 1141 (t2MOVTi16 (t2MOVi16 (t2_lo16 imm:$src)), (t2_hi16 imm:$src))>; 1142