1//===-- M68kInstrArithmetic.td - Integer Arith Instrs ------*- tablegen -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8/// 9/// \file 10/// This file describes the integer arithmetic instructions in the M68k 11/// architecture. Here is the current status of the file: 12/// 13/// Machine: 14/// 15/// ADD [~] ADDA [~] ADDI [~] ADDQ [ ] ADDX [~] 16/// CLR [ ] CMP [~] CMPA [~] CMPI [~] CMPM [ ] 17/// CMP2 [ ] DIVS/DIVU [~] DIVSL/DIVUL [ ] EXT [~] EXTB [ ] 18/// MULS/MULU [~] NEG [~] NEGX [~] SUB [~] SUBA [~] 19/// SUBI [~] SUBQ [ ] SUBX [~] 20/// 21/// Map: 22/// 23/// [ ] - was not touched at all 24/// [!] - requires extarnal stuff implemented 25/// [~] - functional implementation 26/// [X] - complete implementation 27/// 28//===----------------------------------------------------------------------===// 29 30//===----------------------------------------------------------------------===// 31// OPMODE Encoding 32//===----------------------------------------------------------------------===// 33class MxOpModeEncoding<bits<3> encoding> { 34 bits<3> Value = encoding; 35} 36 37// op EA, Dn 38def MxOpMode8_d_EA : MxOpModeEncoding<0b000>; 39def MxOpMode16_d_EA : MxOpModeEncoding<0b001>; 40def MxOpMode32_d_EA : MxOpModeEncoding<0b010>; 41 42// op Dn, EA 43def MxOpMode8_EA_d : MxOpModeEncoding<0b100>; 44def MxOpMode16_EA_d : MxOpModeEncoding<0b101>; 45def MxOpMode32_EA_d : MxOpModeEncoding<0b110>; 46 47// op EA, An 48def MxOpMode16_a_EA : MxOpModeEncoding<0b011>; 49def MxOpMode32_a_EA : MxOpModeEncoding<0b111>; 50 51 52//===----------------------------------------------------------------------===// 53// Encoding 54//===----------------------------------------------------------------------===// 55 56let Defs = [CCR] in { 57let Constraints = "$src = $dst" in { 58 59/// Encoding for Normal forms 60/// ---------------------------------------------------- 61/// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0 62/// ---------------------------------------------------- 63/// | | | EFFECTIVE ADDRESS 64/// x x x x | REG | OP MODE | MODE | REG 65/// ---------------------------------------------------- 66 67// $reg, $ccr <- $reg op $reg 68class MxBiArOp_R_RR_xEA<string MN, SDNode NODE, MxType DST_TYPE, MxType SRC_TYPE, 69 bits<4> CMD> 70 : MxInst<(outs DST_TYPE.ROp:$dst), (ins DST_TYPE.ROp:$src, SRC_TYPE.ROp:$opd), 71 MN#"."#DST_TYPE.Prefix#"\t$opd, $dst", 72 [(set DST_TYPE.VT:$dst, CCR, (NODE DST_TYPE.VT:$src, SRC_TYPE.VT:$opd))]> { 73 let Inst = (descend 74 CMD, (operand "$dst", 3), 75 !cast<MxOpModeEncoding>("MxOpMode"#DST_TYPE.Size#"_"#DST_TYPE.RLet#"_EA").Value, 76 !cond( 77 !eq(SRC_TYPE.RLet, "r") : (descend 0b00, (operand "$opd", 4)), 78 !eq(SRC_TYPE.RLet, "d") : (descend 0b000, (operand "$opd", 3)) 79 ) 80 ); 81} 82 83/// This Op is similar to the one above except it uses reversed opmode, some 84/// commands(e.g. eor) do not support dEA or rEA modes and require EAd for 85/// register only operations. 86/// NOTE when using dd commands it is irrelevant which opmode to use(as it seems) 87/// but some opcodes support address register and some do not which creates this 88/// mess. 89class MxBiArOp_R_RR_EAd<string MN, SDNode NODE, MxType TYPE, bits<4> CMD> 90 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd), 91 MN#"."#TYPE.Prefix#"\t$opd, $dst", 92 [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd))]> { 93 let Inst = (descend 94 CMD, (operand "$opd", 3), 95 !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_EA_"#TYPE.RLet).Value, 96 /*Destination can only be a data register*/ 97 /*MODE*/0b000, 98 /*REGISTER*/(operand "$dst", 3)); 99} 100 101let mayLoad = 1 in 102class MxBiArOp_R_RM<string MN, SDNode NODE, MxType TYPE, MxOperand OPD, ComplexPattern PAT, 103 bits<4> CMD, MxEncMemOp SRC_ENC> 104 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, OPD:$opd), 105 MN#"."#TYPE.Prefix#"\t$opd, $dst", 106 [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, (TYPE.Load PAT:$opd)))]> { 107 let Inst = (ascend 108 (descend CMD, (operand "$dst", 3), 109 !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_"#TYPE.RLet#"_EA").Value, 110 SRC_ENC.EA), 111 SRC_ENC.Supplement 112 ); 113} 114 115/// Encoding for Immediate forms 116/// --------------------------------------------------- 117/// F E D C B A 9 8 | 7 6 | 5 4 3 | 2 1 0 118/// --------------------------------------------------- 119/// | | EFFECTIVE ADDRESS 120/// x x x x x x x x | SIZE | MODE | REG 121/// --------------------------------------------------- 122/// 16-BIT WORD DATA | 8-BIT BYTE DATA 123/// --------------------------------------------------- 124/// 32-BIT LONG DATA 125/// --------------------------------------------------- 126/// NOTE It is used to store an immediate to memory, imm-to-reg are handled with 127/// normal version 128 129// $reg <- $reg op $imm 130class MxBiArOp_R_RI_xEA<string MN, SDNode NODE, MxType TYPE, bits<4> CMD> 131 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd), 132 MN#"."#TYPE.Prefix#"\t$opd, $dst", 133 [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))]> { 134 let Inst = (ascend 135 (descend CMD, (operand "$dst", 3), 136 !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_"#TYPE.RLet#"_EA").Value, 137 MxEncAddrMode_i<"opd", TYPE.Size>.EA), 138 MxEncAddrMode_i<"opd", TYPE.Size>.Supplement 139 ); 140} 141 142// Again, there are two ways to write an immediate to Dn register either dEA 143// opmode or using *I encoding, and again some instructions also support address 144// registers some do not. 145class MxBiArOp_R_RI<string MN, SDNode NODE, MxType TYPE, bits<4> CMD> 146 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd), 147 MN#"i."#TYPE.Prefix#"\t$opd, $dst", 148 [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))]> { 149 let Inst = (ascend 150 (descend 0b0000, CMD, 151 !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 152 // The destination cannot be address register, so it's always 153 // the MODE for data register direct mode. 154 /*MODE*/0b000, 155 /*REGISTER*/(operand "$dst", 3)), 156 // Source (i.e. immediate value) encoding 157 MxEncAddrMode_i<"opd", TYPE.Size>.Supplement 158 ); 159} 160} // Constraints 161 162let mayLoad = 1, mayStore = 1 in { 163 164// FIXME MxBiArOp_FMR/FMI cannot consume CCR from MxAdd/MxSub which leads for 165// MxAdd to survive the match and subsequent mismatch. 166class MxBiArOp_MR<string MN, MxType TYPE, 167 MxOperand MEMOpd, bits<4> CMD, MxEncMemOp DST_ENC> 168 : MxInst<(outs), (ins MEMOpd:$dst, TYPE.ROp:$opd), 169 MN#"."#TYPE.Prefix#"\t$opd, $dst", []> { 170 let Inst = (ascend 171 (descend CMD, (operand "$opd", 3), 172 !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_EA_"#TYPE.RLet).Value, 173 DST_ENC.EA), 174 DST_ENC.Supplement 175 ); 176} 177 178class MxBiArOp_MI<string MN, MxType TYPE, 179 MxOperand MEMOpd, bits<4> CMD, MxEncMemOp DST_ENC> 180 : MxInst<(outs), (ins MEMOpd:$dst, TYPE.IOp:$opd), 181 MN#"."#TYPE.Prefix#"\t$opd, $dst", []> { 182 let Inst = (ascend 183 (descend 0b0000, CMD, 184 !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 185 DST_ENC.EA), 186 // Source (i.e. immediate value) encoding 187 MxEncAddrMode_i<"opd", TYPE.Size>.Supplement, 188 // Destination encoding 189 DST_ENC.Supplement 190 ); 191} 192} // mayLoad, mayStore 193} // Defs = [CCR] 194 195multiclass MxBiArOp_DF<string MN, SDNode NODE, bit isComm, 196 bits<4> CMD, bits<4> CMDI> { 197 198 foreach SZ = [8, 16, 32] in { 199 // op $mem, $reg 200 def NAME#SZ#"dk" : MxBiArOp_R_RM<MN, NODE, 201 !cast<MxType>("MxType"#SZ#"d"), 202 !cast<MxType>("MxType"#SZ).KOp, 203 !cast<MxType>("MxType"#SZ).KPat, 204 CMD, MxEncAddrMode_k<"opd">>; 205 206 def NAME#SZ#"dq" : MxBiArOp_R_RM<MN, NODE, 207 !cast<MxType>("MxType"#SZ#"d"), 208 !cast<MxType>("MxType"#SZ).QOp, 209 !cast<MxType>("MxType"#SZ).QPat, 210 CMD, MxEncAddrMode_q<"opd">>; 211 212 def NAME#SZ#"dp" : MxBiArOp_R_RM<MN, NODE, 213 !cast<MxType>("MxType"#SZ#"d"), 214 !cast<MxType>("MxType"#SZ).POp, 215 !cast<MxType>("MxType"#SZ).PPat, 216 CMD, MxEncAddrMode_p<"opd">>; 217 218 def NAME#SZ#"df" : MxBiArOp_R_RM<MN, NODE, 219 !cast<MxType>("MxType"#SZ#"d"), 220 !cast<MxType>("MxType"#SZ).FOp, 221 !cast<MxType>("MxType"#SZ).FPat, 222 CMD, MxEncAddrMode_f<"opd">>; 223 224 def NAME#SZ#"dj" : MxBiArOp_R_RM<MN, NODE, 225 !cast<MxType>("MxType"#SZ#"d"), 226 !cast<MxType>("MxType"#SZ).JOp, 227 !cast<MxType>("MxType"#SZ).JPat, 228 CMD, MxEncAddrMode_j<"opd">>; 229 // op $imm, $reg 230 def NAME#SZ#"di" : MxBiArOp_R_RI_xEA<MN, NODE, 231 !cast<MxType>("MxType"#SZ#"d"), 232 CMD>; 233 // op $reg, $mem 234 def NAME#SZ#"pd" : MxBiArOp_MR<MN, 235 !cast<MxType>("MxType"#SZ#"d"), 236 !cast<MxType>("MxType"#SZ).POp, 237 CMD, MxEncAddrMode_p<"dst">>; 238 239 def NAME#SZ#"fd" : MxBiArOp_MR<MN, 240 !cast<MxType>("MxType"#SZ#"d"), 241 !cast<MxType>("MxType"#SZ).FOp, 242 CMD, MxEncAddrMode_f<"dst">>; 243 244 def NAME#SZ#"jd" : MxBiArOp_MR<MN, 245 !cast<MxType>("MxType"#SZ#"d"), 246 !cast<MxType>("MxType"#SZ).JOp, 247 CMD, MxEncAddrMode_j<"dst">>; 248 // op $imm, $mem 249 def NAME#SZ#"pi" : MxBiArOp_MI<MN, 250 !cast<MxType>("MxType"#SZ), 251 !cast<MxType>("MxType"#SZ).POp, 252 CMDI, MxEncAddrMode_p<"dst">>; 253 254 def NAME#SZ#"fi" : MxBiArOp_MI<MN, 255 !cast<MxType>("MxType"#SZ), 256 !cast<MxType>("MxType"#SZ).FOp, 257 CMDI, MxEncAddrMode_f<"dst">>; 258 259 def NAME#SZ#"ji" : MxBiArOp_MI<MN, 260 !cast<MxType>("MxType"#SZ), 261 !cast<MxType>("MxType"#SZ).JOp, 262 CMDI, MxEncAddrMode_j<"dst">>; 263 // op $reg, $reg 264 let isCommutable = isComm in 265 def NAME#SZ#"dd" : MxBiArOp_R_RR_xEA<MN, NODE, 266 !cast<MxType>("MxType"#SZ#"d"), 267 !cast<MxType>("MxType"#SZ#"d"), 268 CMD>; 269 } // foreach SZ 270 271 foreach SZ = [16, 32] in 272 def NAME#SZ#"dr" : MxBiArOp_R_RR_xEA<MN, NODE, 273 !cast<MxType>("MxType"#SZ#"d"), 274 !cast<MxType>("MxType"#SZ#"r"), 275 CMD>; 276 277} // MxBiArOp_DF 278 279 280// These special snowflakes allowed to match address registers but since *A 281// operations do not produce CCR we should not match them against Mx nodes that 282// produce it. 283let Pattern = [(null_frag)] in 284multiclass MxBiArOp_AF<string MN, SDNode NODE, bits<4> CMD> { 285 286 def NAME#"32ak" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.KOp, MxType32.KPat, 287 CMD, MxEncAddrMode_k<"opd">>; 288 def NAME#"32aq" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.QOp, MxType32.QPat, 289 CMD, MxEncAddrMode_q<"opd">>; 290 def NAME#"32af" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.FOp, MxType32.FPat, 291 CMD, MxEncAddrMode_f<"opd">>; 292 def NAME#"32ap" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.POp, MxType32.PPat, 293 CMD, MxEncAddrMode_p<"opd">>; 294 def NAME#"32aj" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.JOp, MxType32.JPat, 295 CMD, MxEncAddrMode_j<"opd">>; 296 def NAME#"32ab" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.BOp, MxType32.BPat, 297 CMD, MxEncAddrMode_abs<"opd", true>>; 298 def NAME#"32ai" : MxBiArOp_R_RI_xEA<MN, NODE, MxType32a, CMD>; 299 300 def NAME#"32ar" : MxBiArOp_R_RR_xEA<MN, NODE, MxType32a, MxType32r, CMD>; 301 302} // MxBiArOp_AF 303 304// NOTE These naturally produce CCR 305 306//===----------------------------------------------------------------------===// 307// Add/Sub 308//===----------------------------------------------------------------------===// 309 310defm ADD : MxBiArOp_DF<"add", MxAdd, 1, 0xD, 0x6>; 311defm ADD : MxBiArOp_AF<"adda", MxAdd, 0xD>; 312defm SUB : MxBiArOp_DF<"sub", MxSub, 0, 0x9, 0x4>; 313defm SUB : MxBiArOp_AF<"suba", MxSub, 0x9>; 314 315// This pattern is used to enable the instruction selector to select ADD32ab 316// for global values that are allocated in thread-local storage, i.e.: 317// t8: i32 = ISD::ADD GLOBAL_OFFSET_TABLE, TargetGlobalTLSAddress:i32<ptr @myvar> 318// ====> 319// t8: i32,i8 = ADD32ab GLOBAL_OFFSET_TABLE, TargetGlobalTLSAddress:i32<ptr @myvar> 320def : Pat<(add MxARD32:$src, tglobaltlsaddr:$opd), (ADD32ab MxARD32:$src, MxAL32:$opd)>; 321 322let Uses = [CCR], Defs = [CCR] in { 323let Constraints = "$src = $dst" in { 324 325/// Encoding for Extended forms 326/// ------------------------------------------------------ 327/// F E D C | B A 9 | 8 | 7 6 | 5 4 | 3 | 2 1 0 328/// ------------------------------------------------------ 329/// x x x x | REG Rx | 1 | SIZE | 0 0 | M | REG Ry 330/// ------------------------------------------------------ 331/// Rx - destination 332/// Ry - source 333/// M - address mode switch 334 335// $reg, ccr <- $reg op $reg op ccr 336class MxBiArOp_R_RRX<string MN, SDNode NODE, MxType TYPE, bits<4> CMD> 337 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd), 338 MN#"."#TYPE.Prefix#"\t$opd, $dst", 339 [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd, CCR))]> { 340 let Inst = (descend CMD, 341 // Destination register 342 (operand "$dst", 3), 343 0b1, 344 // SIZE 345 !cond(!eq(TYPE.Size, 8): 0b00, 346 !eq(TYPE.Size, 16): 0b01, 347 !eq(TYPE.Size, 32): 0b10), 348 0b00, /*R/M*/0b0, 349 // Source register 350 (operand "$opd", 3) 351 ); 352} 353} // Constraints 354} // Uses, Defs 355 356multiclass MxBiArOp_RFF<string MN, SDNode NODE, bit isComm, bits<4> CMD> { 357 358let isCommutable = isComm in { 359 foreach SZ = [8, 16, 32] in 360 def NAME#SZ#"dd" : MxBiArOp_R_RRX<MN, NODE, !cast<MxType>("MxType"#SZ#"d"), CMD>; 361} // isComm 362 363} // MxBiArOp_RFF 364 365// NOTE These consume and produce CCR 366defm ADDX : MxBiArOp_RFF<"addx", MxAddX, 1, 0xD>; 367defm SUBX : MxBiArOp_RFF<"subx", MxSubX, 0, 0x9>; 368 369 370//===----------------------------------------------------------------------===// 371// And/Xor/Or 372//===----------------------------------------------------------------------===// 373 374defm AND : MxBiArOp_DF<"and", MxAnd, 1, 0xC, 0x2>; 375defm OR : MxBiArOp_DF<"or", MxOr, 1, 0x8, 0x0>; 376 377multiclass MxBiArOp_DF_EAd<string MN, SDNode NODE, bits<4> CMD, bits<4> CMDI> { 378 foreach SZ = [8, 16, 32] in { 379 let isCommutable = 1 in 380 def NAME#SZ#"dd" : MxBiArOp_R_RR_EAd<MN, NODE, 381 !cast<MxType>("MxType"#SZ#"d"), 382 CMD>; 383 384 def NAME#SZ#"di" : MxBiArOp_R_RI<MN, NODE, 385 !cast<MxType>("MxType"#SZ#"d"), 386 CMDI>; 387 } // foreach SZ 388} // MxBiArOp_DF_EAd 389 390defm XOR : MxBiArOp_DF_EAd<"eor", MxXor, 0xB, 0xA>; 391 392 393//===----------------------------------------------------------------------===// 394// CMP 395//===----------------------------------------------------------------------===// 396 397let Defs = [CCR] in { 398class MxCmp_RR<MxType LHS_TYPE, MxType RHS_TYPE = LHS_TYPE> 399 : MxInst<(outs), (ins LHS_TYPE.ROp:$lhs, RHS_TYPE.ROp:$rhs), 400 "cmp."#RHS_TYPE.Prefix#"\t$lhs, $rhs", 401 [(set CCR, (MxCmp LHS_TYPE.VT:$lhs, RHS_TYPE.VT:$rhs))]> { 402 let Inst = (descend 0b1011, 403 // REGISTER 404 (operand "$rhs", 3), 405 // OPMODE 406 !cast<MxOpModeEncoding>("MxOpMode"#RHS_TYPE.Size#"_"#RHS_TYPE.RLet#"_EA").Value, 407 // MODE without last bit 408 0b00, 409 // REGISTER prefixed by D/A bit 410 (operand "$lhs", 4) 411 ); 412} 413 414class MxCmp_RI<MxType TYPE> 415 : MxInst<(outs), (ins TYPE.IOp:$imm, TYPE.ROp:$reg), 416 "cmpi."#TYPE.Prefix#"\t$imm, $reg", 417 [(set CCR, (MxCmp TYPE.IPat:$imm, TYPE.VT:$reg))]> { 418 let Inst = (ascend 419 (descend 0b00001100, 420 !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 421 // The destination cannot be address register, so it's always 422 // the MODE for data register direct mode. 423 /*MODE*/0b000, 424 /*REGISTER*/(operand "$reg", 3)), 425 // Source (i.e. immediate value) encoding 426 MxEncAddrMode_i<"imm", TYPE.Size>.Supplement 427 ); 428} 429 430let mayLoad = 1 in { 431 432class MxCmp_MI<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat, 433 MxEncMemOp MEM_ENC> 434 : MxInst<(outs), (ins TYPE.IOp:$imm, MEMOpd:$mem), 435 "cmpi."#TYPE.Prefix#"\t$imm, $mem", 436 [(set CCR, (MxCmp TYPE.IPat:$imm, (load MEMPat:$mem)))]> { 437 let Inst = (ascend 438 (descend 0b00001100, 439 !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 440 MEM_ENC.EA), 441 // Source (i.e. immediate value) encoding 442 MxEncAddrMode_i<"imm", TYPE.Size>.Supplement, 443 // Destination (i.e. memory operand) encoding 444 MEM_ENC.Supplement 445 ); 446} 447 448// FIXME: What about abs.W? 449class MxCmp_BI<MxType TYPE> 450 : MxInst<(outs), (ins TYPE.IOp:$imm, MxAL32:$abs), 451 "cmpi."#TYPE.Prefix#"\t$imm, $abs", 452 [(set CCR, (MxCmp TYPE.IPat:$imm, 453 (load (i32 (MxWrapper tglobaladdr:$abs)))))]> { 454 defvar AbsEncoding = MxEncAddrMode_abs<"abs", true>; 455 let Inst = (ascend 456 (descend 0b00001100, 457 !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 458 AbsEncoding.EA), 459 // Source (i.e. immediate value) encoding 460 MxEncAddrMode_i<"imm", TYPE.Size>.Supplement, 461 // Destination (i.e. memory operand) encoding 462 AbsEncoding.Supplement 463 ); 464} 465 466class MxCmp_RM<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat, 467 MxEncMemOp MEM_ENC> 468 : MxInst<(outs), (ins TYPE.ROp:$reg, MEMOpd:$mem), 469 "cmp."#TYPE.Prefix#"\t$mem, $reg", 470 [(set CCR, (MxCmp (load MEMPat:$mem), TYPE.ROp:$reg))]> { 471 let Inst = (ascend 472 (descend 0b1011, 473 // REGISTER 474 (operand "$reg", 3), 475 // OPMODE 476 !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_d_EA").Value, 477 MEM_ENC.EA), 478 MEM_ENC.Supplement 479 ); 480} 481} // let mayLoad = 1 482 483} // let Defs = [CCR] 484 485multiclass MMxCmp_RM<MxType TYPE> { 486 def NAME#TYPE.KOp.Letter : MxCmp_RM<TYPE, TYPE.KOp, TYPE.KPat, MxEncAddrMode_k<"mem">>; 487 def NAME#TYPE.QOp.Letter : MxCmp_RM<TYPE, TYPE.QOp, TYPE.QPat, MxEncAddrMode_q<"mem">>; 488 def NAME#TYPE.POp.Letter : MxCmp_RM<TYPE, TYPE.POp, TYPE.PPat, MxEncAddrMode_p<"mem">>; 489 def NAME#TYPE.FOp.Letter : MxCmp_RM<TYPE, TYPE.FOp, TYPE.FPat, MxEncAddrMode_f<"mem">>; 490 def NAME#TYPE.JOp.Letter : MxCmp_RM<TYPE, TYPE.JOp, TYPE.JPat, MxEncAddrMode_j<"mem">>; 491} 492 493multiclass MMxCmp_MI<MxType TYPE> { 494 def NAME#TYPE.KOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.KOp, TYPE.KPat, 495 MxEncAddrMode_k<"mem">>; 496 def NAME#TYPE.QOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.QOp, TYPE.QPat, 497 MxEncAddrMode_q<"mem">>; 498 def NAME#TYPE.POp.Letter#"i" : MxCmp_MI<TYPE, TYPE.POp, TYPE.PPat, 499 MxEncAddrMode_p<"mem">>; 500 def NAME#TYPE.FOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.FOp, TYPE.FPat, 501 MxEncAddrMode_f<"mem">>; 502 def NAME#TYPE.JOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.JOp, TYPE.JPat, 503 MxEncAddrMode_j<"mem">>; 504} 505 506foreach S = [8, 16, 32] in { 507 def CMP#S#di : MxCmp_RI<!cast<MxType>("MxType"#S#"d")>; 508 def CMP#S#bi : MxCmp_BI<!cast<MxType>("MxType"#S#"d")>; 509} // foreach 510 511def CMP8dd : MxCmp_RR<MxType8d>; 512foreach S = [16, 32] in { 513 def CMP#S#dr : MxCmp_RR<!cast<MxType>("MxType"#S#"r"), 514 !cast<MxType>("MxType"#S#"d")>; 515} 516 517// cmp mem, Dn 518defm CMP8d : MMxCmp_RM<MxType8d>; 519defm CMP16d : MMxCmp_RM<MxType16d>; 520defm CMP32d : MMxCmp_RM<MxType32d>; 521 522// cmp #imm, mem 523defm CMP8 : MMxCmp_MI<MxType8d>; 524defm CMP16 : MMxCmp_MI<MxType16d>; 525defm CMP32 : MMxCmp_MI<MxType32d>; 526 527 528//===----------------------------------------------------------------------===// 529// EXT 530//===----------------------------------------------------------------------===// 531 532/// --------------------------------------------------- 533/// F E D C B A 9 | 8 7 6 | 5 4 3 | 2 1 0 534/// --------------------------------------------------- 535/// 0 1 0 0 1 0 0 | OPMODE | 0 0 0 | REG 536/// --------------------------------------------------- 537let Defs = [CCR] in 538let Constraints = "$src = $dst" in 539class MxExt<MxType TO, MxType FROM> 540 : MxInst<(outs TO.ROp:$dst), (ins TO.ROp:$src), 541 "ext."#TO.Prefix#"\t$src", []> { 542 let Inst = (descend 0b0100100, 543 // OPMODE 544 !cond( 545 // byte -> word 546 !and(!eq(FROM.Size, 8), !eq(TO.Size, 16)): 0b010, 547 // word -> long 548 !and(!eq(FROM.Size, 16), !eq(TO.Size, 32)): 0b011, 549 // byte -> long 550 !and(!eq(FROM.Size, 8), !eq(TO.Size, 32)): 0b111 551 ), 552 0b000, 553 // REGISTER 554 (operand "$src", 3) 555 ); 556} 557 558def EXT16 : MxExt<MxType16d, MxType8d>; 559def EXT32 : MxExt<MxType32d, MxType16d>; 560 561def : Pat<(sext_inreg i16:$src, i8), (EXT16 $src)>; 562def : Pat<(sext_inreg i32:$src, i16), (EXT32 $src)>; 563def : Pat<(sext_inreg i32:$src, i8), 564 (EXT32 (MOVXd32d16 (EXT16 (EXTRACT_SUBREG $src, MxSubRegIndex16Lo))))>; 565 566 567//===----------------------------------------------------------------------===// 568// DIV/MUL 569//===----------------------------------------------------------------------===// 570 571/// Word operation: 572/// ---------------------------------------------------- 573/// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0 574/// ---------------------------------------------------- 575/// | | | EFFECTIVE ADDRESS 576/// x x x x | REG | OP MODE | MODE | REG 577/// ---------------------------------------------------- 578let Defs = [CCR] in { 579let Constraints = "$src = $dst" in { 580// $dreg <- $dreg op $dreg 581class MxDiMuOp_DD<string MN, bits<4> CMD, bit SIGNED = false, 582 MxOperand DST, MxOperand OPD> 583 : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", []> { 584 let Inst = (descend CMD, 585 // REGISTER 586 (operand "$dst", 3), 587 !if(SIGNED, 0b111, 0b011), 588 /*MODE*/0b000, /*REGISTER*/(operand "$opd", 3) 589 ); 590} 591 592// $dreg <- $dreg op $dreg 593class MxDiMuOp_DD_Long<string MN, bits<10> CMD, bit SIGNED = false> 594 : MxInst<(outs MxDRD32:$dst), (ins MxDRD32:$src, MxDRD32:$opd), MN#"\t$opd, $dst", []> { 595 let Inst = (ascend 596 (descend CMD, 597 /*MODE*/0b000, /*REGISTER*/(operand "$opd", 3)), 598 (descend 0b0, 599 // REGISTER 600 (operand "$dst", 3), 601 !if(SIGNED, 0b1, 0b0), 602 /*SIZE*/0b0, 0b0000000, 603 // Dr REGISTER 604 0b000) 605 ); 606} 607 608// $reg <- $reg op $imm 609class MxDiMuOp_DI<string MN, bits<4> CMD, bit SIGNED = false, 610 MxOperand DST, MxOperand OPD> 611 : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", []> { 612 // FIXME: Support immediates with different widths. 613 defvar ImmEnc = MxEncAddrMode_i<"opd", 16>; 614 let Inst = (ascend 615 (descend CMD, 616 // REGISTER 617 (operand "$dst", 3), 618 !if(SIGNED, 0b111, 0b011), ImmEnc.EA), 619 ImmEnc.Supplement 620 ); 621} 622} // let Constraints 623} // Defs = [CCR] 624 625multiclass MxDiMuOp<string MN, bits<4> CMD, bit isComm = 0> { 626 let isCommutable = isComm in { 627 def "S"#NAME#"d32d16" : MxDiMuOp_DD<MN#"s", CMD, /*SIGNED*/true, MxDRD32, MxDRD16>; 628 def "U"#NAME#"d32d16" : MxDiMuOp_DD<MN#"u", CMD, /*SIGNED*/false, MxDRD32, MxDRD16>; 629 } 630 631 def "S"#NAME#"d32i16" : MxDiMuOp_DI<MN#"s", CMD, /*SIGNED*/true, MxDRD32, Mxi16imm>; 632 def "U"#NAME#"d32i16" : MxDiMuOp_DI<MN#"u", CMD, /*SIGNED*/false, MxDRD32, Mxi16imm>; 633} 634 635defm DIV : MxDiMuOp<"div", 0x8>; 636 637def SDIVd32d32 : MxDiMuOp_DD_Long<"divs.l", 0x131, /*SIGNED*/true>; 638def UDIVd32d32 : MxDiMuOp_DD_Long<"divu.l", 0x131, /*SIGNED*/false>; 639 640// This is used to cast immediates to 16-bits for operations which don't 641// support smaller immediate sizes. 642def as_i16imm : SDNodeXForm<imm, [{ 643 return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i16); 644}]>; 645 646// RR i8 647def : Pat<(sdiv i8:$dst, i8:$opd), 648 (EXTRACT_SUBREG 649 (SDIVd32d16 (MOVSXd32d8 $dst), (MOVSXd16d8 $opd)), 650 MxSubRegIndex8Lo)>; 651 652def : Pat<(udiv i8:$dst, i8:$opd), 653 (EXTRACT_SUBREG 654 (UDIVd32d16 (MOVZXd32d8 $dst), (MOVZXd16d8 $opd)), 655 MxSubRegIndex8Lo)>; 656 657def : Pat<(srem i8:$dst, i8:$opd), 658 (EXTRACT_SUBREG 659 (ASR32di (ASR32di (SDIVd32d16 (MOVSXd32d8 $dst), (MOVSXd16d8 $opd)), 8), 8), 660 MxSubRegIndex8Lo)>; 661 662def : Pat<(urem i8:$dst, i8:$opd), 663 (EXTRACT_SUBREG 664 (LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d8 $dst), (MOVZXd16d8 $opd)), 8), 8), 665 MxSubRegIndex8Lo)>; 666 667// RR i16 668def : Pat<(sdiv i16:$dst, i16:$opd), 669 (EXTRACT_SUBREG 670 (SDIVd32d16 (MOVSXd32d16 $dst), $opd), 671 MxSubRegIndex16Lo)>; 672 673def : Pat<(udiv i16:$dst, i16:$opd), 674 (EXTRACT_SUBREG 675 (UDIVd32d16 (MOVZXd32d16 $dst), $opd), 676 MxSubRegIndex16Lo)>; 677 678def : Pat<(srem i16:$dst, i16:$opd), 679 (EXTRACT_SUBREG 680 (ASR32di (ASR32di (SDIVd32d16 (MOVSXd32d16 $dst), $opd), 8), 8), 681 MxSubRegIndex16Lo)>; 682 683def : Pat<(urem i16:$dst, i16:$opd), 684 (EXTRACT_SUBREG 685 (LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d16 $dst), $opd), 8), 8), 686 MxSubRegIndex16Lo)>; 687 688 689// RR i32 690def : Pat<(sdiv i32:$dst, i32:$opd), (SDIVd32d32 $dst, $opd)>; 691 692def : Pat<(udiv i32:$dst, i32:$opd), (UDIVd32d32 $dst, $opd)>; 693 694 695// RI i8 696def : Pat<(sdiv i8:$dst, MximmSExt8:$opd), 697 (EXTRACT_SUBREG 698 (SDIVd32i16 (MOVSXd32d8 $dst), (as_i16imm $opd)), 699 MxSubRegIndex8Lo)>; 700 701def : Pat<(udiv i8:$dst, MximmSExt8:$opd), 702 (EXTRACT_SUBREG 703 (UDIVd32i16 (MOVZXd32d8 $dst), (as_i16imm $opd)), 704 MxSubRegIndex8Lo)>; 705 706def : Pat<(srem i8:$dst, MximmSExt8:$opd), 707 (EXTRACT_SUBREG 708 (ASR32di (ASR32di (SDIVd32i16 (MOVSXd32d8 $dst), (as_i16imm $opd)), 8), 8), 709 MxSubRegIndex8Lo)>; 710 711def : Pat<(urem i8:$dst, MximmSExt8:$opd), 712 (EXTRACT_SUBREG 713 (LSR32di (LSR32di (UDIVd32i16 (MOVZXd32d8 $dst), (as_i16imm $opd)), 8), 8), 714 MxSubRegIndex8Lo)>; 715 716// RI i16 717def : Pat<(sdiv i16:$dst, MximmSExt16:$opd), 718 (EXTRACT_SUBREG 719 (SDIVd32i16 (MOVSXd32d16 $dst), imm:$opd), 720 MxSubRegIndex16Lo)>; 721 722def : Pat<(udiv i16:$dst, MximmSExt16:$opd), 723 (EXTRACT_SUBREG 724 (UDIVd32i16 (MOVZXd32d16 $dst), imm:$opd), 725 MxSubRegIndex16Lo)>; 726 727def : Pat<(srem i16:$dst, MximmSExt16:$opd), 728 (EXTRACT_SUBREG 729 (ASR32di (ASR32di (SDIVd32i16 (MOVSXd32d16 $dst), imm:$opd), 8), 8), 730 MxSubRegIndex16Lo)>; 731 732def : Pat<(urem i16:$dst, MximmSExt16:$opd), 733 (EXTRACT_SUBREG 734 (LSR32di (LSR32di (UDIVd32i16 (MOVZXd32d16 $dst), imm:$opd), 8), 8), 735 MxSubRegIndex16Lo)>; 736 737 738defm MUL : MxDiMuOp<"mul", 0xC, 1>; 739 740def SMULd32d32 : MxDiMuOp_DD_Long<"muls.l", 0x130, /*SIGNED*/true>; 741def UMULd32d32 : MxDiMuOp_DD_Long<"mulu.l", 0x130, /*SIGNED*/false>; 742 743// RR 744def : Pat<(mul i16:$dst, i16:$opd), 745 (EXTRACT_SUBREG 746 (SMULd32d16 (MOVXd32d16 $dst), $opd), 747 MxSubRegIndex16Lo)>; 748 749def : Pat<(mulhs i16:$dst, i16:$opd), 750 (EXTRACT_SUBREG 751 (ASR32di (ASR32di (SMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8), 752 MxSubRegIndex16Lo)>; 753 754def : Pat<(mulhu i16:$dst, i16:$opd), 755 (EXTRACT_SUBREG 756 (LSR32di (LSR32di (UMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8), 757 MxSubRegIndex16Lo)>; 758 759def : Pat<(mul i32:$dst, i32:$opd), (SMULd32d32 $dst, $opd)>; 760 761 762// RI 763def : Pat<(mul i16:$dst, MximmSExt16:$opd), 764 (EXTRACT_SUBREG 765 (SMULd32i16 (MOVXd32d16 $dst), imm:$opd), 766 MxSubRegIndex16Lo)>; 767 768def : Pat<(mulhs i16:$dst, MximmSExt16:$opd), 769 (EXTRACT_SUBREG 770 (ASR32di (ASR32di (SMULd32i16 (MOVXd32d16 $dst), imm:$opd), 8), 8), 771 MxSubRegIndex16Lo)>; 772 773def : Pat<(mulhu i16:$dst, MximmSExt16:$opd), 774 (EXTRACT_SUBREG 775 (LSR32di (LSR32di (UMULd32i16 (MOVXd32d16 $dst), imm:$opd), 8), 8), 776 MxSubRegIndex16Lo)>; 777 778 779//===----------------------------------------------------------------------===// 780// NEG/NEGX 781//===----------------------------------------------------------------------===// 782 783/// ------------+------------+------+---------+--------- 784/// F E D C | B A 9 8 | 7 6 | 5 4 3 | 2 1 0 785/// ------------+------------+------+------------------- 786/// | | | EFFECTIVE ADDRESS 787/// 0 1 0 0 | x x x x | SIZE | MODE | REG 788/// ------------+------------+------+---------+--------- 789let Defs = [CCR] in { 790let Constraints = "$src = $dst" in { 791 792class MxNeg_D<MxType TYPE> 793 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src), 794 "neg."#TYPE.Prefix#"\t$dst", 795 [(set TYPE.VT:$dst, (ineg TYPE.VT:$src))]> { 796 let Inst = (descend 0b01000100, 797 /*SIZE*/!cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 798 //MODE without last bit 799 0b00, 800 //REGISTER prefixed by D/A bit 801 (operand "$dst", 4) 802 ); 803} 804 805let Uses = [CCR] in { 806class MxNegX_D<MxType TYPE> 807 : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src), 808 "negx."#TYPE.Prefix#"\t$dst", 809 [(set TYPE.VT:$dst, (MxSubX 0, TYPE.VT:$src, CCR))]> { 810 let Inst = (descend 0b01000000, 811 /*SIZE*/!cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 812 //MODE without last bit 813 0b00, 814 //REGISTER prefixed by D/A bit 815 (operand "$dst", 4) 816 ); 817} 818} 819 820} // let Constraints 821} // let Defs = [CCR] 822 823foreach S = [8, 16, 32] in { 824 def NEG#S#d : MxNeg_D<!cast<MxType>("MxType"#S#"d")>; 825 def NEGX#S#d : MxNegX_D<!cast<MxType>("MxType"#S#"d")>; 826} 827 828def : Pat<(MxSub 0, i8 :$src), (NEG8d MxDRD8 :$src)>; 829def : Pat<(MxSub 0, i16:$src), (NEG16d MxDRD16:$src)>; 830def : Pat<(MxSub 0, i32:$src), (NEG32d MxDRD32:$src)>; 831// SExt of i1 values. 832// Although we specify `ZeroOrOneBooleanContent` for boolean content, 833// we're still adding an AND here as we don't know the origin of the i1 value. 834def : Pat<(sext_inreg i8:$src, i1), (NEG8d (AND8di MxDRD8:$src, 1))>; 835def : Pat<(sext_inreg i16:$src, i1), (NEG16d (AND16di MxDRD16:$src, 1))>; 836def : Pat<(sext_inreg i32:$src, i1), (NEG32d (AND32di MxDRD32:$src, 1))>; 837 838//===----------------------------------------------------------------------===// 839// no-CCR Patterns 840//===----------------------------------------------------------------------===// 841 842/// Basically the reason for this stuff is that add and addc share the same 843/// operand types constraints for whatever reasons and I had to define a common 844/// MxAdd and MxSub instructions that produce CCR and then pattern-map add and addc 845/// to it. 846/// NOTE On the other hand I see no reason why I cannot just drop explicit CCR 847/// result. Anyway works for now, hopefully I will better understand how this stuff 848/// is designed later 849foreach N = ["add", "addc"] in { 850 851 // add reg, reg 852 def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd), 853 (ADD8dd MxDRD8 :$src, MxDRD8 :$opd)>; 854 def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd), 855 (ADD16dr MxXRD16:$src, MxDRD16:$opd)>; 856 def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd), 857 (ADD32dr MxXRD32:$src, MxDRD32:$opd)>; 858 859 // add (An), reg 860 def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)), 861 (ADD8dj MxDRD8:$src, MxType8.JOp:$opd)>; 862 def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)), 863 (ADD16dj MxDRD16:$src, MxType16.JOp:$opd)>; 864 def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)), 865 (ADD32dj MxDRD32:$src, MxType32.JOp:$opd)>; 866 867 // add (i,An), reg 868 def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)), 869 (ADD8dp MxDRD8:$src, MxType8.POp:$opd)>; 870 def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)), 871 (ADD16dp MxDRD16:$src, MxType16.POp:$opd)>; 872 def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)), 873 (ADD32dp MxDRD32:$src, MxType32.POp:$opd)>; 874 875 // add (i,An,Xn), reg 876 def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)), 877 (ADD8df MxDRD8:$src, MxType8.FOp:$opd)>; 878 def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)), 879 (ADD16df MxDRD16:$src, MxType16.FOp:$opd)>; 880 def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)), 881 (ADD32df MxDRD32:$src, MxType32.FOp:$opd)>; 882 883 // add reg, imm 884 def : Pat<(!cast<SDNode>(N) i8: $src, MximmSExt8:$opd), 885 (ADD8di MxDRD8 :$src, imm:$opd)>; 886 def : Pat<(!cast<SDNode>(N) i16:$src, MximmSExt16:$opd), 887 (ADD16di MxDRD16:$src, imm:$opd)>; 888 889 // LEAp is more complex and thus will be selected over normal ADD32ri but it cannot 890 // be used with data registers, here by adding complexity to a simple ADD32ri insts 891 // we make sure it will be selected over LEAp 892 let AddedComplexity = 15 in { 893 def : Pat<(!cast<SDNode>(N) i32:$src, MximmSExt32:$opd), 894 (ADD32di MxDRD32:$src, imm:$opd)>; 895 } // AddedComplexity = 15 896 897 // add imm, (An) 898 def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd), 899 MxType8.JPat:$dst), 900 (ADD8ji MxType8.JOp:$dst, imm:$opd)>; 901 def : Pat<(store (!cast<SDNode>(N) (load MxType16.JPat:$dst), MxType16.IPat:$opd), 902 MxType16.JPat:$dst), 903 (ADD16ji MxType16.JOp:$dst, imm:$opd)>; 904 def : Pat<(store (!cast<SDNode>(N) (load MxType32.JPat:$dst), MxType32.IPat:$opd), 905 MxType32.JPat:$dst), 906 (ADD32ji MxType32.JOp:$dst, imm:$opd)>; 907 908} // foreach add, addc 909 910def : Pat<(adde i8 :$src, i8 :$opd), (ADDX8dd MxDRD8 :$src, MxDRD8 :$opd)>; 911def : Pat<(adde i16:$src, i16:$opd), (ADDX16dd MxDRD16:$src, MxDRD16:$opd)>; 912def : Pat<(adde i32:$src, i32:$opd), (ADDX32dd MxDRD32:$src, MxDRD32:$opd)>; 913 914 915 916foreach N = ["sub", "subc"] in { 917 918 // sub reg, reg 919 def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd), 920 (SUB8dd MxDRD8 :$src, MxDRD8 :$opd)>; 921 def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd), 922 (SUB16dd MxDRD16:$src, MxDRD16:$opd)>; 923 def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd), 924 (SUB32dd MxDRD32:$src, MxDRD32:$opd)>; 925 926 927 // sub (An), reg 928 def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)), 929 (SUB8dj MxDRD8:$src, MxType8.JOp:$opd)>; 930 def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)), 931 (SUB16dj MxDRD16:$src, MxType16.JOp:$opd)>; 932 def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)), 933 (SUB32dj MxDRD32:$src, MxType32.JOp:$opd)>; 934 935 // sub (i,An), reg 936 def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)), 937 (SUB8dp MxDRD8:$src, MxType8.POp:$opd)>; 938 def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)), 939 (SUB16dp MxDRD16:$src, MxType16.POp:$opd)>; 940 def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)), 941 (SUB32dp MxDRD32:$src, MxType32.POp:$opd)>; 942 943 // sub (i,An,Xn), reg 944 def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)), 945 (SUB8df MxDRD8:$src, MxType8.FOp:$opd)>; 946 def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)), 947 (SUB16df MxDRD16:$src, MxType16.FOp:$opd)>; 948 def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)), 949 (SUB32df MxDRD32:$src, MxType32.FOp:$opd)>; 950 951 // sub reg, imm 952 def : Pat<(!cast<SDNode>(N) i8 :$src, MximmSExt8 :$opd), 953 (SUB8di MxDRD8 :$src, imm:$opd)>; 954 def : Pat<(!cast<SDNode>(N) i16:$src, MximmSExt16:$opd), 955 (SUB16di MxDRD16:$src, imm:$opd)>; 956 def : Pat<(!cast<SDNode>(N) i32:$src, MximmSExt32:$opd), 957 (SUB32di MxDRD32:$src, imm:$opd)>; 958 959 // sub imm, (An) 960 def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd), 961 MxType8.JPat:$dst), 962 (SUB8ji MxType8.JOp:$dst, imm:$opd)>; 963 def : Pat<(store (!cast<SDNode>(N) (load MxType16.JPat:$dst), MxType16.IPat:$opd), 964 MxType16.JPat:$dst), 965 (SUB16ji MxType16.JOp:$dst, imm:$opd)>; 966 def : Pat<(store (!cast<SDNode>(N) (load MxType32.JPat:$dst), MxType32.IPat:$opd), 967 MxType32.JPat:$dst), 968 (SUB32ji MxType32.JOp:$dst, imm:$opd)>; 969 970} // foreach sub, subx 971 972def : Pat<(sube i8 :$src, i8 :$opd), (SUBX8dd MxDRD8 :$src, MxDRD8 :$opd)>; 973def : Pat<(sube i16:$src, i16:$opd), (SUBX16dd MxDRD16:$src, MxDRD16:$opd)>; 974def : Pat<(sube i32:$src, i32:$opd), (SUBX32dd MxDRD32:$src, MxDRD32:$opd)>; 975 976multiclass BitwisePat<string INST, SDNode OP> { 977 // op reg, reg 978 def : Pat<(OP i8 :$src, i8 :$opd), 979 (!cast<MxInst>(INST#"8dd") MxDRD8 :$src, MxDRD8 :$opd)>; 980 def : Pat<(OP i16:$src, i16:$opd), 981 (!cast<MxInst>(INST#"16dd") MxDRD16:$src, MxDRD16:$opd)>; 982 def : Pat<(OP i32:$src, i32:$opd), 983 (!cast<MxInst>(INST#"32dd") MxDRD32:$src, MxDRD32:$opd)>; 984 // op reg, imm 985 def : Pat<(OP i8: $src, MximmSExt8 :$opd), 986 (!cast<MxInst>(INST#"8di") MxDRD8 :$src, imm:$opd)>; 987 def : Pat<(OP i16:$src, MximmSExt16:$opd), 988 (!cast<MxInst>(INST#"16di") MxDRD16:$src, imm:$opd)>; 989 def : Pat<(OP i32:$src, MximmSExt32:$opd), 990 (!cast<MxInst>(INST#"32di") MxDRD32:$src, imm:$opd)>; 991} 992 993defm : BitwisePat<"AND", and>; 994defm : BitwisePat<"OR", or>; 995defm : BitwisePat<"XOR", xor>; 996 997//===----------------------------------------------------------------------===// 998// Floating point arithmetic instruction 999//===----------------------------------------------------------------------===// 1000 1001let Defs = [FPS] in 1002class MxFArithBase_FF<dag outs, dag ins, string asm, string rounding, 1003 list<dag> patterns> 1004 : MxInst<outs, ins, asm, patterns> { 1005 let Uses = !if(!eq(rounding, ""), [FPC], []); 1006 1007 let Predicates = !if(!eq(rounding, ""), [AtLeastM68881], [AtLeastM68040]); 1008} 1009 1010class MxFPOpModeSelector<string rounding, bits<7> single, bits<7> double, 1011 bits<7> extended> { 1012 bits<7> Mode = !cond(!eq(rounding, "s"): single, 1013 !eq(rounding, "d"): double, 1014 !eq(rounding, ""): extended); 1015} 1016 1017//===----------------------------------------------------------------------===// 1018// Unary floating point instruction 1019//===----------------------------------------------------------------------===// 1020 1021class MxFUnary_FF<MxOpBundle Opnd, string rounding, 1022 string mnemonic, bits<7> opmode> 1023 : MxFArithBase_FF<(outs Opnd.Op:$dst), (ins Opnd.Op:$src), 1024 "f"#rounding#mnemonic#".x\t$src, $dst", rounding, [(null_frag)]> { 1025 let Inst = (ascend 1026 (descend 0b1111, 1027 /*COPROCESSOR ID*/0b001, 1028 0b000, 1029 /*MODE+REGISTER*/0b000000), 1030 (descend 0b0, /* R/M */ 0b0, 0b0, 1031 /*SOURCE SPECIFIER*/ 1032 (operand "$src", 3), 1033 /*DESTINATION*/ 1034 (operand "$dst", 3), 1035 /*OPMODE*/ 1036 opmode) 1037 ); 1038} 1039 1040multiclass MxFUnaryOp<string mnemonic, bits<7> single, bits<7> double, 1041 bits<7> extended> { 1042 foreach rounding = ["", "s", "d"] in { 1043 defvar opmode = MxFPOpModeSelector<rounding, single, double, extended>.Mode; 1044 1045 def F # !toupper(rounding) # !substr(NAME, 1) # "80fp_fp" 1046 : MxFUnary_FF<MxOp80AddrMode_fpr, rounding, mnemonic, opmode>; 1047 1048 let isCodeGenOnly = 1 in 1049 foreach size = [32, 64] in 1050 def F # !toupper(rounding) # !substr(NAME, 1) # size # "fp_fp" 1051 : MxFUnary_FF<!cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr"), 1052 rounding, mnemonic, opmode>; 1053 } 1054} 1055 1056defm FABS : MxFUnaryOp<"abs", 0b1011000, 0b1011100, 0b0011000>; 1057defm FNEG : MxFUnaryOp<"neg", 0b1011010, 0b1011110, 0b0011010>; 1058 1059//===----------------------------------------------------------------------===// 1060// Binary floating point instruction 1061//===----------------------------------------------------------------------===// 1062 1063let Constraints = "$src = $dst" in 1064class MxFBinary_FF<MxOpBundle Opnd, string rounding, 1065 string mnemonic, bits<7> opmode> 1066 : MxFArithBase_FF<(outs Opnd.Op:$dst), (ins Opnd.Op:$src, Opnd.Op:$opd), 1067 "f"#rounding#mnemonic#".x\t$opd, $dst", rounding, [(null_frag)]> { 1068 let Inst = (ascend 1069 (descend 0b1111, 1070 /*COPROCESSOR ID*/0b001, 1071 0b000, 1072 /*MODE+REGISTER*/0b000000), 1073 (descend 0b0, /* R/M */ 0b0, 0b0, 1074 /*SOURCE SPECIFIER*/ 1075 (operand "$opd", 3), 1076 /*DESTINATION*/ 1077 (operand "$dst", 3), 1078 /*OPMODE*/ 1079 opmode) 1080 ); 1081} 1082 1083multiclass MxFBinaryOp<string mnemonic, bits<7> single, bits<7> double, 1084 bits<7> extended> { 1085 foreach rounding = ["", "s", "d"] in { 1086 defvar opmode = MxFPOpModeSelector<rounding, single, double, extended>.Mode; 1087 1088 def F # !toupper(rounding) # !substr(NAME, 1) # "80fp_fp" 1089 : MxFBinary_FF<MxOp80AddrMode_fpr, rounding, mnemonic, opmode>; 1090 1091 let isCodeGenOnly = 1 in 1092 foreach size = [32, 64] in 1093 def F # !toupper(rounding) # !substr(NAME, 1) # size # "fp_fp" 1094 : MxFBinary_FF<!cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr"), 1095 rounding, mnemonic, opmode>; 1096 } 1097} 1098 1099defm FADD : MxFBinaryOp<"add", 0b1100010, 0b1100110, 0b0100010>; 1100defm FSUB : MxFBinaryOp<"sub", 0b1101000, 0b1101100, 0b0101000>; 1101defm FMUL : MxFBinaryOp<"mul", 0b1100011, 0b1100111, 0b0100011>; 1102defm FDIV : MxFBinaryOp<"div", 0b1100000, 0b1100100, 0b0100000>; 1103