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