1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
|
//== M68kInstrData.td - M68k Data Movement Instructions -*- tablegen --===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file describes the Motorola 680x0 data movement instructions which are
/// the basic means of transferring and storing addresses and data. Here is the
/// current status of the file:
///
/// Machine:
///
/// EXG [ ] FMOVE [ ] FSMOVE [ ] FDMOVE [ ] FMOVEM [ ]
/// LEA [~] PEA [ ] MOVE [~] MOVE16 [ ] MOVEA [ ]
/// MOVEM [ ] MOVEP [ ] MOVEQ [ ] LINK [ ] UNLK [ ]
///
/// Pseudo:
///
/// MOVSX [x] MOVZX [x] MOVX [x]
///
/// Map:
///
/// [ ] - was not touched at all
/// [!] - requires extarnal stuff implemented
/// [~] - in progress but usable
/// [x] - done
///
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// MOVE
//===----------------------------------------------------------------------===//
/// -----------------------------------------------------
/// F E | D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0
/// -----------------------------------------------------
/// | | DESTINATION | SOURCE
/// 0 0 | SIZE | REG | MODE | MODE | REG
/// -----------------------------------------------------
///
/// NOTE Move requires EA X version for direct register destination(0)
class MxMoveEncoding<MxBead2Bits size,
MxEncEA srcEA, MxEncExt srcExt,
MxEncEA dstEA, MxEncExt dstExt>
: MxEncoding<srcEA.Reg, srcEA.DA, srcEA.Mode, dstEA.DA, dstEA.Mode, dstEA.Reg,
size, MxBead2Bits<0b00>,
srcExt.Imm, srcExt.B8, srcExt.Scale, srcExt.WL, srcExt.DAReg,
dstExt.Imm, dstExt.B8, dstExt.Scale, dstExt.WL, dstExt.DAReg>;
/// MOVE has alternate size encoding
class MxMoveSize<bits<2> value> : MxBead2Bits<value>;
def MxMoveSize8 : MxMoveSize<0b01>;
def MxMoveSize16 : MxMoveSize<0b11>;
def MxMoveSize32 : MxMoveSize<0b10>;
let Defs = [CCR] in
class MxMove<string size, dag outs, dag ins, list<dag> pattern, MxEncoding enc>
: MxInst<outs, ins, "move."#size#"\t$src, $dst", pattern, enc>;
class MxMove_RR<MxType DST, MxType SRC, MxMoveEncoding ENC>
: MxMove<DST.Prefix, (outs DST.ROp:$dst), (ins SRC.ROp:$src),
[(null_frag)], ENC>;
let mayStore = 1 in {
class MxMove_MR<MxOperand MEMOpd, ComplexPattern MEMPat, MxType REG,
MxMoveEncoding ENC>
: MxMove<REG.Prefix, (outs), (ins MEMOpd:$dst, REG.ROp:$src),
[(store REG.VT:$src, MEMPat:$dst)], ENC>;
class MxMove_MI<MxOperand MEMOpd, ComplexPattern MEMPat, MxType TYPE,
MxMoveEncoding ENC>
: MxMove<TYPE.Prefix, (outs), (ins MEMOpd:$dst, TYPE.IOp:$src),
[(store TYPE.IPat:$src, MEMPat:$dst)], ENC>;
} // let mayStore = 1
class MxMove_RI<MxType DST, MxMoveEncoding ENC>
: MxMove<DST.Prefix, (outs DST.ROp:$dst), (ins DST.IOp:$src),
[(set DST.VT:$dst, DST.IPat:$src)], ENC>;
let mayLoad = 1 in
class MxMove_RM<MxType REG, MxOperand MEMOpd, ComplexPattern MEMPat,
MxBead2Bits SIZE,
MxEncEA SRCEA, MxEncExt SRCEXT,
MxEncEA DSTEA, MxEncExt DSTEXT>
: MxMove<REG.Prefix, (outs REG.ROp:$dst), (ins MEMOpd:$src),
[(set REG.VT:$dst, (REG.Load MEMPat:$src))],
MxMoveEncoding<SIZE, SRCEA, SRCEXT, DSTEA, DSTEXT>>;
multiclass MMxMove_RM<MxType REG, MxMoveSize SIZE, MxEncEA EA_0> {
// REG <- (An)+
def NAME#REG.OOp.Letter#REG.Postfix : MxMove_RM<REG, REG.OOp, REG.OPat,
SIZE, MxEncEAo_1, MxExtEmpty, EA_0, MxExtEmpty>;
// REG <- -(An)
def NAME#REG.EOp.Letter#REG.Postfix : MxMove_RM<REG, REG.EOp, REG.EPat,
SIZE, MxEncEAe_1, MxExtEmpty, EA_0, MxExtEmpty>;
// REG <- (i,PC,Xn)
def NAME#REG.KOp.Letter#REG.Postfix : MxMove_RM<REG, REG.KOp, REG.KPat,
SIZE, MxEncEAk, MxExtBrief_1, EA_0, MxExtEmpty>;
// REG <- (i,PC)
def NAME#REG.QOp.Letter#REG.Postfix : MxMove_RM<REG, REG.QOp, REG.QPat,
SIZE, MxEncEAq, MxExtI16_1, EA_0, MxExtEmpty>;
// REG <- (i,An,Xn)
def NAME#REG.FOp.Letter#REG.Postfix : MxMove_RM<REG, REG.FOp, REG.FPat,
SIZE, MxEncEAf_1, MxExtBrief_1, EA_0, MxExtEmpty>;
// REG <- (i,An)
def NAME#REG.POp.Letter#REG.Postfix : MxMove_RM<REG, REG.POp, REG.PPat,
SIZE, MxEncEAp_1, MxExtI16_1, EA_0, MxExtEmpty>;
// REG <- (ABS)
def NAME#REG.BOp.Letter#REG.Postfix : MxMove_RM<REG, REG.BOp, REG.BPat,
SIZE, MxEncEAb, MxExtI32_1, EA_0, MxExtEmpty>;
// REG <- (An)
def NAME#REG.JOp.Letter#REG.Postfix : MxMove_RM<REG, REG.JOp, REG.JPat,
SIZE, MxEncEAj_1, MxExtEmpty, EA_0, MxExtEmpty>;
}
let mayLoad = 1, mayStore = 1 in {
class MxMove_MM<string SIZE, PatFrag LOAD,
MxOperand DSTOpd, ComplexPattern DSTPat,
MxOperand SRCOpd, ComplexPattern SRCPat,
MxBead2Bits ESIZE,
MxEncEA SRCEA, MxEncExt SRCEXT,
MxEncEA DSTEA, MxEncExt DSTEXT>
: MxMove<SIZE, (outs), (ins DSTOpd:$dst, SRCOpd:$src),
[(store (LOAD SRCPat:$src), DSTPat:$dst)],
MxMoveEncoding<ESIZE, SRCEA, SRCEXT, DSTEA, DSTEXT>>;
} // let mayLoad = 1, mayStore = 1
multiclass MMxMove_MM<MxType TYPE, MxOperand DSTOpd, ComplexPattern DSTPat,
MxMoveSize SIZE, MxEncEA EA_0, MxEncExt EXT_0> {
// MEM <- (An)+
def NAME#TYPE.OOp.Letter#TYPE.Postfix
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.OOp, TYPE.OPat,
SIZE, MxEncEAo_1, MxExtEmpty, EA_0, EXT_0>;
// MEM <- -(An)
def NAME#TYPE.EOp.Letter#TYPE.Postfix
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.EOp, TYPE.EPat,
SIZE, MxEncEAe_1, MxExtEmpty, EA_0, EXT_0>;
// MEM <- (i,An)
def NAME#TYPE.POp.Letter#TYPE.Postfix
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.POp, TYPE.PPat,
SIZE, MxEncEAp_1, MxExtI16_1, EA_0, EXT_0>;
// MEM <- (i,An,Xn)
def NAME#TYPE.FOp.Letter#TYPE.Postfix
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.FOp, TYPE.FPat,
SIZE, MxEncEAf_1, MxExtBrief_1, EA_0, EXT_0>;
// MEM <- (i,PC,Xn)
def NAME#TYPE.KOp.Letter#TYPE.Postfix
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.KOp, TYPE.KPat,
SIZE, MxEncEAk, MxExtBrief_1, EA_0, EXT_0>;
// MEM <- (i,PC)
def NAME#TYPE.QOp.Letter#TYPE.Postfix
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.QOp, TYPE.QPat,
SIZE, MxEncEAq, MxExtI16_1, EA_0, EXT_0>;
// MEM <- (ABS)
def NAME#TYPE.BOp.Letter#TYPE.Postfix
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.BOp, TYPE.BPat,
SIZE, MxEncEAb, MxExtI32_1, EA_0, EXT_0>;
// MEM <- (An)
def NAME#TYPE.JOp.Letter#TYPE.Postfix
: MxMove_MM<TYPE.Prefix, TYPE.Load, DSTOpd, DSTPat, TYPE.JOp, TYPE.JPat,
SIZE, MxEncEAj_1, MxExtEmpty, EA_0, EXT_0>;
}
def MOV8dd
: MxMove_RR<MxType8d, MxType8d,
MxMoveEncoding<MxMoveSize8, MxEncEAd_1, MxExtEmpty, MxEncEAd_0, MxExtEmpty>>;
// M <- R
def MOV8fd : MxMove_MR<MxType8.FOp, MxType8.FPat, MxType8d,
MxMoveEncoding<MxMoveSize8,
/*src*/ MxEncEAd_1, MxExtEmpty,
/*dst*/ MxEncEAf_0, MxExtBrief_0>>;
def MOV8pd : MxMove_MR<MxType8.POp, MxType8.PPat, MxType8d,
MxMoveEncoding<MxMoveSize8,
/*src*/ MxEncEAd_1, MxExtEmpty,
/*dst*/ MxEncEAp_0, MxExtI16_0>>;
def MOV8ed : MxMove_MR<MxType8.EOp, MxType8.EPat, MxType8d,
MxMoveEncoding<MxMoveSize8,
/*src*/ MxEncEAd_1, MxExtEmpty,
/*dst*/ MxEncEAe_0, MxExtEmpty>>;
def MOV8od : MxMove_MR<MxType8.OOp, MxType8.OPat, MxType8d,
MxMoveEncoding<MxMoveSize8,
/*src*/ MxEncEAd_1, MxExtEmpty,
/*dst*/ MxEncEAo_0, MxExtEmpty>>;
def MOV8bd : MxMove_MR<MxType8.BOp, MxType8.BPat, MxType8d,
MxMoveEncoding<MxMoveSize8,
/*src*/ MxEncEAd_1, MxExtEmpty,
/*dst*/ MxEncEAb, MxExtI32_0>>;
def MOV8jd : MxMove_MR<MxType8.JOp, MxType8.JPat, MxType8d,
MxMoveEncoding<MxMoveSize8,
/*src*/ MxEncEAd_1, MxExtEmpty,
/*dst*/ MxEncEAj_0, MxExtEmpty>>;
// R <- I
def MOV8di : MxMove_RI<MxType8d,
MxMoveEncoding<MxMoveSize8, MxEncEAi, MxExtI8_1, MxEncEAd_0, MxExtEmpty>>;
foreach S = [16, 32] in {
foreach D = [ "r", "a" ] in {
foreach O = [ "r", "a" ] in {
def MOV#S#D#O : MxMove_RR<
!cast<MxType>("MxType"#S#D),
!cast<MxType>("MxType"#S#O),
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
!cast<MxEncEA>("MxEncEA"#D#"_0_reflected"), MxExtEmpty>>;
}
// M <- R
def MOV#S#"f"#D : MxMove_MR<
!cast<MxType>("MxType"#S).FOp,
!cast<MxType>("MxType"#S).FPat,
!cast<MxType>("MxType"#S#D),
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
MxEncEAf_0, MxExtBrief_0>>;
def MOV#S#"p"#D : MxMove_MR<
!cast<MxType>("MxType"#S).POp,
!cast<MxType>("MxType"#S).PPat,
!cast<MxType>("MxType"#S#D),
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
MxEncEAp_0, MxExtI16_0>>;
def MOV#S#"e"#D : MxMove_MR<
!cast<MxType>("MxType"#S).EOp,
!cast<MxType>("MxType"#S).EPat,
!cast<MxType>("MxType"#S#D),
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
MxEncEAe_0, MxExtEmpty>>;
def MOV#S#"o"#D : MxMove_MR<
!cast<MxType>("MxType"#S).OOp,
!cast<MxType>("MxType"#S).OPat,
!cast<MxType>("MxType"#S#D),
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
MxEncEAo_0, MxExtEmpty>>;
def MOV#S#"b"#D : MxMove_MR<
!cast<MxType>("MxType"#S).BOp,
!cast<MxType>("MxType"#S).BPat,
!cast<MxType>("MxType"#S#D),
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
MxEncEAb, MxExtI32_0>>;
def MOV#S#"j"#D : MxMove_MR<
!cast<MxType>("MxType"#S).JOp,
!cast<MxType>("MxType"#S).JPat,
!cast<MxType>("MxType"#S#D),
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
!cast<MxEncEA>("MxEncEA"#D#"_1"), MxExtEmpty,
MxEncEAj_0, MxExtEmpty>>;
// R <- I
def MOV#S#D#"i" : MxMove_RI<
!cast<MxType>("MxType"#S#D),
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
!cast<MxEncEA>("MxEncEA"#D#"_0_reflected"), MxExtEmpty>>;
}
}
// M <- I
foreach S = [8, 16, 32] in {
def MOV#S#"f"#"i" : MxMove_MI<
!cast<MxType>("MxType"#S).FOp,
!cast<MxType>("MxType"#S).FPat,
!cast<MxType>("MxType"#S),
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
MxEncEAf_0, MxExtBrief_0>>;
def MOV#S#"p"#"i" : MxMove_MI<
!cast<MxType>("MxType"#S).POp,
!cast<MxType>("MxType"#S).PPat,
!cast<MxType>("MxType"#S),
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
MxEncEAp_0, MxExtI16_0>>;
def MOV#S#"b"#"i" : MxMove_MI<
!cast<MxType>("MxType"#S).BOp,
!cast<MxType>("MxType"#S).BPat,
!cast<MxType>("MxType"#S),
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
MxEncEAb, MxExtI32_0>>;
def MOV#S#"j"#"i" : MxMove_MI<
!cast<MxType>("MxType"#S).JOp,
!cast<MxType>("MxType"#S).JPat,
!cast<MxType>("MxType"#S),
MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#S),
MxEncEAi, !cast<MxEncExt>("MxExtI"#S#"_1"),
MxEncEAj_0, MxExtEmpty>>;
}
// Store ABS(basically pointer) as Immdiate to Mem
def : Pat<(store MxType32.BPat :$src, MxType32.PPat :$dst),
(MOV32pi MxType32.POp :$dst, MxType32.IOp :$src)>;
def : Pat<(store MxType32.BPat :$src, MxType32.FPat :$dst),
(MOV32fi MxType32.FOp :$dst, MxType32.IOp :$src)>;
def : Pat<(store MxType32.BPat :$src, MxType32.BPat :$dst),
(MOV32bi MxType32.BOp :$dst, MxType32.IOp :$src)>;
def : Pat<(store MxType32.BPat :$src, MxType32.JPat :$dst),
(MOV32ji MxType32.JOp :$dst, MxType32.IOp :$src)>;
// R <- M
defm MOV8d : MMxMove_RM<MxType8d, MxMoveSize8, MxEncEAd_0>;
defm MOV16r : MMxMove_RM<MxType16r, MxMoveSize16, MxEncEAr_0_reflected>;
defm MOV16a : MMxMove_RM<MxType16a, MxMoveSize16, MxEncEAa_0>;
defm MOV32r : MMxMove_RM<MxType32r, MxMoveSize32, MxEncEAr_0_reflected>;
defm MOV32a : MMxMove_RM<MxType32a, MxMoveSize32, MxEncEAa_0>;
let Pattern = [(null_frag)] in {
defm MOV16r : MMxMove_RM<MxType16r_TC, MxMoveSize16, MxEncEAr_0_reflected>;
defm MOV16a : MMxMove_RM<MxType16a_TC, MxMoveSize16, MxEncEAa_0>;
defm MOV32r : MMxMove_RM<MxType32r_TC, MxMoveSize32, MxEncEAr_0_reflected>;
defm MOV32a : MMxMove_RM<MxType32a_TC, MxMoveSize32, MxEncEAa_0>;
} // Pattern
// M <- M
defm MOV8p : MMxMove_MM<MxType8, MxType8.POp, MxType8.PPat,
MxMoveSize8, MxEncEAp_0, MxExtI16_0>;
defm MOV16p : MMxMove_MM<MxType16, MxType16.POp, MxType16.PPat,
MxMoveSize16, MxEncEAp_0, MxExtI16_0>;
defm MOV32p : MMxMove_MM<MxType32, MxType32.POp, MxType32.PPat,
MxMoveSize32, MxEncEAp_0, MxExtI16_0>;
defm MOV8f : MMxMove_MM<MxType8, MxType8.FOp, MxType8.FPat,
MxMoveSize8, MxEncEAf_0, MxExtBrief_0>;
defm MOV16f : MMxMove_MM<MxType16, MxType16.FOp, MxType16.FPat,
MxMoveSize16, MxEncEAf_0, MxExtBrief_0>;
defm MOV32f : MMxMove_MM<MxType32, MxType32.FOp, MxType32.FPat,
MxMoveSize32, MxEncEAf_0, MxExtBrief_0>;
defm MOV8b : MMxMove_MM<MxType8, MxType8.BOp, MxType8.BPat,
MxMoveSize8, MxEncEAb, MxExtI32_0>;
defm MOV16b : MMxMove_MM<MxType16, MxType16.BOp, MxType16.BPat,
MxMoveSize16, MxEncEAb, MxExtI32_0>;
defm MOV32b : MMxMove_MM<MxType32, MxType32.BOp, MxType32.BPat,
MxMoveSize32, MxEncEAb, MxExtI32_0>;
defm MOV8e : MMxMove_MM<MxType8, MxType8.EOp, MxType8.EPat,
MxMoveSize8, MxEncEAe_0, MxExtEmpty>;
defm MOV16e : MMxMove_MM<MxType16, MxType16.EOp, MxType16.EPat,
MxMoveSize16, MxEncEAe_0, MxExtEmpty>;
defm MOV32e : MMxMove_MM<MxType32, MxType32.EOp, MxType32.EPat,
MxMoveSize32, MxEncEAe_0, MxExtEmpty>;
defm MOV8o : MMxMove_MM<MxType8, MxType8.OOp, MxType8.OPat,
MxMoveSize8, MxEncEAo_0, MxExtEmpty>;
defm MOV16o : MMxMove_MM<MxType16, MxType16.OOp, MxType16.OPat,
MxMoveSize16, MxEncEAo_0, MxExtEmpty>;
defm MOV32o : MMxMove_MM<MxType32, MxType32.OOp, MxType32.OPat,
MxMoveSize32, MxEncEAo_0, MxExtEmpty>;
defm MOV8j : MMxMove_MM<MxType8, MxType8.JOp, MxType8.JPat,
MxMoveSize8, MxEncEAj_0, MxExtEmpty>;
defm MOV16j : MMxMove_MM<MxType16, MxType16.JOp, MxType16.JPat,
MxMoveSize16, MxEncEAj_0, MxExtEmpty>;
defm MOV32j : MMxMove_MM<MxType32, MxType32.JOp, MxType32.JPat,
MxMoveSize32, MxEncEAj_0, MxExtEmpty>;
//===----------------------------------------------------------------------===//
// MOVEM
//
// The mask is already pre-processed by the save/restore spill hook
//===----------------------------------------------------------------------===//
// Direction
def MxMOVEM_MR : MxBead1Bit<0>;
def MxMOVEM_RM : MxBead1Bit<1>;
// Size
def MxMOVEM_W : MxBead1Bit<0>;
def MxMOVEM_L : MxBead1Bit<1>;
/// ---------------+-------------+-------------+---------
/// F E D C B | A | 9 8 7 | 6 | 5 4 3 | 2 1 0
/// ---------------+---+---------+---+---------+---------
/// 0 1 0 0 1 | D | 0 0 1 | S | MODE | REG
/// ---------------+---+---------+---+---------+---------
/// REGISTER LIST MASK
/// -----------------------------------------------------
/// D - direction(RM,MR)
/// S - size(W,L)
class MxMOVEMEncoding<MxEncEA EA, MxEncExt EXT, MxBead1Bit SIZE, MxBead1Bit DIR,
MxBead16Imm IMM>
: MxEncoding<EA.Reg, EA.DA, EA.Mode, SIZE, MxBead3Bits<0b001>, DIR,
MxBead1Bit<1>, MxBead4Bits<0b0100>, IMM,
EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>;
let mayStore = 1 in
class MxMOVEM_MR<MxType TYPE, MxBead1Bit SIZE,
MxOperand MEMOp, MxEncEA EA, MxEncExt EXT>
: MxInst<(outs), (ins MEMOp:$dst, MxMoveMask:$mask),
"movem."#TYPE.Prefix#"\t$mask, $dst", [],
MxMOVEMEncoding<EA, EXT, SIZE, MxMOVEM_MR, MxBead16Imm<1>>>;
let mayLoad = 1 in
class MxMOVEM_RM<MxType TYPE, MxBead1Bit SIZE,
MxOperand MEMOp, MxEncEA EA, MxEncExt EXT>
: MxInst<(outs), (ins MxMoveMask:$mask, MEMOp:$src),
"movem."#TYPE.Prefix#"\t$src, $mask", [],
MxMOVEMEncoding<EA, EXT, SIZE, MxMOVEM_RM, MxBead16Imm<0>>>;
def MOVM32jm : MxMOVEM_MR<MxType32, MxMOVEM_L, MxType32.JOp, MxEncEAj_0, MxExtEmpty>;
def MOVM32pm : MxMOVEM_MR<MxType32, MxMOVEM_L, MxType32.POp, MxEncEAp_0, MxExtI16_0>;
def MOVM32mj : MxMOVEM_RM<MxType32, MxMOVEM_L, MxType32.JOp, MxEncEAj_1, MxExtEmpty>;
def MOVM32mp : MxMOVEM_RM<MxType32, MxMOVEM_L, MxType32.POp, MxEncEAp_1, MxExtI16_1>;
// Pseudo versions. These a required by virtual register spill/restore since
// the mask requires real register to encode. These instruction will be expanded
// into real MOVEM after RA finishes.
let mayStore = 1 in
class MxMOVEM_MR_Pseudo<MxType TYPE, MxOperand MEMOp>
: MxPseudo<(outs), (ins MEMOp:$dst, TYPE.ROp:$reg)>;
let mayLoad = 1 in
class MxMOVEM_RM_Pseudo<MxType TYPE, MxOperand MEMOp>
: MxPseudo<(outs TYPE.ROp:$dst), (ins MEMOp:$src)>;
// Mem <- Reg
def MOVM8jm_P : MxMOVEM_MR_Pseudo<MxType8d, MxType8.JOp>;
def MOVM16jm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.JOp>;
def MOVM32jm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.JOp>;
def MOVM8pm_P : MxMOVEM_MR_Pseudo<MxType8d, MxType8.POp>;
def MOVM16pm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.POp>;
def MOVM32pm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.POp>;
// Reg <- Mem
def MOVM8mj_P : MxMOVEM_RM_Pseudo<MxType8d, MxType8.JOp>;
def MOVM16mj_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.JOp>;
def MOVM32mj_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.JOp>;
def MOVM8mp_P : MxMOVEM_RM_Pseudo<MxType8d, MxType8.POp>;
def MOVM16mp_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.POp>;
def MOVM32mp_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.POp>;
//===----------------------------------------------------------------------===//
// MOVE to/from SR/CCR
//
// A special care must be taken working with to/from CCR since it is basically
// word-size SR register truncated for user mode thus it only supports word-size
// instructions. Plus the original M68000 does not support moves from CCR. So in
// order to use CCR effectively one MUST use proper byte-size pseudo instructi-
// ons that will be resolved sometime after RA pass.
//===----------------------------------------------------------------------===//
/// --------------------------------------------------
/// F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0
/// --------------------------------------------------
/// | EFFECTIVE ADDRESS
/// 0 1 0 0 0 1 0 0 1 1 | MODE | REG
/// --------------------------------------------------
let Defs = [CCR] in
class MxMoveToCCR<dag INS, MxEncEA EA, MxEncExt EXT>
: MxInst<(outs CCRC:$dst), INS, "move.w\t$src, $dst", [],
MxEncoding<EA.Reg, EA.DA, EA.Mode,
MxBead4Bits<0b0011>, MxBead4Bits<0b0001>, MxBead2Bits<0b01>,
EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>;
class MxMoveToCCRPseudo<dag INS> : MxPseudo<(outs CCRC:$dst), INS>;
let mayLoad = 1 in {
def MOV16cp : MxMoveToCCR<(ins MxType16d.POp:$src), MxEncEAp_1, MxExtI16_1>;
def MOV8cp : MxMoveToCCRPseudo<(ins MxType8d.POp:$src)>;
} // let mayLoad = 1
def MOV16cd : MxMoveToCCR<(ins MxType16d.ROp:$src), MxEncEAd_1, MxExtEmpty>;
def MOV8cd : MxMoveToCCRPseudo<(ins MxType8d.ROp:$src)>;
/// Move from CCR
/// --------------------------------------------------
/// F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0
/// --------------------------------------------------
/// | EFFECTIVE ADDRESS
/// 0 1 0 0 0 0 1 0 1 1 | MODE | REG
/// --------------------------------------------------
let Uses = [CCR] in
class MxMoveFromCCR<dag OUTS, dag INS, MxEncEA EA, MxEncExt EXT>
: MxInst<OUTS, INS, "move.w\t$src, $dst", [],
MxEncoding<EA.Reg, EA.DA, EA.Mode,
MxBead4Bits<0b1011>, MxBead4Bits<0b0000>, MxBead2Bits<0b01>,
EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>,
Requires<[ IsM68010 ]>;
class MxMoveFromCCRPseudo<dag INS> : MxPseudo<(outs), INS>;
let mayStore = 1 in {
def MOV16pc
: MxMoveFromCCR<(outs), (ins MxType16d.POp:$dst, CCRC:$src), MxEncEAp_0, MxExtI16_0>;
def MOV8pc : MxMoveFromCCRPseudo<(ins MxType8d.POp:$dst, CCRC:$src)>;
} // let mayStore = 1
def MOV16dc
: MxMoveFromCCR<(outs MxType16d.ROp:$dst), (ins CCRC:$src), MxEncEAd_0, MxExtEmpty>;
def MOV8dc : MxMoveFromCCRPseudo<(ins MxType8d.ROp:$dst, CCRC:$src)>;
//===----------------------------------------------------------------------===//
// LEA
//===----------------------------------------------------------------------===//
/// ----------------------------------------------------
/// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0
/// ----------------------------------------------------
/// 0 1 0 0 | DST REG | 1 1 1 | MODE | REG
/// ----------------------------------------------------
class MxLEA<MxOperand SRCOpd, ComplexPattern SRCPat, MxEncEA EA, MxEncExt EXT>
: MxInst<(outs MxARD32:$dst), (ins SRCOpd:$src),
"lea\t$src, $dst", [(set i32:$dst, SRCPat:$src)],
MxEncoding<EA.Reg, EA.DA, EA.Mode,
MxBead3Bits<0b111>, MxBeadReg<0>, MxBead4Bits<0x4>,
EXT.Imm, EXT.B8, EXT.Scale, EXT.WL, EXT.DAReg>>;
def LEA32p : MxLEA<MxARID32, MxCP_ARID, MxEncEAp_1, MxExtI16_1>;
def LEA32f : MxLEA<MxARII32, MxCP_ARII, MxEncEAf_1, MxExtBrief_1>;
def LEA32q : MxLEA<MxPCD32, MxCP_PCD, MxEncEAq, MxExtI16_1>;
def LEA32b : MxLEA<MxAL32, MxCP_AL, MxEncEAb, MxExtI32_1>;
//===----------------------------------------------------------------------===//
// Pseudos
//===----------------------------------------------------------------------===//
/// Pushe/Pop to/from SP for simplicity
let Uses = [SP], Defs = [SP], hasSideEffects = 0 in {
// SP <- SP - <size>; (SP) <- Dn
let mayStore = 1 in {
def PUSH8d : MxPseudo<(outs), (ins DR8:$reg)>;
def PUSH16d : MxPseudo<(outs), (ins DR16:$reg)>;
def PUSH32r : MxPseudo<(outs), (ins XR32:$reg)>;
} // let mayStore = 1
// Dn <- (SP); SP <- SP + <size>
let mayLoad = 1 in {
def POP8d : MxPseudo<(outs DR8:$reg), (ins)>;
def POP16d : MxPseudo<(outs DR16:$reg), (ins)>;
def POP32r : MxPseudo<(outs XR32:$reg), (ins)>;
} // let mayLoad = 1
} // let Uses/Defs = [SP], hasSideEffects = 0
let Defs = [CCR] in {
class MxPseudoMove_RR<MxType DST, MxType SRC, list<dag> PAT = []>
: MxPseudo<(outs DST.ROp:$dst), (ins SRC.ROp:$src), PAT>;
class MxPseudoMove_RM<MxType DST, MxOperand SRCOpd, list<dag> PAT = []>
: MxPseudo<(outs DST.ROp:$dst), (ins SRCOpd:$src), PAT>;
}
/// This group of Pseudos is analogues to the real x86 extending moves, but
/// since M68k does not have those we need to emulate. These instructions
/// will be expanded right after RA completed because we need to know precisely
/// what registers are allocated for the operands and if they overlap we just
/// extend the value if the registers are completely different we need to move
/// first.
foreach EXT = ["S", "Z"] in {
let hasSideEffects = 0 in {
def MOV#EXT#Xd16d8 : MxPseudoMove_RR<MxType16d, MxType8d>;
def MOV#EXT#Xd32d8 : MxPseudoMove_RR<MxType32d, MxType8d>;
def MOV#EXT#Xd32d16 : MxPseudoMove_RR<MxType32r, MxType16r>;
let mayLoad = 1 in {
def MOV#EXT#Xd16j8 : MxPseudoMove_RM<MxType16d, MxType8.JOp>;
def MOV#EXT#Xd32j8 : MxPseudoMove_RM<MxType32d, MxType8.JOp>;
def MOV#EXT#Xd32j16 : MxPseudoMove_RM<MxType32d, MxType16.JOp>;
def MOV#EXT#Xd16p8 : MxPseudoMove_RM<MxType16d, MxType8.POp>;
def MOV#EXT#Xd32p8 : MxPseudoMove_RM<MxType32d, MxType8.POp>;
def MOV#EXT#Xd32p16 : MxPseudoMove_RM<MxType32d, MxType16.POp>;
def MOV#EXT#Xd16f8 : MxPseudoMove_RM<MxType16d, MxType8.FOp>;
def MOV#EXT#Xd32f8 : MxPseudoMove_RM<MxType32d, MxType8.FOp>;
def MOV#EXT#Xd32f16 : MxPseudoMove_RM<MxType32d, MxType16.FOp>;
}
}
}
/// This group of instructions is similar to the group above but DOES NOT do
/// any value extension, they just load a smaller register into the lower part
/// of another register if operands' real registers are different or does
/// nothing if they are the same.
def MOVXd16d8 : MxPseudoMove_RR<MxType16d, MxType8d>;
def MOVXd32d8 : MxPseudoMove_RR<MxType32d, MxType8d>;
def MOVXd32d16 : MxPseudoMove_RR<MxType32r, MxType16r>;
//===----------------------------------------------------------------------===//
// Extend/Truncate Patterns
//===----------------------------------------------------------------------===//
// i16 <- sext i8
def: Pat<(i16 (sext i8:$src)),
(EXTRACT_SUBREG (MOVSXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;
def: Pat<(MxSExtLoadi16i8 MxCP_ARI:$src),
(EXTRACT_SUBREG (MOVSXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;
def: Pat<(MxSExtLoadi16i8 MxCP_ARID:$src),
(EXTRACT_SUBREG (MOVSXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;
def: Pat<(MxSExtLoadi16i8 MxCP_ARII:$src),
(EXTRACT_SUBREG (MOVSXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;
// i32 <- sext i8
def: Pat<(i32 (sext i8:$src)), (MOVSXd32d8 MxDRD8:$src)>;
def: Pat<(MxSExtLoadi32i8 MxCP_ARI :$src), (MOVSXd32j8 MxARI8 :$src)>;
def: Pat<(MxSExtLoadi32i8 MxCP_ARID:$src), (MOVSXd32p8 MxARID8:$src)>;
def: Pat<(MxSExtLoadi32i8 MxCP_ARII:$src), (MOVSXd32f8 MxARII8:$src)>;
// i32 <- sext i16
def: Pat<(i32 (sext i16:$src)), (MOVSXd32d16 MxDRD16:$src)>;
def: Pat<(MxSExtLoadi32i16 MxCP_ARI :$src), (MOVSXd32j16 MxARI16 :$src)>;
def: Pat<(MxSExtLoadi32i16 MxCP_ARID:$src), (MOVSXd32p16 MxARID16:$src)>;
def: Pat<(MxSExtLoadi32i16 MxCP_ARII:$src), (MOVSXd32f16 MxARII16:$src)>;
// i16 <- zext i8
def: Pat<(i16 (zext i8:$src)),
(EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;
def: Pat<(MxZExtLoadi16i8 MxCP_ARI:$src),
(EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;
def: Pat<(MxZExtLoadi16i8 MxCP_ARID:$src),
(EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;
def: Pat<(MxZExtLoadi16i8 MxCP_ARII:$src),
(EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;
// i32 <- zext i8
def: Pat<(i32 (zext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>;
def: Pat<(MxZExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>;
def: Pat<(MxZExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>;
def: Pat<(MxZExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>;
// i32 <- zext i16
def: Pat<(i32 (zext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>;
def: Pat<(MxZExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>;
def: Pat<(MxZExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>;
def: Pat<(MxZExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>;
// i16 <- anyext i8
def: Pat<(i16 (anyext i8:$src)),
(EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>;
def: Pat<(MxExtLoadi16i8 MxCP_ARI:$src),
(EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>;
def: Pat<(MxExtLoadi16i8 MxCP_ARID:$src),
(EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>;
def: Pat<(MxExtLoadi16i8 MxCP_ARII:$src),
(EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>;
// i32 <- anyext i8
def: Pat<(i32 (anyext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>;
def: Pat<(MxExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>;
def: Pat<(MxExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>;
def: Pat<(MxExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>;
// i32 <- anyext i16
def: Pat<(i32 (anyext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>;
def: Pat<(MxExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>;
def: Pat<(MxExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>;
def: Pat<(MxExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>;
// trunc patterns
def : Pat<(i16 (trunc i32:$src)),
(EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex16Lo)>;
def : Pat<(i8 (trunc i32:$src)),
(EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex8Lo)>;
def : Pat<(i8 (trunc i16:$src)),
(EXTRACT_SUBREG MxXRD16:$src, MxSubRegIndex8Lo)>;
|