1//==- SystemZInstrFormats.td - SystemZ Instruction Formats --*- tablegen -*-==// 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//===----------------------------------------------------------------------===// 11// Basic SystemZ instruction definition 12//===----------------------------------------------------------------------===// 13 14class InstSystemZ<int size, dag outs, dag ins, string asmstr, 15 list<dag> pattern> : Instruction { 16 let Namespace = "SystemZ"; 17 18 dag OutOperandList = outs; 19 dag InOperandList = ins; 20 let Size = size; 21 let Pattern = pattern; 22 let AsmString = asmstr; 23 24 // Some instructions come in pairs, one having a 12-bit displacement 25 // and the other having a 20-bit displacement. Both instructions in 26 // the pair have the same DispKey and their DispSizes are "12" and "20" 27 // respectively. 28 string DispKey = ""; 29 string DispSize = "none"; 30 31 // Many register-based <INSN>R instructions have a memory-based <INSN> 32 // counterpart. OpKey uniquely identifies <INSN>, while OpType is 33 // "reg" for <INSN>R and "mem" for <INSN>. 34 string OpKey = ""; 35 string OpType = "none"; 36 37 // Many distinct-operands instructions have older 2-operand equivalents. 38 // NumOpsKey uniquely identifies one of these 2-operand and 3-operand pairs, 39 // with NumOpsValue being "2" or "3" as appropriate. 40 string NumOpsKey = ""; 41 string NumOpsValue = "none"; 42 43 // True if this instruction is a simple D(X,B) load of a register 44 // (with no sign or zero extension). 45 bit SimpleBDXLoad = 0; 46 47 // True if this instruction is a simple D(X,B) store of a register 48 // (with no truncation). 49 bit SimpleBDXStore = 0; 50 51 // True if this instruction has a 20-bit displacement field. 52 bit Has20BitOffset = 0; 53 54 // True if addresses in this instruction have an index register. 55 bit HasIndex = 0; 56 57 // True if this is a 128-bit pseudo instruction that combines two 64-bit 58 // operations. 59 bit Is128Bit = 0; 60 61 // The access size of all memory operands in bytes, or 0 if not known. 62 bits<5> AccessBytes = 0; 63 64 // If the instruction sets CC to a useful value, this gives the mask 65 // of all possible CC results. The mask has the same form as 66 // SystemZ::CCMASK_*. 67 bits<4> CCValues = 0; 68 69 // The subset of CCValues that have the same meaning as they would after 70 // a comparison of the first operand against zero. 71 bits<4> CompareZeroCCMask = 0; 72 73 // True if the instruction is conditional and if the CC mask operand 74 // comes first (as for BRC, etc.). 75 bit CCMaskFirst = 0; 76 77 // Similar, but true if the CC mask operand comes last (as for LOC, etc.). 78 bit CCMaskLast = 0; 79 80 // True if the instruction is the "logical" rather than "arithmetic" form, 81 // in cases where a distinction exists. 82 bit IsLogical = 0; 83 84 let TSFlags{0} = SimpleBDXLoad; 85 let TSFlags{1} = SimpleBDXStore; 86 let TSFlags{2} = Has20BitOffset; 87 let TSFlags{3} = HasIndex; 88 let TSFlags{4} = Is128Bit; 89 let TSFlags{9-5} = AccessBytes; 90 let TSFlags{13-10} = CCValues; 91 let TSFlags{17-14} = CompareZeroCCMask; 92 let TSFlags{18} = CCMaskFirst; 93 let TSFlags{19} = CCMaskLast; 94 let TSFlags{20} = IsLogical; 95} 96 97//===----------------------------------------------------------------------===// 98// Mappings between instructions 99//===----------------------------------------------------------------------===// 100 101// Return the version of an instruction that has an unsigned 12-bit 102// displacement. 103def getDisp12Opcode : InstrMapping { 104 let FilterClass = "InstSystemZ"; 105 let RowFields = ["DispKey"]; 106 let ColFields = ["DispSize"]; 107 let KeyCol = ["20"]; 108 let ValueCols = [["12"]]; 109} 110 111// Return the version of an instruction that has a signed 20-bit displacement. 112def getDisp20Opcode : InstrMapping { 113 let FilterClass = "InstSystemZ"; 114 let RowFields = ["DispKey"]; 115 let ColFields = ["DispSize"]; 116 let KeyCol = ["12"]; 117 let ValueCols = [["20"]]; 118} 119 120// Return the memory form of a register instruction. 121def getMemOpcode : InstrMapping { 122 let FilterClass = "InstSystemZ"; 123 let RowFields = ["OpKey"]; 124 let ColFields = ["OpType"]; 125 let KeyCol = ["reg"]; 126 let ValueCols = [["mem"]]; 127} 128 129// Return the 3-operand form of a 2-operand instruction. 130def getThreeOperandOpcode : InstrMapping { 131 let FilterClass = "InstSystemZ"; 132 let RowFields = ["NumOpsKey"]; 133 let ColFields = ["NumOpsValue"]; 134 let KeyCol = ["2"]; 135 let ValueCols = [["3"]]; 136} 137 138//===----------------------------------------------------------------------===// 139// Instruction formats 140//===----------------------------------------------------------------------===// 141// 142// Formats are specified using operand field declarations of the form: 143// 144// bits<4> Rn : register input or output for operand n 145// bits<m> In : immediate value of width m for operand n 146// bits<4> BDn : address operand n, which has a base and a displacement 147// bits<m> XBDn : address operand n, which has an index, a base and a 148// displacement 149// bits<4> Xn : index register for address operand n 150// bits<4> Mn : mode value for operand n 151// 152// The operand numbers ("n" in the list above) follow the architecture manual. 153// Assembly operands sometimes have a different order; in particular, R3 often 154// is often written between operands 1 and 2. 155// 156//===----------------------------------------------------------------------===// 157 158class InstRI<bits<12> op, dag outs, dag ins, string asmstr, list<dag> pattern> 159 : InstSystemZ<4, outs, ins, asmstr, pattern> { 160 field bits<32> Inst; 161 field bits<32> SoftFail = 0; 162 163 bits<4> R1; 164 bits<16> I2; 165 166 let Inst{31-24} = op{11-4}; 167 let Inst{23-20} = R1; 168 let Inst{19-16} = op{3-0}; 169 let Inst{15-0} = I2; 170} 171 172class InstRIEb<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 173 : InstSystemZ<6, outs, ins, asmstr, pattern> { 174 field bits<48> Inst; 175 field bits<48> SoftFail = 0; 176 177 bits<4> R1; 178 bits<4> R2; 179 bits<4> M3; 180 bits<16> RI4; 181 182 let Inst{47-40} = op{15-8}; 183 let Inst{39-36} = R1; 184 let Inst{35-32} = R2; 185 let Inst{31-16} = RI4; 186 let Inst{15-12} = M3; 187 let Inst{11-8} = 0; 188 let Inst{7-0} = op{7-0}; 189} 190 191class InstRIEc<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 192 : InstSystemZ<6, outs, ins, asmstr, pattern> { 193 field bits<48> Inst; 194 field bits<48> SoftFail = 0; 195 196 bits<4> R1; 197 bits<8> I2; 198 bits<4> M3; 199 bits<16> RI4; 200 201 let Inst{47-40} = op{15-8}; 202 let Inst{39-36} = R1; 203 let Inst{35-32} = M3; 204 let Inst{31-16} = RI4; 205 let Inst{15-8} = I2; 206 let Inst{7-0} = op{7-0}; 207} 208 209class InstRIEd<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 210 : InstSystemZ<6, outs, ins, asmstr, pattern> { 211 field bits<48> Inst; 212 field bits<48> SoftFail = 0; 213 214 bits<4> R1; 215 bits<4> R3; 216 bits<16> I2; 217 218 let Inst{47-40} = op{15-8}; 219 let Inst{39-36} = R1; 220 let Inst{35-32} = R3; 221 let Inst{31-16} = I2; 222 let Inst{15-8} = 0; 223 let Inst{7-0} = op{7-0}; 224} 225 226class InstRIEf<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 227 : InstSystemZ<6, outs, ins, asmstr, pattern> { 228 field bits<48> Inst; 229 field bits<48> SoftFail = 0; 230 231 bits<4> R1; 232 bits<4> R2; 233 bits<8> I3; 234 bits<8> I4; 235 bits<8> I5; 236 237 let Inst{47-40} = op{15-8}; 238 let Inst{39-36} = R1; 239 let Inst{35-32} = R2; 240 let Inst{31-24} = I3; 241 let Inst{23-16} = I4; 242 let Inst{15-8} = I5; 243 let Inst{7-0} = op{7-0}; 244} 245 246class InstRIL<bits<12> op, dag outs, dag ins, string asmstr, list<dag> pattern> 247 : InstSystemZ<6, outs, ins, asmstr, pattern> { 248 field bits<48> Inst; 249 field bits<48> SoftFail = 0; 250 251 bits<4> R1; 252 bits<32> I2; 253 254 let Inst{47-40} = op{11-4}; 255 let Inst{39-36} = R1; 256 let Inst{35-32} = op{3-0}; 257 let Inst{31-0} = I2; 258} 259 260class InstRR<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> 261 : InstSystemZ<2, outs, ins, asmstr, pattern> { 262 field bits<16> Inst; 263 field bits<16> SoftFail = 0; 264 265 bits<4> R1; 266 bits<4> R2; 267 268 let Inst{15-8} = op; 269 let Inst{7-4} = R1; 270 let Inst{3-0} = R2; 271} 272 273class InstRRD<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 274 : InstSystemZ<4, outs, ins, asmstr, pattern> { 275 field bits<32> Inst; 276 field bits<32> SoftFail = 0; 277 278 bits<4> R1; 279 bits<4> R3; 280 bits<4> R2; 281 282 let Inst{31-16} = op; 283 let Inst{15-12} = R1; 284 let Inst{11-8} = 0; 285 let Inst{7-4} = R3; 286 let Inst{3-0} = R2; 287} 288 289class InstRRE<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 290 : InstSystemZ<4, outs, ins, asmstr, pattern> { 291 field bits<32> Inst; 292 field bits<32> SoftFail = 0; 293 294 bits<4> R1; 295 bits<4> R2; 296 297 let Inst{31-16} = op; 298 let Inst{15-8} = 0; 299 let Inst{7-4} = R1; 300 let Inst{3-0} = R2; 301} 302 303class InstRRF<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 304 : InstSystemZ<4, outs, ins, asmstr, pattern> { 305 field bits<32> Inst; 306 field bits<32> SoftFail = 0; 307 308 bits<4> R1; 309 bits<4> R2; 310 bits<4> R3; 311 bits<4> R4; 312 313 let Inst{31-16} = op; 314 let Inst{15-12} = R3; 315 let Inst{11-8} = R4; 316 let Inst{7-4} = R1; 317 let Inst{3-0} = R2; 318} 319 320class InstRX<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> 321 : InstSystemZ<4, outs, ins, asmstr, pattern> { 322 field bits<32> Inst; 323 field bits<32> SoftFail = 0; 324 325 bits<4> R1; 326 bits<20> XBD2; 327 328 let Inst{31-24} = op; 329 let Inst{23-20} = R1; 330 let Inst{19-0} = XBD2; 331 332 let HasIndex = 1; 333} 334 335class InstRXE<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 336 : InstSystemZ<6, outs, ins, asmstr, pattern> { 337 field bits<48> Inst; 338 field bits<48> SoftFail = 0; 339 340 bits<4> R1; 341 bits<20> XBD2; 342 343 let Inst{47-40} = op{15-8}; 344 let Inst{39-36} = R1; 345 let Inst{35-16} = XBD2; 346 let Inst{15-8} = 0; 347 let Inst{7-0} = op{7-0}; 348 349 let HasIndex = 1; 350} 351 352class InstRXF<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 353 : InstSystemZ<6, outs, ins, asmstr, pattern> { 354 field bits<48> Inst; 355 field bits<48> SoftFail = 0; 356 357 bits<4> R1; 358 bits<4> R3; 359 bits<20> XBD2; 360 361 let Inst{47-40} = op{15-8}; 362 let Inst{39-36} = R3; 363 let Inst{35-16} = XBD2; 364 let Inst{15-12} = R1; 365 let Inst{11-8} = 0; 366 let Inst{7-0} = op{7-0}; 367 368 let HasIndex = 1; 369} 370 371class InstRXY<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 372 : InstSystemZ<6, outs, ins, asmstr, pattern> { 373 field bits<48> Inst; 374 field bits<48> SoftFail = 0; 375 376 bits<4> R1; 377 bits<28> XBD2; 378 379 let Inst{47-40} = op{15-8}; 380 let Inst{39-36} = R1; 381 let Inst{35-8} = XBD2; 382 let Inst{7-0} = op{7-0}; 383 384 let Has20BitOffset = 1; 385 let HasIndex = 1; 386} 387 388class InstRS<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> 389 : InstSystemZ<4, outs, ins, asmstr, pattern> { 390 field bits<32> Inst; 391 field bits<32> SoftFail = 0; 392 393 bits<4> R1; 394 bits<4> R3; 395 bits<16> BD2; 396 397 let Inst{31-24} = op; 398 let Inst{23-20} = R1; 399 let Inst{19-16} = R3; 400 let Inst{15-0} = BD2; 401} 402 403class InstRSY<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 404 : InstSystemZ<6, outs, ins, asmstr, pattern> { 405 field bits<48> Inst; 406 field bits<48> SoftFail = 0; 407 408 bits<4> R1; 409 bits<4> R3; 410 bits<24> BD2; 411 412 let Inst{47-40} = op{15-8}; 413 let Inst{39-36} = R1; 414 let Inst{35-32} = R3; 415 let Inst{31-8} = BD2; 416 let Inst{7-0} = op{7-0}; 417 418 let Has20BitOffset = 1; 419} 420 421class InstSI<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> 422 : InstSystemZ<4, outs, ins, asmstr, pattern> { 423 field bits<32> Inst; 424 field bits<32> SoftFail = 0; 425 426 bits<16> BD1; 427 bits<8> I2; 428 429 let Inst{31-24} = op; 430 let Inst{23-16} = I2; 431 let Inst{15-0} = BD1; 432} 433 434class InstSIL<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 435 : InstSystemZ<6, outs, ins, asmstr, pattern> { 436 field bits<48> Inst; 437 field bits<48> SoftFail = 0; 438 439 bits<16> BD1; 440 bits<16> I2; 441 442 let Inst{47-32} = op; 443 let Inst{31-16} = BD1; 444 let Inst{15-0} = I2; 445} 446 447class InstSIY<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 448 : InstSystemZ<6, outs, ins, asmstr, pattern> { 449 field bits<48> Inst; 450 field bits<48> SoftFail = 0; 451 452 bits<24> BD1; 453 bits<8> I2; 454 455 let Inst{47-40} = op{15-8}; 456 let Inst{39-32} = I2; 457 let Inst{31-8} = BD1; 458 let Inst{7-0} = op{7-0}; 459 460 let Has20BitOffset = 1; 461} 462 463class InstSS<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> 464 : InstSystemZ<6, outs, ins, asmstr, pattern> { 465 field bits<48> Inst; 466 field bits<48> SoftFail = 0; 467 468 bits<24> BDL1; 469 bits<16> BD2; 470 471 let Inst{47-40} = op; 472 let Inst{39-16} = BDL1; 473 let Inst{15-0} = BD2; 474} 475 476class InstS<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> 477 : InstSystemZ<4, outs, ins, asmstr, pattern> { 478 field bits<32> Inst; 479 field bits<32> SoftFail = 0; 480 481 bits<16> BD2; 482 483 let Inst{31-16} = op; 484 let Inst{15-0} = BD2; 485} 486 487//===----------------------------------------------------------------------===// 488// Instruction definitions with semantics 489//===----------------------------------------------------------------------===// 490// 491// These classes have the form [Cond]<Category><Format>, where <Format> is one 492// of the formats defined above and where <Category> describes the inputs 493// and outputs. "Cond" is used if the instruction is conditional, 494// in which case the 4-bit condition-code mask is added as a final operand. 495// <Category> can be one of: 496// 497// Inherent: 498// One register output operand and no input operands. 499// 500// BranchUnary: 501// One register output operand, one register input operand and 502// one branch displacement. The instructions stores a modified 503// form of the source register in the destination register and 504// branches on the result. 505// 506// Store: 507// One register or immediate input operand and one address input operand. 508// The instruction stores the first operand to the address. 509// 510// This category is used for both pure and truncating stores. 511// 512// LoadMultiple: 513// One address input operand and two explicit output operands. 514// The instruction loads a range of registers from the address, 515// with the explicit operands giving the first and last register 516// to load. Other loaded registers are added as implicit definitions. 517// 518// StoreMultiple: 519// Two explicit input register operands and an address operand. 520// The instruction stores a range of registers to the address, 521// with the explicit operands giving the first and last register 522// to store. Other stored registers are added as implicit uses. 523// 524// Unary: 525// One register output operand and one input operand. 526// 527// Binary: 528// One register output operand and two input operands. 529// 530// Compare: 531// Two input operands and an implicit CC output operand. 532// 533// Ternary: 534// One register output operand and three input operands. 535// 536// LoadAndOp: 537// One output operand and two input operands, one of which is an address. 538// The instruction both reads from and writes to the address. 539// 540// CmpSwap: 541// One output operand and three input operands, one of which is an address. 542// The instruction both reads from and writes to the address. 543// 544// RotateSelect: 545// One output operand and five input operands. The first two operands 546// are registers and the other three are immediates. 547// 548// Prefetch: 549// One 4-bit immediate operand and one address operand. The immediate 550// operand is 1 for a load prefetch and 2 for a store prefetch. 551// 552// The format determines which input operands are tied to output operands, 553// and also determines the shape of any address operand. 554// 555// Multiclasses of the form <Category><Format>Pair define two instructions, 556// one with <Category><Format> and one with <Category><Format>Y. The name 557// of the first instruction has no suffix, the name of the second has 558// an extra "y". 559// 560//===----------------------------------------------------------------------===// 561 562class InherentRRE<string mnemonic, bits<16> opcode, RegisterOperand cls, 563 dag src> 564 : InstRRE<opcode, (outs cls:$R1), (ins), 565 mnemonic#"\t$R1", 566 [(set cls:$R1, src)]> { 567 let R2 = 0; 568} 569 570class BranchUnaryRI<string mnemonic, bits<12> opcode, RegisterOperand cls> 571 : InstRI<opcode, (outs cls:$R1), (ins cls:$R1src, brtarget16:$I2), 572 mnemonic##"\t$R1, $I2", []> { 573 let isBranch = 1; 574 let isTerminator = 1; 575 let Constraints = "$R1 = $R1src"; 576 let DisableEncoding = "$R1src"; 577} 578 579class LoadMultipleRSY<string mnemonic, bits<16> opcode, RegisterOperand cls> 580 : InstRSY<opcode, (outs cls:$R1, cls:$R3), (ins bdaddr20only:$BD2), 581 mnemonic#"\t$R1, $R3, $BD2", []> { 582 let mayLoad = 1; 583} 584 585class StoreRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator, 586 RegisterOperand cls> 587 : InstRIL<opcode, (outs), (ins cls:$R1, pcrel32:$I2), 588 mnemonic#"\t$R1, $I2", 589 [(operator cls:$R1, pcrel32:$I2)]> { 590 let mayStore = 1; 591 // We want PC-relative addresses to be tried ahead of BD and BDX addresses. 592 // However, BDXs have two extra operands and are therefore 6 units more 593 // complex. 594 let AddedComplexity = 7; 595} 596 597class StoreRX<string mnemonic, bits<8> opcode, SDPatternOperator operator, 598 RegisterOperand cls, bits<5> bytes, 599 AddressingMode mode = bdxaddr12only> 600 : InstRX<opcode, (outs), (ins cls:$R1, mode:$XBD2), 601 mnemonic#"\t$R1, $XBD2", 602 [(operator cls:$R1, mode:$XBD2)]> { 603 let OpKey = mnemonic ## cls; 604 let OpType = "mem"; 605 let mayStore = 1; 606 let AccessBytes = bytes; 607} 608 609class StoreRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator, 610 RegisterOperand cls, bits<5> bytes, 611 AddressingMode mode = bdxaddr20only> 612 : InstRXY<opcode, (outs), (ins cls:$R1, mode:$XBD2), 613 mnemonic#"\t$R1, $XBD2", 614 [(operator cls:$R1, mode:$XBD2)]> { 615 let OpKey = mnemonic ## cls; 616 let OpType = "mem"; 617 let mayStore = 1; 618 let AccessBytes = bytes; 619} 620 621multiclass StoreRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode, 622 SDPatternOperator operator, RegisterOperand cls, 623 bits<5> bytes> { 624 let DispKey = mnemonic ## #cls in { 625 let DispSize = "12" in 626 def "" : StoreRX<mnemonic, rxOpcode, operator, cls, bytes, bdxaddr12pair>; 627 let DispSize = "20" in 628 def Y : StoreRXY<mnemonic#"y", rxyOpcode, operator, cls, bytes, 629 bdxaddr20pair>; 630 } 631} 632 633class StoreMultipleRSY<string mnemonic, bits<16> opcode, RegisterOperand cls> 634 : InstRSY<opcode, (outs), (ins cls:$R1, cls:$R3, bdaddr20only:$BD2), 635 mnemonic#"\t$R1, $R3, $BD2", []> { 636 let mayStore = 1; 637} 638 639// StoreSI* instructions are used to store an integer to memory, but the 640// addresses are more restricted than for normal stores. If we are in the 641// situation of having to force either the address into a register or the 642// constant into a register, it's usually better to do the latter. 643// We therefore match the address in the same way as a normal store and 644// only use the StoreSI* instruction if the matched address is suitable. 645class StoreSI<string mnemonic, bits<8> opcode, SDPatternOperator operator, 646 Immediate imm> 647 : InstSI<opcode, (outs), (ins mviaddr12pair:$BD1, imm:$I2), 648 mnemonic#"\t$BD1, $I2", 649 [(operator imm:$I2, mviaddr12pair:$BD1)]> { 650 let mayStore = 1; 651} 652 653class StoreSIY<string mnemonic, bits<16> opcode, SDPatternOperator operator, 654 Immediate imm> 655 : InstSIY<opcode, (outs), (ins mviaddr20pair:$BD1, imm:$I2), 656 mnemonic#"\t$BD1, $I2", 657 [(operator imm:$I2, mviaddr20pair:$BD1)]> { 658 let mayStore = 1; 659} 660 661class StoreSIL<string mnemonic, bits<16> opcode, SDPatternOperator operator, 662 Immediate imm> 663 : InstSIL<opcode, (outs), (ins mviaddr12pair:$BD1, imm:$I2), 664 mnemonic#"\t$BD1, $I2", 665 [(operator imm:$I2, mviaddr12pair:$BD1)]> { 666 let mayStore = 1; 667} 668 669multiclass StoreSIPair<string mnemonic, bits<8> siOpcode, bits<16> siyOpcode, 670 SDPatternOperator operator, Immediate imm> { 671 let DispKey = mnemonic in { 672 let DispSize = "12" in 673 def "" : StoreSI<mnemonic, siOpcode, operator, imm>; 674 let DispSize = "20" in 675 def Y : StoreSIY<mnemonic#"y", siyOpcode, operator, imm>; 676 } 677} 678 679class CondStoreRSY<string mnemonic, bits<16> opcode, 680 RegisterOperand cls, bits<5> bytes, 681 AddressingMode mode = bdaddr20only> 682 : InstRSY<opcode, (outs), (ins cls:$R1, mode:$BD2, cond4:$valid, cond4:$R3), 683 mnemonic#"$R3\t$R1, $BD2", []>, 684 Requires<[FeatureLoadStoreOnCond]> { 685 let mayStore = 1; 686 let AccessBytes = bytes; 687 let CCMaskLast = 1; 688} 689 690// Like CondStoreRSY, but used for the raw assembly form. The condition-code 691// mask is the third operand rather than being part of the mnemonic. 692class AsmCondStoreRSY<string mnemonic, bits<16> opcode, 693 RegisterOperand cls, bits<5> bytes, 694 AddressingMode mode = bdaddr20only> 695 : InstRSY<opcode, (outs), (ins cls:$R1, mode:$BD2, imm32zx4:$R3), 696 mnemonic#"\t$R1, $BD2, $R3", []>, 697 Requires<[FeatureLoadStoreOnCond]> { 698 let mayStore = 1; 699 let AccessBytes = bytes; 700} 701 702// Like CondStoreRSY, but with a fixed CC mask. 703class FixedCondStoreRSY<string mnemonic, bits<16> opcode, 704 RegisterOperand cls, bits<4> ccmask, bits<5> bytes, 705 AddressingMode mode = bdaddr20only> 706 : InstRSY<opcode, (outs), (ins cls:$R1, mode:$BD2), 707 mnemonic#"\t$R1, $BD2", []>, 708 Requires<[FeatureLoadStoreOnCond]> { 709 let mayStore = 1; 710 let AccessBytes = bytes; 711 let R3 = ccmask; 712} 713 714class UnaryRR<string mnemonic, bits<8> opcode, SDPatternOperator operator, 715 RegisterOperand cls1, RegisterOperand cls2> 716 : InstRR<opcode, (outs cls1:$R1), (ins cls2:$R2), 717 mnemonic#"r\t$R1, $R2", 718 [(set cls1:$R1, (operator cls2:$R2))]> { 719 let OpKey = mnemonic ## cls1; 720 let OpType = "reg"; 721} 722 723class UnaryRRE<string mnemonic, bits<16> opcode, SDPatternOperator operator, 724 RegisterOperand cls1, RegisterOperand cls2> 725 : InstRRE<opcode, (outs cls1:$R1), (ins cls2:$R2), 726 mnemonic#"r\t$R1, $R2", 727 [(set cls1:$R1, (operator cls2:$R2))]> { 728 let OpKey = mnemonic ## cls1; 729 let OpType = "reg"; 730} 731 732class UnaryRRF<string mnemonic, bits<16> opcode, RegisterOperand cls1, 733 RegisterOperand cls2> 734 : InstRRF<opcode, (outs cls1:$R1), (ins imm32zx4:$R3, cls2:$R2), 735 mnemonic#"r\t$R1, $R3, $R2", []> { 736 let OpKey = mnemonic ## cls1; 737 let OpType = "reg"; 738 let R4 = 0; 739} 740 741class UnaryRRF4<string mnemonic, bits<16> opcode, RegisterOperand cls1, 742 RegisterOperand cls2> 743 : InstRRF<opcode, (outs cls1:$R1), (ins imm32zx4:$R3, cls2:$R2, imm32zx4:$R4), 744 mnemonic#"\t$R1, $R3, $R2, $R4", []>; 745 746// These instructions are generated by if conversion. The old value of R1 747// is added as an implicit use. 748class CondUnaryRRF<string mnemonic, bits<16> opcode, RegisterOperand cls1, 749 RegisterOperand cls2> 750 : InstRRF<opcode, (outs cls1:$R1), (ins cls2:$R2, cond4:$valid, cond4:$R3), 751 mnemonic#"r$R3\t$R1, $R2", []>, 752 Requires<[FeatureLoadStoreOnCond]> { 753 let CCMaskLast = 1; 754 let R4 = 0; 755} 756 757// Like CondUnaryRRF, but used for the raw assembly form. The condition-code 758// mask is the third operand rather than being part of the mnemonic. 759class AsmCondUnaryRRF<string mnemonic, bits<16> opcode, RegisterOperand cls1, 760 RegisterOperand cls2> 761 : InstRRF<opcode, (outs cls1:$R1), (ins cls1:$R1src, cls2:$R2, imm32zx4:$R3), 762 mnemonic#"r\t$R1, $R2, $R3", []>, 763 Requires<[FeatureLoadStoreOnCond]> { 764 let Constraints = "$R1 = $R1src"; 765 let DisableEncoding = "$R1src"; 766 let R4 = 0; 767} 768 769// Like CondUnaryRRF, but with a fixed CC mask. 770class FixedCondUnaryRRF<string mnemonic, bits<16> opcode, RegisterOperand cls1, 771 RegisterOperand cls2, bits<4> ccmask> 772 : InstRRF<opcode, (outs cls1:$R1), (ins cls1:$R1src, cls2:$R2), 773 mnemonic#"\t$R1, $R2", []>, 774 Requires<[FeatureLoadStoreOnCond]> { 775 let Constraints = "$R1 = $R1src"; 776 let DisableEncoding = "$R1src"; 777 let R3 = ccmask; 778 let R4 = 0; 779} 780 781class UnaryRI<string mnemonic, bits<12> opcode, SDPatternOperator operator, 782 RegisterOperand cls, Immediate imm> 783 : InstRI<opcode, (outs cls:$R1), (ins imm:$I2), 784 mnemonic#"\t$R1, $I2", 785 [(set cls:$R1, (operator imm:$I2))]>; 786 787class UnaryRIL<string mnemonic, bits<12> opcode, SDPatternOperator operator, 788 RegisterOperand cls, Immediate imm> 789 : InstRIL<opcode, (outs cls:$R1), (ins imm:$I2), 790 mnemonic#"\t$R1, $I2", 791 [(set cls:$R1, (operator imm:$I2))]>; 792 793class UnaryRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator, 794 RegisterOperand cls> 795 : InstRIL<opcode, (outs cls:$R1), (ins pcrel32:$I2), 796 mnemonic#"\t$R1, $I2", 797 [(set cls:$R1, (operator pcrel32:$I2))]> { 798 let mayLoad = 1; 799 // We want PC-relative addresses to be tried ahead of BD and BDX addresses. 800 // However, BDXs have two extra operands and are therefore 6 units more 801 // complex. 802 let AddedComplexity = 7; 803} 804 805class CondUnaryRSY<string mnemonic, bits<16> opcode, 806 SDPatternOperator operator, RegisterOperand cls, 807 bits<5> bytes, AddressingMode mode = bdaddr20only> 808 : InstRSY<opcode, (outs cls:$R1), 809 (ins cls:$R1src, mode:$BD2, cond4:$valid, cond4:$R3), 810 mnemonic#"$R3\t$R1, $BD2", 811 [(set cls:$R1, 812 (z_select_ccmask (load bdaddr20only:$BD2), cls:$R1src, 813 cond4:$valid, cond4:$R3))]>, 814 Requires<[FeatureLoadStoreOnCond]> { 815 let Constraints = "$R1 = $R1src"; 816 let DisableEncoding = "$R1src"; 817 let mayLoad = 1; 818 let AccessBytes = bytes; 819 let CCMaskLast = 1; 820} 821 822// Like CondUnaryRSY, but used for the raw assembly form. The condition-code 823// mask is the third operand rather than being part of the mnemonic. 824class AsmCondUnaryRSY<string mnemonic, bits<16> opcode, 825 RegisterOperand cls, bits<5> bytes, 826 AddressingMode mode = bdaddr20only> 827 : InstRSY<opcode, (outs cls:$R1), (ins cls:$R1src, mode:$BD2, imm32zx4:$R3), 828 mnemonic#"\t$R1, $BD2, $R3", []>, 829 Requires<[FeatureLoadStoreOnCond]> { 830 let mayLoad = 1; 831 let AccessBytes = bytes; 832 let Constraints = "$R1 = $R1src"; 833 let DisableEncoding = "$R1src"; 834} 835 836// Like CondUnaryRSY, but with a fixed CC mask. 837class FixedCondUnaryRSY<string mnemonic, bits<16> opcode, 838 RegisterOperand cls, bits<4> ccmask, bits<5> bytes, 839 AddressingMode mode = bdaddr20only> 840 : InstRSY<opcode, (outs cls:$R1), (ins cls:$R1src, mode:$BD2), 841 mnemonic#"\t$R1, $BD2", []>, 842 Requires<[FeatureLoadStoreOnCond]> { 843 let Constraints = "$R1 = $R1src"; 844 let DisableEncoding = "$R1src"; 845 let R3 = ccmask; 846 let mayLoad = 1; 847 let AccessBytes = bytes; 848} 849 850class UnaryRX<string mnemonic, bits<8> opcode, SDPatternOperator operator, 851 RegisterOperand cls, bits<5> bytes, 852 AddressingMode mode = bdxaddr12only> 853 : InstRX<opcode, (outs cls:$R1), (ins mode:$XBD2), 854 mnemonic#"\t$R1, $XBD2", 855 [(set cls:$R1, (operator mode:$XBD2))]> { 856 let OpKey = mnemonic ## cls; 857 let OpType = "mem"; 858 let mayLoad = 1; 859 let AccessBytes = bytes; 860} 861 862class UnaryRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator, 863 RegisterOperand cls, bits<5> bytes> 864 : InstRXE<opcode, (outs cls:$R1), (ins bdxaddr12only:$XBD2), 865 mnemonic#"\t$R1, $XBD2", 866 [(set cls:$R1, (operator bdxaddr12only:$XBD2))]> { 867 let OpKey = mnemonic ## cls; 868 let OpType = "mem"; 869 let mayLoad = 1; 870 let AccessBytes = bytes; 871} 872 873class UnaryRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator, 874 RegisterOperand cls, bits<5> bytes, 875 AddressingMode mode = bdxaddr20only> 876 : InstRXY<opcode, (outs cls:$R1), (ins mode:$XBD2), 877 mnemonic#"\t$R1, $XBD2", 878 [(set cls:$R1, (operator mode:$XBD2))]> { 879 let OpKey = mnemonic ## cls; 880 let OpType = "mem"; 881 let mayLoad = 1; 882 let AccessBytes = bytes; 883} 884 885multiclass UnaryRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode, 886 SDPatternOperator operator, RegisterOperand cls, 887 bits<5> bytes> { 888 let DispKey = mnemonic ## #cls in { 889 let DispSize = "12" in 890 def "" : UnaryRX<mnemonic, rxOpcode, operator, cls, bytes, bdxaddr12pair>; 891 let DispSize = "20" in 892 def Y : UnaryRXY<mnemonic#"y", rxyOpcode, operator, cls, bytes, 893 bdxaddr20pair>; 894 } 895} 896 897class BinaryRR<string mnemonic, bits<8> opcode, SDPatternOperator operator, 898 RegisterOperand cls1, RegisterOperand cls2> 899 : InstRR<opcode, (outs cls1:$R1), (ins cls1:$R1src, cls2:$R2), 900 mnemonic#"r\t$R1, $R2", 901 [(set cls1:$R1, (operator cls1:$R1src, cls2:$R2))]> { 902 let OpKey = mnemonic ## cls1; 903 let OpType = "reg"; 904 let Constraints = "$R1 = $R1src"; 905 let DisableEncoding = "$R1src"; 906} 907 908class BinaryRRE<string mnemonic, bits<16> opcode, SDPatternOperator operator, 909 RegisterOperand cls1, RegisterOperand cls2> 910 : InstRRE<opcode, (outs cls1:$R1), (ins cls1:$R1src, cls2:$R2), 911 mnemonic#"r\t$R1, $R2", 912 [(set cls1:$R1, (operator cls1:$R1src, cls2:$R2))]> { 913 let OpKey = mnemonic ## cls1; 914 let OpType = "reg"; 915 let Constraints = "$R1 = $R1src"; 916 let DisableEncoding = "$R1src"; 917} 918 919class BinaryRRF<string mnemonic, bits<16> opcode, SDPatternOperator operator, 920 RegisterOperand cls1, RegisterOperand cls2> 921 : InstRRF<opcode, (outs cls1:$R1), (ins cls1:$R3, cls2:$R2), 922 mnemonic#"r\t$R1, $R3, $R2", 923 [(set cls1:$R1, (operator cls1:$R3, cls2:$R2))]> { 924 let OpKey = mnemonic ## cls1; 925 let OpType = "reg"; 926 let R4 = 0; 927} 928 929class BinaryRRFK<string mnemonic, bits<16> opcode, SDPatternOperator operator, 930 RegisterOperand cls1, RegisterOperand cls2> 931 : InstRRF<opcode, (outs cls1:$R1), (ins cls1:$R2, cls2:$R3), 932 mnemonic#"rk\t$R1, $R2, $R3", 933 [(set cls1:$R1, (operator cls1:$R2, cls2:$R3))]> { 934 let R4 = 0; 935} 936 937multiclass BinaryRRAndK<string mnemonic, bits<8> opcode1, bits<16> opcode2, 938 SDPatternOperator operator, RegisterOperand cls1, 939 RegisterOperand cls2> { 940 let NumOpsKey = mnemonic in { 941 let NumOpsValue = "3" in 942 def K : BinaryRRFK<mnemonic, opcode2, null_frag, cls1, cls2>, 943 Requires<[FeatureDistinctOps]>; 944 let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in 945 def "" : BinaryRR<mnemonic, opcode1, operator, cls1, cls2>; 946 } 947} 948 949multiclass BinaryRREAndK<string mnemonic, bits<16> opcode1, bits<16> opcode2, 950 SDPatternOperator operator, RegisterOperand cls1, 951 RegisterOperand cls2> { 952 let NumOpsKey = mnemonic in { 953 let NumOpsValue = "3" in 954 def K : BinaryRRFK<mnemonic, opcode2, null_frag, cls1, cls2>, 955 Requires<[FeatureDistinctOps]>; 956 let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in 957 def "" : BinaryRRE<mnemonic, opcode1, operator, cls1, cls2>; 958 } 959} 960 961class BinaryRI<string mnemonic, bits<12> opcode, SDPatternOperator operator, 962 RegisterOperand cls, Immediate imm> 963 : InstRI<opcode, (outs cls:$R1), (ins cls:$R1src, imm:$I2), 964 mnemonic#"\t$R1, $I2", 965 [(set cls:$R1, (operator cls:$R1src, imm:$I2))]> { 966 let Constraints = "$R1 = $R1src"; 967 let DisableEncoding = "$R1src"; 968} 969 970class BinaryRIE<string mnemonic, bits<16> opcode, SDPatternOperator operator, 971 RegisterOperand cls, Immediate imm> 972 : InstRIEd<opcode, (outs cls:$R1), (ins cls:$R3, imm:$I2), 973 mnemonic#"\t$R1, $R3, $I2", 974 [(set cls:$R1, (operator cls:$R3, imm:$I2))]>; 975 976multiclass BinaryRIAndK<string mnemonic, bits<12> opcode1, bits<16> opcode2, 977 SDPatternOperator operator, RegisterOperand cls, 978 Immediate imm> { 979 let NumOpsKey = mnemonic in { 980 let NumOpsValue = "3" in 981 def K : BinaryRIE<mnemonic##"k", opcode2, null_frag, cls, imm>, 982 Requires<[FeatureDistinctOps]>; 983 let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in 984 def "" : BinaryRI<mnemonic, opcode1, operator, cls, imm>; 985 } 986} 987 988class BinaryRIL<string mnemonic, bits<12> opcode, SDPatternOperator operator, 989 RegisterOperand cls, Immediate imm> 990 : InstRIL<opcode, (outs cls:$R1), (ins cls:$R1src, imm:$I2), 991 mnemonic#"\t$R1, $I2", 992 [(set cls:$R1, (operator cls:$R1src, imm:$I2))]> { 993 let Constraints = "$R1 = $R1src"; 994 let DisableEncoding = "$R1src"; 995} 996 997class BinaryRS<string mnemonic, bits<8> opcode, SDPatternOperator operator, 998 RegisterOperand cls> 999 : InstRS<opcode, (outs cls:$R1), (ins cls:$R1src, shift12only:$BD2), 1000 mnemonic#"\t$R1, $BD2", 1001 [(set cls:$R1, (operator cls:$R1src, shift12only:$BD2))]> { 1002 let R3 = 0; 1003 let Constraints = "$R1 = $R1src"; 1004 let DisableEncoding = "$R1src"; 1005} 1006 1007class BinaryRSY<string mnemonic, bits<16> opcode, SDPatternOperator operator, 1008 RegisterOperand cls> 1009 : InstRSY<opcode, (outs cls:$R1), (ins cls:$R3, shift20only:$BD2), 1010 mnemonic#"\t$R1, $R3, $BD2", 1011 [(set cls:$R1, (operator cls:$R3, shift20only:$BD2))]>; 1012 1013multiclass BinaryRSAndK<string mnemonic, bits<8> opcode1, bits<16> opcode2, 1014 SDPatternOperator operator, RegisterOperand cls> { 1015 let NumOpsKey = mnemonic in { 1016 let NumOpsValue = "3" in 1017 def K : BinaryRSY<mnemonic##"k", opcode2, null_frag, cls>, 1018 Requires<[FeatureDistinctOps]>; 1019 let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in 1020 def "" : BinaryRS<mnemonic, opcode1, operator, cls>; 1021 } 1022} 1023 1024class BinaryRX<string mnemonic, bits<8> opcode, SDPatternOperator operator, 1025 RegisterOperand cls, SDPatternOperator load, bits<5> bytes, 1026 AddressingMode mode = bdxaddr12only> 1027 : InstRX<opcode, (outs cls:$R1), (ins cls:$R1src, mode:$XBD2), 1028 mnemonic#"\t$R1, $XBD2", 1029 [(set cls:$R1, (operator cls:$R1src, (load mode:$XBD2)))]> { 1030 let OpKey = mnemonic ## cls; 1031 let OpType = "mem"; 1032 let Constraints = "$R1 = $R1src"; 1033 let DisableEncoding = "$R1src"; 1034 let mayLoad = 1; 1035 let AccessBytes = bytes; 1036} 1037 1038class BinaryRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator, 1039 RegisterOperand cls, SDPatternOperator load, bits<5> bytes> 1040 : InstRXE<opcode, (outs cls:$R1), (ins cls:$R1src, bdxaddr12only:$XBD2), 1041 mnemonic#"\t$R1, $XBD2", 1042 [(set cls:$R1, (operator cls:$R1src, 1043 (load bdxaddr12only:$XBD2)))]> { 1044 let OpKey = mnemonic ## cls; 1045 let OpType = "mem"; 1046 let Constraints = "$R1 = $R1src"; 1047 let DisableEncoding = "$R1src"; 1048 let mayLoad = 1; 1049 let AccessBytes = bytes; 1050} 1051 1052class BinaryRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator, 1053 RegisterOperand cls, SDPatternOperator load, bits<5> bytes, 1054 AddressingMode mode = bdxaddr20only> 1055 : InstRXY<opcode, (outs cls:$R1), (ins cls:$R1src, mode:$XBD2), 1056 mnemonic#"\t$R1, $XBD2", 1057 [(set cls:$R1, (operator cls:$R1src, (load mode:$XBD2)))]> { 1058 let OpKey = mnemonic ## cls; 1059 let OpType = "mem"; 1060 let Constraints = "$R1 = $R1src"; 1061 let DisableEncoding = "$R1src"; 1062 let mayLoad = 1; 1063 let AccessBytes = bytes; 1064} 1065 1066multiclass BinaryRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode, 1067 SDPatternOperator operator, RegisterOperand cls, 1068 SDPatternOperator load, bits<5> bytes> { 1069 let DispKey = mnemonic ## #cls in { 1070 let DispSize = "12" in 1071 def "" : BinaryRX<mnemonic, rxOpcode, operator, cls, load, bytes, 1072 bdxaddr12pair>; 1073 let DispSize = "20" in 1074 def Y : BinaryRXY<mnemonic#"y", rxyOpcode, operator, cls, load, bytes, 1075 bdxaddr20pair>; 1076 } 1077} 1078 1079class BinarySI<string mnemonic, bits<8> opcode, SDPatternOperator operator, 1080 Operand imm, AddressingMode mode = bdaddr12only> 1081 : InstSI<opcode, (outs), (ins mode:$BD1, imm:$I2), 1082 mnemonic#"\t$BD1, $I2", 1083 [(store (operator (load mode:$BD1), imm:$I2), mode:$BD1)]> { 1084 let mayLoad = 1; 1085 let mayStore = 1; 1086} 1087 1088class BinarySIY<string mnemonic, bits<16> opcode, SDPatternOperator operator, 1089 Operand imm, AddressingMode mode = bdaddr20only> 1090 : InstSIY<opcode, (outs), (ins mode:$BD1, imm:$I2), 1091 mnemonic#"\t$BD1, $I2", 1092 [(store (operator (load mode:$BD1), imm:$I2), mode:$BD1)]> { 1093 let mayLoad = 1; 1094 let mayStore = 1; 1095} 1096 1097multiclass BinarySIPair<string mnemonic, bits<8> siOpcode, 1098 bits<16> siyOpcode, SDPatternOperator operator, 1099 Operand imm> { 1100 let DispKey = mnemonic ## #cls in { 1101 let DispSize = "12" in 1102 def "" : BinarySI<mnemonic, siOpcode, operator, imm, bdaddr12pair>; 1103 let DispSize = "20" in 1104 def Y : BinarySIY<mnemonic#"y", siyOpcode, operator, imm, bdaddr20pair>; 1105 } 1106} 1107 1108class CompareRR<string mnemonic, bits<8> opcode, SDPatternOperator operator, 1109 RegisterOperand cls1, RegisterOperand cls2> 1110 : InstRR<opcode, (outs), (ins cls1:$R1, cls2:$R2), 1111 mnemonic#"r\t$R1, $R2", 1112 [(operator cls1:$R1, cls2:$R2)]> { 1113 let OpKey = mnemonic ## cls1; 1114 let OpType = "reg"; 1115 let isCompare = 1; 1116} 1117 1118class CompareRRE<string mnemonic, bits<16> opcode, SDPatternOperator operator, 1119 RegisterOperand cls1, RegisterOperand cls2> 1120 : InstRRE<opcode, (outs), (ins cls1:$R1, cls2:$R2), 1121 mnemonic#"r\t$R1, $R2", 1122 [(operator cls1:$R1, cls2:$R2)]> { 1123 let OpKey = mnemonic ## cls1; 1124 let OpType = "reg"; 1125 let isCompare = 1; 1126} 1127 1128class CompareRI<string mnemonic, bits<12> opcode, SDPatternOperator operator, 1129 RegisterOperand cls, Immediate imm> 1130 : InstRI<opcode, (outs), (ins cls:$R1, imm:$I2), 1131 mnemonic#"\t$R1, $I2", 1132 [(operator cls:$R1, imm:$I2)]> { 1133 let isCompare = 1; 1134} 1135 1136class CompareRIL<string mnemonic, bits<12> opcode, SDPatternOperator operator, 1137 RegisterOperand cls, Immediate imm> 1138 : InstRIL<opcode, (outs), (ins cls:$R1, imm:$I2), 1139 mnemonic#"\t$R1, $I2", 1140 [(operator cls:$R1, imm:$I2)]> { 1141 let isCompare = 1; 1142} 1143 1144class CompareRILPC<string mnemonic, bits<12> opcode, SDPatternOperator operator, 1145 RegisterOperand cls, SDPatternOperator load> 1146 : InstRIL<opcode, (outs), (ins cls:$R1, pcrel32:$I2), 1147 mnemonic#"\t$R1, $I2", 1148 [(operator cls:$R1, (load pcrel32:$I2))]> { 1149 let isCompare = 1; 1150 let mayLoad = 1; 1151 // We want PC-relative addresses to be tried ahead of BD and BDX addresses. 1152 // However, BDXs have two extra operands and are therefore 6 units more 1153 // complex. 1154 let AddedComplexity = 7; 1155} 1156 1157class CompareRX<string mnemonic, bits<8> opcode, SDPatternOperator operator, 1158 RegisterOperand cls, SDPatternOperator load, bits<5> bytes, 1159 AddressingMode mode = bdxaddr12only> 1160 : InstRX<opcode, (outs), (ins cls:$R1, mode:$XBD2), 1161 mnemonic#"\t$R1, $XBD2", 1162 [(operator cls:$R1, (load mode:$XBD2))]> { 1163 let OpKey = mnemonic ## cls; 1164 let OpType = "mem"; 1165 let isCompare = 1; 1166 let mayLoad = 1; 1167 let AccessBytes = bytes; 1168} 1169 1170class CompareRXE<string mnemonic, bits<16> opcode, SDPatternOperator operator, 1171 RegisterOperand cls, SDPatternOperator load, bits<5> bytes> 1172 : InstRXE<opcode, (outs), (ins cls:$R1, bdxaddr12only:$XBD2), 1173 mnemonic#"\t$R1, $XBD2", 1174 [(operator cls:$R1, (load bdxaddr12only:$XBD2))]> { 1175 let OpKey = mnemonic ## cls; 1176 let OpType = "mem"; 1177 let isCompare = 1; 1178 let mayLoad = 1; 1179 let AccessBytes = bytes; 1180} 1181 1182class CompareRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator, 1183 RegisterOperand cls, SDPatternOperator load, bits<5> bytes, 1184 AddressingMode mode = bdxaddr20only> 1185 : InstRXY<opcode, (outs), (ins cls:$R1, mode:$XBD2), 1186 mnemonic#"\t$R1, $XBD2", 1187 [(operator cls:$R1, (load mode:$XBD2))]> { 1188 let OpKey = mnemonic ## cls; 1189 let OpType = "mem"; 1190 let isCompare = 1; 1191 let mayLoad = 1; 1192 let AccessBytes = bytes; 1193} 1194 1195multiclass CompareRXPair<string mnemonic, bits<8> rxOpcode, bits<16> rxyOpcode, 1196 SDPatternOperator operator, RegisterOperand cls, 1197 SDPatternOperator load, bits<5> bytes> { 1198 let DispKey = mnemonic ## #cls in { 1199 let DispSize = "12" in 1200 def "" : CompareRX<mnemonic, rxOpcode, operator, cls, 1201 load, bytes, bdxaddr12pair>; 1202 let DispSize = "20" in 1203 def Y : CompareRXY<mnemonic#"y", rxyOpcode, operator, cls, 1204 load, bytes, bdxaddr20pair>; 1205 } 1206} 1207 1208class CompareSI<string mnemonic, bits<8> opcode, SDPatternOperator operator, 1209 SDPatternOperator load, Immediate imm, 1210 AddressingMode mode = bdaddr12only> 1211 : InstSI<opcode, (outs), (ins mode:$BD1, imm:$I2), 1212 mnemonic#"\t$BD1, $I2", 1213 [(operator (load mode:$BD1), imm:$I2)]> { 1214 let isCompare = 1; 1215 let mayLoad = 1; 1216} 1217 1218class CompareSIL<string mnemonic, bits<16> opcode, SDPatternOperator operator, 1219 SDPatternOperator load, Immediate imm> 1220 : InstSIL<opcode, (outs), (ins bdaddr12only:$BD1, imm:$I2), 1221 mnemonic#"\t$BD1, $I2", 1222 [(operator (load bdaddr12only:$BD1), imm:$I2)]> { 1223 let isCompare = 1; 1224 let mayLoad = 1; 1225} 1226 1227class CompareSIY<string mnemonic, bits<16> opcode, SDPatternOperator operator, 1228 SDPatternOperator load, Immediate imm, 1229 AddressingMode mode = bdaddr20only> 1230 : InstSIY<opcode, (outs), (ins mode:$BD1, imm:$I2), 1231 mnemonic#"\t$BD1, $I2", 1232 [(operator (load mode:$BD1), imm:$I2)]> { 1233 let isCompare = 1; 1234 let mayLoad = 1; 1235} 1236 1237multiclass CompareSIPair<string mnemonic, bits<8> siOpcode, bits<16> siyOpcode, 1238 SDPatternOperator operator, SDPatternOperator load, 1239 Immediate imm> { 1240 let DispKey = mnemonic in { 1241 let DispSize = "12" in 1242 def "" : CompareSI<mnemonic, siOpcode, operator, load, imm, bdaddr12pair>; 1243 let DispSize = "20" in 1244 def Y : CompareSIY<mnemonic#"y", siyOpcode, operator, load, imm, 1245 bdaddr20pair>; 1246 } 1247} 1248 1249class TernaryRRD<string mnemonic, bits<16> opcode, 1250 SDPatternOperator operator, RegisterOperand cls> 1251 : InstRRD<opcode, (outs cls:$R1), (ins cls:$R1src, cls:$R3, cls:$R2), 1252 mnemonic#"r\t$R1, $R3, $R2", 1253 [(set cls:$R1, (operator cls:$R1src, cls:$R3, cls:$R2))]> { 1254 let OpKey = mnemonic ## cls; 1255 let OpType = "reg"; 1256 let Constraints = "$R1 = $R1src"; 1257 let DisableEncoding = "$R1src"; 1258} 1259 1260class TernaryRXF<string mnemonic, bits<16> opcode, SDPatternOperator operator, 1261 RegisterOperand cls, SDPatternOperator load, bits<5> bytes> 1262 : InstRXF<opcode, (outs cls:$R1), 1263 (ins cls:$R1src, cls:$R3, bdxaddr12only:$XBD2), 1264 mnemonic#"\t$R1, $R3, $XBD2", 1265 [(set cls:$R1, (operator cls:$R1src, cls:$R3, 1266 (load bdxaddr12only:$XBD2)))]> { 1267 let OpKey = mnemonic ## cls; 1268 let OpType = "mem"; 1269 let Constraints = "$R1 = $R1src"; 1270 let DisableEncoding = "$R1src"; 1271 let mayLoad = 1; 1272 let AccessBytes = bytes; 1273} 1274 1275class LoadAndOpRSY<string mnemonic, bits<16> opcode, SDPatternOperator operator, 1276 RegisterOperand cls, AddressingMode mode = bdaddr20only> 1277 : InstRSY<opcode, (outs cls:$R1), (ins cls:$R3, mode:$BD2), 1278 mnemonic#"\t$R1, $R3, $BD2", 1279 [(set cls:$R1, (operator mode:$BD2, cls:$R3))]> { 1280 let mayLoad = 1; 1281 let mayStore = 1; 1282} 1283 1284class CmpSwapRS<string mnemonic, bits<8> opcode, SDPatternOperator operator, 1285 RegisterOperand cls, AddressingMode mode = bdaddr12only> 1286 : InstRS<opcode, (outs cls:$R1), (ins cls:$R1src, cls:$R3, mode:$BD2), 1287 mnemonic#"\t$R1, $R3, $BD2", 1288 [(set cls:$R1, (operator mode:$BD2, cls:$R1src, cls:$R3))]> { 1289 let Constraints = "$R1 = $R1src"; 1290 let DisableEncoding = "$R1src"; 1291 let mayLoad = 1; 1292 let mayStore = 1; 1293} 1294 1295class CmpSwapRSY<string mnemonic, bits<16> opcode, SDPatternOperator operator, 1296 RegisterOperand cls, AddressingMode mode = bdaddr20only> 1297 : InstRSY<opcode, (outs cls:$R1), (ins cls:$R1src, cls:$R3, mode:$BD2), 1298 mnemonic#"\t$R1, $R3, $BD2", 1299 [(set cls:$R1, (operator mode:$BD2, cls:$R1src, cls:$R3))]> { 1300 let Constraints = "$R1 = $R1src"; 1301 let DisableEncoding = "$R1src"; 1302 let mayLoad = 1; 1303 let mayStore = 1; 1304} 1305 1306multiclass CmpSwapRSPair<string mnemonic, bits<8> rsOpcode, bits<16> rsyOpcode, 1307 SDPatternOperator operator, RegisterOperand cls> { 1308 let DispKey = mnemonic ## #cls in { 1309 let DispSize = "12" in 1310 def "" : CmpSwapRS<mnemonic, rsOpcode, operator, cls, bdaddr12pair>; 1311 let DispSize = "20" in 1312 def Y : CmpSwapRSY<mnemonic#"y", rsyOpcode, operator, cls, bdaddr20pair>; 1313 } 1314} 1315 1316class RotateSelectRIEf<string mnemonic, bits<16> opcode, RegisterOperand cls1, 1317 RegisterOperand cls2> 1318 : InstRIEf<opcode, (outs cls1:$R1), 1319 (ins cls1:$R1src, cls2:$R2, imm32zx8:$I3, imm32zx8:$I4, 1320 imm32zx6:$I5), 1321 mnemonic#"\t$R1, $R2, $I3, $I4, $I5", []> { 1322 let Constraints = "$R1 = $R1src"; 1323 let DisableEncoding = "$R1src"; 1324} 1325 1326class PrefetchRXY<string mnemonic, bits<16> opcode, SDPatternOperator operator> 1327 : InstRXY<opcode, (outs), (ins imm32zx4:$R1, bdxaddr20only:$XBD2), 1328 mnemonic##"\t$R1, $XBD2", 1329 [(operator imm32zx4:$R1, bdxaddr20only:$XBD2)]>; 1330 1331class PrefetchRILPC<string mnemonic, bits<12> opcode, 1332 SDPatternOperator operator> 1333 : InstRIL<opcode, (outs), (ins imm32zx4:$R1, pcrel32:$I2), 1334 mnemonic##"\t$R1, $I2", 1335 [(operator imm32zx4:$R1, pcrel32:$I2)]> { 1336 // We want PC-relative addresses to be tried ahead of BD and BDX addresses. 1337 // However, BDXs have two extra operands and are therefore 6 units more 1338 // complex. 1339 let AddedComplexity = 7; 1340} 1341 1342// A floating-point load-and test operation. Create both a normal unary 1343// operation and one that acts as a comparison against zero. 1344multiclass LoadAndTestRRE<string mnemonic, bits<16> opcode, 1345 RegisterOperand cls> { 1346 def "" : UnaryRRE<mnemonic, opcode, null_frag, cls, cls>; 1347 let isCodeGenOnly = 1 in 1348 def Compare : CompareRRE<mnemonic, opcode, null_frag, cls, cls>; 1349} 1350 1351//===----------------------------------------------------------------------===// 1352// Pseudo instructions 1353//===----------------------------------------------------------------------===// 1354// 1355// Convenience instructions that get lowered to real instructions 1356// by either SystemZTargetLowering::EmitInstrWithCustomInserter() 1357// or SystemZInstrInfo::expandPostRAPseudo(). 1358// 1359//===----------------------------------------------------------------------===// 1360 1361class Pseudo<dag outs, dag ins, list<dag> pattern> 1362 : InstSystemZ<0, outs, ins, "", pattern> { 1363 let isPseudo = 1; 1364 let isCodeGenOnly = 1; 1365} 1366 1367// Like UnaryRI, but expanded after RA depending on the choice of register. 1368class UnaryRIPseudo<SDPatternOperator operator, RegisterOperand cls, 1369 Immediate imm> 1370 : Pseudo<(outs cls:$R1), (ins imm:$I2), 1371 [(set cls:$R1, (operator imm:$I2))]>; 1372 1373// Like UnaryRXY, but expanded after RA depending on the choice of register. 1374class UnaryRXYPseudo<string key, SDPatternOperator operator, 1375 RegisterOperand cls, bits<5> bytes, 1376 AddressingMode mode = bdxaddr20only> 1377 : Pseudo<(outs cls:$R1), (ins mode:$XBD2), 1378 [(set cls:$R1, (operator mode:$XBD2))]> { 1379 let OpKey = key ## cls; 1380 let OpType = "mem"; 1381 let mayLoad = 1; 1382 let Has20BitOffset = 1; 1383 let HasIndex = 1; 1384 let AccessBytes = bytes; 1385} 1386 1387// Like UnaryRR, but expanded after RA depending on the choice of registers. 1388class UnaryRRPseudo<string key, SDPatternOperator operator, 1389 RegisterOperand cls1, RegisterOperand cls2> 1390 : Pseudo<(outs cls1:$R1), (ins cls2:$R2), 1391 [(set cls1:$R1, (operator cls2:$R2))]> { 1392 let OpKey = key ## cls1; 1393 let OpType = "reg"; 1394} 1395 1396// Like BinaryRI, but expanded after RA depending on the choice of register. 1397class BinaryRIPseudo<SDPatternOperator operator, RegisterOperand cls, 1398 Immediate imm> 1399 : Pseudo<(outs cls:$R1), (ins cls:$R1src, imm:$I2), 1400 [(set cls:$R1, (operator cls:$R1src, imm:$I2))]> { 1401 let Constraints = "$R1 = $R1src"; 1402} 1403 1404// Like BinaryRIE, but expanded after RA depending on the choice of register. 1405class BinaryRIEPseudo<SDPatternOperator operator, RegisterOperand cls, 1406 Immediate imm> 1407 : Pseudo<(outs cls:$R1), (ins cls:$R3, imm:$I2), 1408 [(set cls:$R1, (operator cls:$R3, imm:$I2))]>; 1409 1410// Like BinaryRIAndK, but expanded after RA depending on the choice of register. 1411multiclass BinaryRIAndKPseudo<string key, SDPatternOperator operator, 1412 RegisterOperand cls, Immediate imm> { 1413 let NumOpsKey = key in { 1414 let NumOpsValue = "3" in 1415 def K : BinaryRIEPseudo<null_frag, cls, imm>, 1416 Requires<[FeatureHighWord, FeatureDistinctOps]>; 1417 let NumOpsValue = "2", isConvertibleToThreeAddress = 1 in 1418 def "" : BinaryRIPseudo<operator, cls, imm>, 1419 Requires<[FeatureHighWord]>; 1420 } 1421} 1422 1423// Like CompareRI, but expanded after RA depending on the choice of register. 1424class CompareRIPseudo<SDPatternOperator operator, RegisterOperand cls, 1425 Immediate imm> 1426 : Pseudo<(outs), (ins cls:$R1, imm:$I2), [(operator cls:$R1, imm:$I2)]>; 1427 1428// Like CompareRXY, but expanded after RA depending on the choice of register. 1429class CompareRXYPseudo<SDPatternOperator operator, RegisterOperand cls, 1430 SDPatternOperator load, bits<5> bytes, 1431 AddressingMode mode = bdxaddr20only> 1432 : Pseudo<(outs), (ins cls:$R1, mode:$XBD2), 1433 [(operator cls:$R1, (load mode:$XBD2))]> { 1434 let mayLoad = 1; 1435 let Has20BitOffset = 1; 1436 let HasIndex = 1; 1437 let AccessBytes = bytes; 1438} 1439 1440// Like StoreRXY, but expanded after RA depending on the choice of register. 1441class StoreRXYPseudo<SDPatternOperator operator, RegisterOperand cls, 1442 bits<5> bytes, AddressingMode mode = bdxaddr20only> 1443 : Pseudo<(outs), (ins cls:$R1, mode:$XBD2), 1444 [(operator cls:$R1, mode:$XBD2)]> { 1445 let mayStore = 1; 1446 let Has20BitOffset = 1; 1447 let HasIndex = 1; 1448 let AccessBytes = bytes; 1449} 1450 1451// Like RotateSelectRIEf, but expanded after RA depending on the choice 1452// of registers. 1453class RotateSelectRIEfPseudo<RegisterOperand cls1, RegisterOperand cls2> 1454 : Pseudo<(outs cls1:$R1), 1455 (ins cls1:$R1src, cls2:$R2, imm32zx8:$I3, imm32zx8:$I4, 1456 imm32zx6:$I5), 1457 []> { 1458 let Constraints = "$R1 = $R1src"; 1459 let DisableEncoding = "$R1src"; 1460} 1461 1462// Implements "$dst = $cc & (8 >> CC) ? $src1 : $src2", where CC is 1463// the value of the PSW's 2-bit condition code field. 1464class SelectWrapper<RegisterOperand cls> 1465 : Pseudo<(outs cls:$dst), 1466 (ins cls:$src1, cls:$src2, imm32zx4:$valid, imm32zx4:$cc), 1467 [(set cls:$dst, (z_select_ccmask cls:$src1, cls:$src2, 1468 imm32zx4:$valid, imm32zx4:$cc))]> { 1469 let usesCustomInserter = 1; 1470 // Although the instructions used by these nodes do not in themselves 1471 // change CC, the insertion requires new blocks, and CC cannot be live 1472 // across them. 1473 let Defs = [CC]; 1474 let Uses = [CC]; 1475} 1476 1477// Stores $new to $addr if $cc is true ("" case) or false (Inv case). 1478multiclass CondStores<RegisterOperand cls, SDPatternOperator store, 1479 SDPatternOperator load, AddressingMode mode> { 1480 let Defs = [CC], Uses = [CC], usesCustomInserter = 1 in { 1481 def "" : Pseudo<(outs), 1482 (ins cls:$new, mode:$addr, imm32zx4:$valid, imm32zx4:$cc), 1483 [(store (z_select_ccmask cls:$new, (load mode:$addr), 1484 imm32zx4:$valid, imm32zx4:$cc), 1485 mode:$addr)]>; 1486 def Inv : Pseudo<(outs), 1487 (ins cls:$new, mode:$addr, imm32zx4:$valid, imm32zx4:$cc), 1488 [(store (z_select_ccmask (load mode:$addr), cls:$new, 1489 imm32zx4:$valid, imm32zx4:$cc), 1490 mode:$addr)]>; 1491 } 1492} 1493 1494// OPERATOR is ATOMIC_SWAP or an ATOMIC_LOAD_* operation. PAT and OPERAND 1495// describe the second (non-memory) operand. 1496class AtomicLoadBinary<SDPatternOperator operator, RegisterOperand cls, 1497 dag pat, DAGOperand operand> 1498 : Pseudo<(outs cls:$dst), (ins bdaddr20only:$ptr, operand:$src2), 1499 [(set cls:$dst, (operator bdaddr20only:$ptr, pat))]> { 1500 let Defs = [CC]; 1501 let Has20BitOffset = 1; 1502 let mayLoad = 1; 1503 let mayStore = 1; 1504 let usesCustomInserter = 1; 1505} 1506 1507// Specializations of AtomicLoadWBinary. 1508class AtomicLoadBinaryReg32<SDPatternOperator operator> 1509 : AtomicLoadBinary<operator, GR32, (i32 GR32:$src2), GR32>; 1510class AtomicLoadBinaryImm32<SDPatternOperator operator, Immediate imm> 1511 : AtomicLoadBinary<operator, GR32, (i32 imm:$src2), imm>; 1512class AtomicLoadBinaryReg64<SDPatternOperator operator> 1513 : AtomicLoadBinary<operator, GR64, (i64 GR64:$src2), GR64>; 1514class AtomicLoadBinaryImm64<SDPatternOperator operator, Immediate imm> 1515 : AtomicLoadBinary<operator, GR64, (i64 imm:$src2), imm>; 1516 1517// OPERATOR is ATOMIC_SWAPW or an ATOMIC_LOADW_* operation. PAT and OPERAND 1518// describe the second (non-memory) operand. 1519class AtomicLoadWBinary<SDPatternOperator operator, dag pat, 1520 DAGOperand operand> 1521 : Pseudo<(outs GR32:$dst), 1522 (ins bdaddr20only:$ptr, operand:$src2, ADDR32:$bitshift, 1523 ADDR32:$negbitshift, uimm32:$bitsize), 1524 [(set GR32:$dst, (operator bdaddr20only:$ptr, pat, ADDR32:$bitshift, 1525 ADDR32:$negbitshift, uimm32:$bitsize))]> { 1526 let Defs = [CC]; 1527 let Has20BitOffset = 1; 1528 let mayLoad = 1; 1529 let mayStore = 1; 1530 let usesCustomInserter = 1; 1531} 1532 1533// Specializations of AtomicLoadWBinary. 1534class AtomicLoadWBinaryReg<SDPatternOperator operator> 1535 : AtomicLoadWBinary<operator, (i32 GR32:$src2), GR32>; 1536class AtomicLoadWBinaryImm<SDPatternOperator operator, Immediate imm> 1537 : AtomicLoadWBinary<operator, (i32 imm:$src2), imm>; 1538 1539// Define an instruction that operates on two fixed-length blocks of memory, 1540// and associated pseudo instructions for operating on blocks of any size. 1541// The Sequence form uses a straight-line sequence of instructions and 1542// the Loop form uses a loop of length-256 instructions followed by 1543// another instruction to handle the excess. 1544multiclass MemorySS<string mnemonic, bits<8> opcode, 1545 SDPatternOperator sequence, SDPatternOperator loop> { 1546 def "" : InstSS<opcode, (outs), (ins bdladdr12onlylen8:$BDL1, 1547 bdaddr12only:$BD2), 1548 mnemonic##"\t$BDL1, $BD2", []>; 1549 let usesCustomInserter = 1 in { 1550 def Sequence : Pseudo<(outs), (ins bdaddr12only:$dest, bdaddr12only:$src, 1551 imm64:$length), 1552 [(sequence bdaddr12only:$dest, bdaddr12only:$src, 1553 imm64:$length)]>; 1554 def Loop : Pseudo<(outs), (ins bdaddr12only:$dest, bdaddr12only:$src, 1555 imm64:$length, GR64:$count256), 1556 [(loop bdaddr12only:$dest, bdaddr12only:$src, 1557 imm64:$length, GR64:$count256)]>; 1558 } 1559} 1560 1561// Define an instruction that operates on two strings, both terminated 1562// by the character in R0. The instruction processes a CPU-determinated 1563// number of bytes at a time and sets CC to 3 if the instruction needs 1564// to be repeated. Also define a pseudo instruction that represents 1565// the full loop (the main instruction plus the branch on CC==3). 1566multiclass StringRRE<string mnemonic, bits<16> opcode, 1567 SDPatternOperator operator> { 1568 def "" : InstRRE<opcode, (outs GR64:$R1, GR64:$R2), 1569 (ins GR64:$R1src, GR64:$R2src), 1570 mnemonic#"\t$R1, $R2", []> { 1571 let Constraints = "$R1 = $R1src, $R2 = $R2src"; 1572 let DisableEncoding = "$R1src, $R2src"; 1573 } 1574 let usesCustomInserter = 1 in 1575 def Loop : Pseudo<(outs GR64:$end), 1576 (ins GR64:$start1, GR64:$start2, GR32:$char), 1577 [(set GR64:$end, (operator GR64:$start1, GR64:$start2, 1578 GR32:$char))]>; 1579} 1580 1581// A pseudo instruction that is a direct alias of a real instruction. 1582// These aliases are used in cases where a particular register operand is 1583// fixed or where the same instruction is used with different register sizes. 1584// The size parameter is the size in bytes of the associated real instruction. 1585class Alias<int size, dag outs, dag ins, list<dag> pattern> 1586 : InstSystemZ<size, outs, ins, "", pattern> { 1587 let isPseudo = 1; 1588 let isCodeGenOnly = 1; 1589} 1590 1591// An alias of a BinaryRI, but with different register sizes. 1592class BinaryAliasRI<SDPatternOperator operator, RegisterOperand cls, 1593 Immediate imm> 1594 : Alias<4, (outs cls:$R1), (ins cls:$R1src, imm:$I2), 1595 [(set cls:$R1, (operator cls:$R1src, imm:$I2))]> { 1596 let Constraints = "$R1 = $R1src"; 1597} 1598 1599// An alias of a BinaryRIL, but with different register sizes. 1600class BinaryAliasRIL<SDPatternOperator operator, RegisterOperand cls, 1601 Immediate imm> 1602 : Alias<6, (outs cls:$R1), (ins cls:$R1src, imm:$I2), 1603 [(set cls:$R1, (operator cls:$R1src, imm:$I2))]> { 1604 let Constraints = "$R1 = $R1src"; 1605} 1606 1607// An alias of a CompareRI, but with different register sizes. 1608class CompareAliasRI<SDPatternOperator operator, RegisterOperand cls, 1609 Immediate imm> 1610 : Alias<4, (outs), (ins cls:$R1, imm:$I2), [(operator cls:$R1, imm:$I2)]> { 1611 let isCompare = 1; 1612} 1613 1614// An alias of a RotateSelectRIEf, but with different register sizes. 1615class RotateSelectAliasRIEf<RegisterOperand cls1, RegisterOperand cls2> 1616 : Alias<6, (outs cls1:$R1), 1617 (ins cls1:$R1src, cls2:$R2, imm32zx8:$I3, imm32zx8:$I4, 1618 imm32zx6:$I5), []> { 1619 let Constraints = "$R1 = $R1src"; 1620} 1621