1//===- XtensaInstrInfo.td - Target Description for Xtensa -*- tablegen -*--===// 2// 3// The LLVM Compiler Infrastructure 4// 5// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6// See https://llvm.org/LICENSE.txt for license information. 7// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8// 9//===----------------------------------------------------------------------===// 10// 11// This file describes the Xtensa instructions in TableGen format. 12// 13//===----------------------------------------------------------------------===// 14 15include "XtensaInstrFormats.td" 16include "XtensaOperands.td" 17include "XtensaOperators.td" 18 19//===----------------------------------------------------------------------===// 20// Arithmetic & Logical instructions 21//===----------------------------------------------------------------------===// 22 23class ArithLogic_RRR<bits<4> oper2, bits<4> oper1, string instrAsm, 24 SDPatternOperator opNode, bit isComm = 0> 25 : RRR_Inst<0x00, oper1, oper2, (outs AR:$r), (ins AR:$s, AR:$t), 26 instrAsm#"\t$r, $s, $t", 27 [(set AR:$r, (opNode AR:$s, AR:$t))]> { 28 let isCommutable = isComm; 29 let isReMaterializable = 0; 30} 31 32def ADD : ArithLogic_RRR<0x08, 0x00, "add", add, 1>; 33def SUB : ArithLogic_RRR<0x0C, 0x00, "sub", sub>; 34def AND : ArithLogic_RRR<0x01, 0x00, "and", and, 1>; 35def OR : ArithLogic_RRR<0x02, 0x00, "or", or, 1>; 36def XOR : ArithLogic_RRR<0x03, 0x00, "xor", xor, 1>; 37 38class ADDX<bits<4> oper, string instrAsm, list<dag> pattern> 39 : RRR_Inst<0x00, 0x00, oper, (outs AR:$r), (ins AR:$s, AR:$t), 40 instrAsm#"\t$r, $s, $t", pattern>; 41 42def ADDX2 : ADDX<0x09, "addx2", [(set AR:$r, (add AR:$t, (shl AR:$s, (i32 1))))]>; 43def ADDX4 : ADDX<0x0A, "addx4", [(set AR:$r, (add AR:$t, (shl AR:$s, (i32 2))))]>; 44def ADDX8 : ADDX<0x0B, "addx8", [(set AR:$r, (add AR:$t, (shl AR:$s, (i32 3))))]>; 45 46class SUBX<bits<4> oper, string instrAsm, list<dag> pattern> 47 : RRR_Inst<0x00, 0x00, oper, (outs AR:$r), (ins AR:$s, AR:$t), 48 instrAsm#"\t$r, $s, $t", pattern>; 49 50def SUBX2 : SUBX<0x0D, "subx2", [(set AR:$r, (sub (shl AR:$s, (i32 1)), AR:$t))]>; 51def SUBX4 : SUBX<0x0E, "subx4", [(set AR:$r, (sub (shl AR:$s, (i32 2)), AR:$t))]>; 52def SUBX8 : SUBX<0x0F, "subx8", [(set AR:$r, (sub (shl AR:$s, (i32 3)), AR:$t))]>; 53 54def ABS : RRR_Inst<0x00, 0x00, 0x06, (outs AR:$r), (ins AR:$t), 55 "abs\t$r, $t", []> { 56 let s = 0x1; 57} 58 59def ADDI : RRI8_Inst<0x02, (outs AR:$t), (ins AR:$s, imm8:$imm8), 60 "addi\t$t, $s, $imm8", 61 [(set AR:$t, (add AR:$s, imm8:$imm8))]> { 62 let r = 0x0C; 63} 64 65def ADDMI : RRI8_Inst<0x02, (outs AR:$t), (ins AR:$s, imm8_sh8:$imm_sh8), 66 "addmi\t$t, $s, $imm_sh8", 67 [(set AR:$t, (add AR:$s, imm8_sh8:$imm_sh8))]> { 68 bits<16> imm_sh8; 69 70 let r = 0x0D; 71 let imm8 = imm_sh8{15-8}; 72} 73 74def NEG : RRR_Inst<0x00, 0x00, 0x06, (outs AR:$r), (ins AR:$t), 75 "neg\t$r, $t", 76 [(set AR:$r, (ineg AR:$t))]> { 77 let s = 0x00; 78} 79 80//===----------------------------------------------------------------------===// 81// Move instructions 82//===----------------------------------------------------------------------===// 83def MOVI : RRI8_Inst<0x02, (outs AR:$t), (ins imm12m:$imm), 84 "movi\t$t, $imm", 85 [(set AR:$t, imm12m:$imm)]> { 86 bits<12> imm; 87 88 let imm8{7-0} = imm{7-0}; 89 let s{3-0} = imm{11-8}; 90 let r = 0xa; 91} 92 93def MOVEQZ : RRR_Inst<0x00, 0x03, 0x08, (outs AR:$r), (ins AR:$s, AR:$t), 94 "moveqz\t$r, $s, $t", []>; 95def MOVNEZ : RRR_Inst<0x00, 0x03, 0x09, (outs AR:$r), (ins AR:$s, AR:$t), 96 "movnez\t$r, $s, $t", []>; 97def MOVLTZ : RRR_Inst<0x00, 0x03, 0x0A, (outs AR:$r), (ins AR:$s, AR:$t), 98 "movltz\t$r, $s, $t", []>; 99def MOVGEZ : RRR_Inst<0x00, 0x03, 0x0B, (outs AR:$r), (ins AR:$s, AR:$t), 100 "movgez\t$r, $s, $t", []>; 101 102//===----------------------------------------------------------------------===// 103// Shift instructions 104//===----------------------------------------------------------------------===// 105 106let Uses = [SAR] in { 107 def SLL : RRR_Inst<0x00, 0x01, 0x0A, (outs AR:$r), (ins AR:$s), 108 "sll\t$r, $s", []> { 109 let t = 0x00; 110 } 111 112 def SRA : RRR_Inst<0x00, 0x01, 0x0B, (outs AR:$r), (ins AR:$t), 113 "sra\t$r, $t", []> { 114 let s = 0x00; 115 } 116 117 def SRC : RRR_Inst<0x00, 0x01, 0x08, (outs AR:$r), (ins AR:$s, AR:$t), 118 "src\t$r, $s, $t", []>; 119 120 def SRL : RRR_Inst<0x00, 0x01, 0x09, (outs AR:$r), (ins AR:$t), 121 "srl\t$r, $t", []> { 122 let s = 0x00; 123 } 124} 125 126let Defs = [SAR] in { 127 def SSL : RRR_Inst<0x00, 0x00, 0x04, (outs), (ins AR:$s), 128 "ssl\t$s", []> { 129 let r = 0x01; 130 let t = 0x00; 131 } 132 133 def SSR : RRR_Inst<0x00, 0x00, 0x04, (outs), (ins AR:$s), 134 "ssr\t$s", []> { 135 let r = 0x00; 136 let t = 0x00; 137 } 138} 139 140def EXTUI : RRR_Inst<0x00, 0x04, 0x00, (outs AR:$r), (ins AR:$t, uimm5:$imm1, imm1_16:$imm2), 141 "extui\t$r, $t, $imm1, $imm2", []> { 142 bits<5> imm1; 143 bits<4> imm2; 144 145 let s = imm1{3-0}; 146 let Inst{16} = imm1{4}; 147 let Inst{23-20} = imm2; 148} 149 150def SRAI : RRR_Inst<0x00, 0x01, 0x02, (outs AR:$r), (ins AR:$t, uimm5:$sa), 151 "srai\t$r, $t, $sa", 152 [(set AR:$r, (sra AR:$t, uimm5:$sa))]> { 153 bits<5> sa; 154 155 let Inst{20} = sa{4}; 156 let s = sa{3-0}; 157} 158 159def SRLI : RRR_Inst<0x00, 0x01, 0x04, (outs AR:$r), (ins AR:$t, uimm4:$sa), 160 "srli\t$r, $t, $sa", 161 [(set AR:$r, (srl AR:$t, uimm4:$sa))]> { 162 bits<4> sa; 163 164 let s = sa; 165} 166 167def SLLI : RRR_Inst<0x00, 0x01, 0x00, (outs AR:$r), (ins AR:$s, shimm1_31:$sa), 168 "slli\t$r, $s, $sa", 169 [(set AR:$r, (shl AR:$s, shimm1_31:$sa))]> { 170 bits<5> sa; 171 172 let Inst{20} = sa{4}; 173 let t = sa{3-0}; 174} 175 176def SSA8L : RRR_Inst<0x00, 0x00, 0x04, (outs), (ins AR:$s), 177 "ssa8l\t$s", []> { 178 let r = 0x2; 179 let t = 0x0; 180} 181 182def SSAI : RRR_Inst<0x00, 0x00, 0x04, (outs), (ins uimm5:$imm), 183 "ssai\t$imm", []> { 184 bits<5> imm; 185 186 let r = 0x04; 187 let s = imm{3-0}; 188 let t{3-1} = 0; 189 let t{0} = imm{4}; 190} 191 192//===----------------------------------------------------------------------===// 193// Load and store instructions 194//===----------------------------------------------------------------------===// 195 196// Load instructions 197let mayLoad = 1 in { 198 199 class Load_RRI8<bits<4> oper, string instrAsm, SDPatternOperator opNode, 200 ComplexPattern addrOp, Operand memOp> 201 : RRI8_Inst<0x02, (outs AR:$t), (ins memOp:$addr), 202 instrAsm#"\t$t, $addr", 203 [(set AR:$t, (opNode addrOp:$addr))]> { 204 bits<12> addr; 205 206 let r = oper; 207 let imm8{7-0} = addr{11-4}; 208 let s{3-0} = addr{3-0}; 209 } 210} 211 212def L8UI : Load_RRI8<0x00, "l8ui", zextloadi8, addr_ish1, mem8>; 213def L16SI : Load_RRI8<0x09, "l16si", sextloadi16, addr_ish2, mem16>; 214def L16UI : Load_RRI8<0x01, "l16ui", zextloadi16, addr_ish2, mem16>; 215def L32I : Load_RRI8<0x02, "l32i", load, addr_ish4, mem32>; 216 217// Store instructions 218let mayStore = 1 in { 219 class Store_II8<bits<4> oper, string instrAsm, SDPatternOperator opNode, 220 ComplexPattern addrOp, Operand memOp> 221 : RRI8_Inst<0x02, (outs), (ins AR:$t, memOp:$addr), 222 instrAsm#"\t$t, $addr", 223 [(opNode AR:$t, addrOp:$addr)]> { 224 bits<12> addr; 225 226 let r = oper; 227 let imm8{7-0} = addr{11-4}; 228 let s{3-0} = addr{3-0}; 229 } 230} 231 232def S8I : Store_II8<0x04, "s8i", truncstorei8, addr_ish1, mem8>; 233def S16I : Store_II8<0x05, "s16i", truncstorei16, addr_ish2, mem16>; 234def S32I : Store_II8<0x06, "s32i", store, addr_ish4, mem32>; 235 236def L32R : RI16_Inst<0x01, (outs AR:$t), (ins L32Rtarget:$label), 237 "l32r\t$t, $label", []> { 238 bits<16> label; 239 let imm16 = label; 240} 241 242// pcrel addr loading using L32R 243def : Pat<(Xtensa_pcrel_wrapper tconstpool : $in), (L32R tconstpool : $in)>; 244 245// FrameIndexes are legalized when they are operands from load/store 246// instructions. The same not happens for stack address copies, so an 247// add op with mem ComplexPattern is used and the stack address copy 248// can be matched. 249// Setting of attribute mayLoad is trick to process instruction operands 250// in function XtensaRegisterInfo::eliminateFI 251 252let isCodeGenOnly = 1, mayLoad = 1 in { 253 254 def LEA_ADD : RRI8_Inst<0x02, (outs AR:$t), (ins mem32:$addr), 255 "addi\t$t, $addr", 256 [(set AR:$t, addr_ish4:$addr)]> { 257 bits<12> addr; 258 259 let r = 0x0C; 260 let imm8{7-0} = addr{11-4}; 261 let s{3-0} = addr{3-0}; 262 } 263} 264 265//extending loads 266def : Pat<(i32 (extloadi1 addr_ish1:$addr)), (L8UI addr_ish1:$addr)>; 267def : Pat<(i32 (extloadi8 addr_ish1:$addr)), (L8UI addr_ish1:$addr)>; 268def : Pat<(i32 (extloadi16 addr_ish2:$addr)), (L16UI addr_ish2:$addr)>; 269 270//===----------------------------------------------------------------------===// 271// Conditional branch instructions 272//===----------------------------------------------------------------------===// 273let isBranch = 1, isTerminator = 1 in { 274 class Branch_RR<bits<4> oper, string instrAsm, CondCode CC> 275 : RRI8_Inst<0x07, (outs), 276 (ins AR:$s, AR:$t, brtarget:$target), 277 instrAsm#"\t$s, $t, $target", 278 [(brcc CC, AR:$s, AR:$t, bb:$target)]> { 279 bits<8> target; 280 281 let r = oper; 282 let imm8 = target; 283 } 284 285 class Branch_RI<bits<4> oper, string instrAsm, CondCode CC> 286 : RRI8_Inst<0x06, (outs), 287 (ins AR:$s, b4const:$imm, brtarget:$target), 288 instrAsm#"\t$s, $imm, $target", 289 [(brcc CC, AR:$s, b4const:$imm, bb:$target)]> { 290 bits<4> imm; 291 bits<8> target; 292 293 let t = oper; 294 let r = imm; 295 let imm8 = target; 296 } 297 298 class Branch_RIU<bits<4> oper, string instrAsm, CondCode CC> 299 : RRI8_Inst<0x06, (outs), 300 (ins AR:$s, b4constu:$imm, brtarget:$target), 301 instrAsm#"\t$s, $imm, $target", 302 [(brcc CC, AR:$s, b4constu:$imm, bb:$target)]> { 303 bits<4> imm; 304 bits<8> target; 305 306 let t = oper; 307 let r = imm; 308 let imm8 = target; 309 } 310 311 class Branch_RZ<bits<2> n, bits<2> m, string instrAsm, CondCode CC> 312 : BRI12_Inst<0x06, n, m, (outs), 313 (ins AR:$s, brtarget:$target), 314 instrAsm#"\t$s, $target", 315 [(brcc CC, AR:$s, (i32 0), bb:$target)]> { 316 bits<12> target; 317 318 let imm12 = target; 319 } 320} 321 322def BEQ : Branch_RR<0x01, "beq", SETEQ>; 323def BNE : Branch_RR<0x09, "bne", SETNE>; 324def BGE : Branch_RR<0x0A, "bge", SETGE>; 325def BLT : Branch_RR<0x02, "blt", SETLT>; 326def BGEU : Branch_RR<0x0B, "bgeu", SETUGE>; 327def BLTU : Branch_RR<0x03, "bltu", SETULT>; 328 329def BEQI : Branch_RI<0x02, "beqi", SETEQ>; 330def BNEI : Branch_RI<0x06, "bnei", SETNE>; 331def BGEI : Branch_RI<0x0E, "bgei", SETGE>; 332def BLTI : Branch_RI<0x0A, "blti", SETLT>; 333def BGEUI : Branch_RIU<0x0F, "bgeui", SETUGE>; 334def BLTUI : Branch_RIU<0x0B, "bltui", SETULT>; 335 336def BEQZ : Branch_RZ<0x01, 0x00, "beqz", SETEQ>; 337def BNEZ : Branch_RZ<0x01, 0x01, "bnez", SETNE>; 338def BGEZ : Branch_RZ<0x01, 0x03, "bgez", SETGE>; 339def BLTZ : Branch_RZ<0x01, 0x02, "bltz", SETLT>; 340 341def BALL : RRI8_Inst<0x07, (outs), 342 (ins AR:$s, AR:$t, brtarget:$target), 343 "ball\t$s, $t, $target", []> { 344 bits<8> target; 345 346 let r = 0x04; 347 let imm8 = target; 348} 349 350def BANY : RRI8_Inst<0x07, (outs), 351 (ins AR:$s, AR:$t, brtarget:$target), 352 "bany\t$s, $t, $target", []> { 353 bits<8> target; 354 355 let r = 0x08; 356 let imm8 = target; 357} 358 359def BBC : RRI8_Inst<0x07, (outs), 360 (ins AR:$s, AR:$t, brtarget:$target), 361 "bbc\t$s, $t, $target", []> { 362 bits<8> target; 363 364 let r = 0x05; 365 let imm8 = target; 366} 367 368def BBS : RRI8_Inst<0x07, (outs), 369 (ins AR:$s, AR:$t, brtarget:$target), 370 "bbs\t$s, $t, $target", []> { 371 bits<8> target; 372 373 let r = 0x0d; 374 let imm8 = target; 375} 376 377def BNALL : RRI8_Inst<0x07, (outs), 378 (ins AR:$s, AR:$t, brtarget:$target), 379 "bnall\t$s, $t, $target", []> { 380 bits<8> target; 381 382 let r = 0x0c; 383 let imm8 = target; 384} 385 386def BNONE : RRI8_Inst<0x07, (outs), 387 (ins AR:$s, AR:$t, brtarget:$target), 388 "bnone\t$s, $t, $target", []> { 389 bits<8> target; 390 391 let r = 0x00; 392 let imm8 = target; 393} 394 395def BBCI : RRI8_Inst<0x07, (outs), 396 (ins AR:$s, uimm5:$imm, brtarget:$target), 397 "bbci\t$s, $imm, $target", []> { 398 bits<8> target; 399 bits<5> imm; 400 401 let r{3-1} = 0x3; 402 let r{0} = imm{4}; 403 let t{3-0} = imm{3-0}; 404 let imm8 = target; 405} 406 407def BBSI : RRI8_Inst<0x07, (outs), 408 (ins AR:$s, uimm5:$imm, brtarget:$target), 409 "bbsi\t$s, $imm, $target", []> { 410 bits<8> target; 411 bits<5> imm; 412 413 let r{3-1} = 0x7; 414 let r{0} = imm{4}; 415 let t{3-0} = imm{3-0}; 416 let imm8 = target; 417} 418 419//===----------------------------------------------------------------------===// 420// Call and jump instructions 421//===----------------------------------------------------------------------===// 422 423let isBranch = 1, isTerminator = 1, isBarrier = 1 in { 424 def J : CALL_Inst<0x06, (outs), (ins jumptarget:$offset), 425 "j\t$offset", 426 [(br bb:$offset)]> { 427 let n = 0x0; 428 } 429 430 def JX : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s), 431 "jx\t$s", 432 [(brind AR:$s)]> { 433 let m = 0x2; 434 let n = 0x2; 435 let r = 0; 436 let isIndirectBranch = 1; 437 } 438} 439 440let isCall = 1, Defs = [A0] in { 441 def CALL0 : CALL_Inst<0x05, (outs), (ins pcrel32call:$offset), 442 "call0\t$offset", []> { 443 let n = 0; 444 } 445 446 def CALLX0 : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins AR:$s), 447 "callx0\t$s", []> { 448 let m = 0x3; 449 let n = 0x0; 450 let r = 0; 451 } 452} 453 454let isReturn = 1, isTerminator = 1, 455 isBarrier = 1, Uses = [A0] in { 456 457 def RET : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins), 458 "ret", [(Xtensa_ret)]> { 459 let m = 0x2; 460 let n = 0x0; 461 let s = 0; 462 let r = 0; 463 } 464} 465 466// Call patterns 467def : Pat<(Xtensa_call (i32 tglobaladdr:$dst)), 468 (CALL0 tglobaladdr:$dst)>; 469def : Pat<(Xtensa_call (i32 texternalsym:$dst)), 470 (CALL0 texternalsym:$dst)>; 471def : Pat<(Xtensa_call AR:$dst), 472 (CALLX0 AR:$dst)>; 473 474let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1, Size = 3 in { 475 def BR_JT: Pseudo<(outs), (ins AR:$s, i32imm:$jt), 476 "!br_jt_p, $s, $jt", 477 [(Xtensa_brjt AR:$s, tjumptable:$jt)]>; 478} 479 480//===----------------------------------------------------------------------===// 481// Mem barrier instructions 482//===----------------------------------------------------------------------===// 483 484def MEMW : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins), 485 "memw", []> { 486 let r = 0x2; 487 let t = 0x0c; 488 let s = 0x0; 489} 490 491def EXTW : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins), 492 "extw", []> { 493 let r = 0x2; 494 let s = 0x0; 495 let t = 0xd; 496 let hasSideEffects = 1; 497} 498 499//===----------------------------------------------------------------------===// 500// Processor control instructions 501//===----------------------------------------------------------------------===// 502 503def DSYNC : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins), 504 "dsync", []> { 505 let r = 0x2; 506 let s = 0x0; 507 let t = 0x3; 508 let hasSideEffects = 1; 509} 510 511def ISYNC : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins), 512 "isync", []> { 513 let r = 0x2; 514 let s = 0x0; 515 let t = 0x0; 516 let hasSideEffects = 1; 517} 518 519def RSYNC : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins), 520 "rsync", []> { 521 let r = 0x2; 522 let s = 0x0; 523 let t = 0x1; 524 let hasSideEffects = 1; 525} 526 527def ESYNC : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins), 528 "esync", []> { 529 let r = 0x2; 530 let s = 0x0; 531 let t = 0x2; 532 let hasSideEffects = 1; 533} 534 535def NOP : RRR_Inst<0x00, 0x00, 0x00, (outs), (ins), 536 "nop", []> { 537 let r = 0x02; 538 let s = 0x00; 539 let t = 0x0f; 540} 541 542def WSR : RSR_Inst<0x00, 0x03, 0x01, (outs SR:$sr), (ins AR:$t), 543 "wsr\t$t, $sr", []>; 544 545def RSR : RSR_Inst<0x00, 0x03, 0x00, (outs AR:$t), (ins SR:$sr), 546 "rsr\t$t, $sr", []>; 547 548def XSR : RSR_Inst<0x00, 0x01, 0x06, (outs AR:$ard, SR:$srd), (ins AR:$t, SR:$sr), 549 "xsr\t$t, $sr", []> { 550 let Constraints = "$ard = $t, $srd = $sr"; 551} 552 553//===----------------------------------------------------------------------===// 554// Stack allocation 555//===----------------------------------------------------------------------===// 556 557// ADJCALLSTACKDOWN/UP implicitly use/def SP because they may be expanded into 558// a stack adjustment and the codegen must know that they may modify the stack 559// pointer before prolog-epilog rewriting occurs. 560let Defs = [SP], Uses = [SP] in { 561 def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 562 "#ADJCALLSTACKDOWN", 563 [(Xtensa_callseq_start timm:$amt1, timm:$amt2)]>; 564 def ADJCALLSTACKUP : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2), 565 "#ADJCALLSTACKUP", 566 [(Xtensa_callseq_end timm:$amt1, timm:$amt2)]>; 567} 568 569//===----------------------------------------------------------------------===// 570// Generic select instruction 571//===----------------------------------------------------------------------===// 572let usesCustomInserter = 1 in { 573 def SELECT : Pseudo<(outs AR:$dst), (ins AR:$lhs, AR:$rhs, AR:$t, AR:$f, i32imm:$cond), 574 "!select $dst, $lhs, $rhs, $t, $f, $cond", 575 [(set i32:$dst, (Xtensa_select_cc i32:$lhs, i32:$rhs, i32:$t, i32:$f, imm:$cond))]>; 576} 577