1fe6060f1SDimitry Andric//===-- M68kInstrArithmetic.td - Integer Arith Instrs ------*- tablegen -*-===// 2fe6060f1SDimitry Andric// 3fe6060f1SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4fe6060f1SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 5fe6060f1SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6fe6060f1SDimitry Andric// 7fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 8fe6060f1SDimitry Andric/// 9fe6060f1SDimitry Andric/// \file 10fe6060f1SDimitry Andric/// This file describes the integer arithmetic instructions in the M68k 11fe6060f1SDimitry Andric/// architecture. Here is the current status of the file: 12fe6060f1SDimitry Andric/// 13fe6060f1SDimitry Andric/// Machine: 14fe6060f1SDimitry Andric/// 15fe6060f1SDimitry Andric/// ADD [~] ADDA [~] ADDI [~] ADDQ [ ] ADDX [~] 16fe6060f1SDimitry Andric/// CLR [ ] CMP [~] CMPA [~] CMPI [~] CMPM [ ] 17fe6060f1SDimitry Andric/// CMP2 [ ] DIVS/DIVU [~] DIVSL/DIVUL [ ] EXT [~] EXTB [ ] 18*0fca6ea1SDimitry Andric/// MULS/MULU [~] NEG [~] NEGX [~] NOT [~] SUB [~] 19*0fca6ea1SDimitry Andric/// SUBA [~] SUBI [~] SUBQ [ ] SUBX [~] 20fe6060f1SDimitry Andric/// 21fe6060f1SDimitry Andric/// Map: 22fe6060f1SDimitry Andric/// 23fe6060f1SDimitry Andric/// [ ] - was not touched at all 24fe6060f1SDimitry Andric/// [!] - requires extarnal stuff implemented 25fe6060f1SDimitry Andric/// [~] - functional implementation 26fe6060f1SDimitry Andric/// [X] - complete implementation 27fe6060f1SDimitry Andric/// 28fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 29fe6060f1SDimitry Andric 30fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 3181ad6265SDimitry Andric// OPMODE Encoding 3281ad6265SDimitry Andric//===----------------------------------------------------------------------===// 3381ad6265SDimitry Andricclass MxOpModeEncoding<bits<3> encoding> { 3481ad6265SDimitry Andric bits<3> Value = encoding; 3581ad6265SDimitry Andric} 3681ad6265SDimitry Andric 3781ad6265SDimitry Andric// op EA, Dn 3881ad6265SDimitry Andricdef MxOpMode8_d_EA : MxOpModeEncoding<0b000>; 3981ad6265SDimitry Andricdef MxOpMode16_d_EA : MxOpModeEncoding<0b001>; 4081ad6265SDimitry Andricdef MxOpMode32_d_EA : MxOpModeEncoding<0b010>; 4181ad6265SDimitry Andric 4281ad6265SDimitry Andric// op Dn, EA 4381ad6265SDimitry Andricdef MxOpMode8_EA_d : MxOpModeEncoding<0b100>; 4481ad6265SDimitry Andricdef MxOpMode16_EA_d : MxOpModeEncoding<0b101>; 4581ad6265SDimitry Andricdef MxOpMode32_EA_d : MxOpModeEncoding<0b110>; 4681ad6265SDimitry Andric 4781ad6265SDimitry Andric// op EA, An 4881ad6265SDimitry Andricdef MxOpMode16_a_EA : MxOpModeEncoding<0b011>; 4981ad6265SDimitry Andricdef MxOpMode32_a_EA : MxOpModeEncoding<0b111>; 5081ad6265SDimitry Andric 5181ad6265SDimitry Andric 5281ad6265SDimitry Andric//===----------------------------------------------------------------------===// 53fe6060f1SDimitry Andric// Encoding 54fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 55fe6060f1SDimitry Andric 5681ad6265SDimitry Andriclet Defs = [CCR] in { 5781ad6265SDimitry Andriclet Constraints = "$src = $dst" in { 5881ad6265SDimitry Andric 59fe6060f1SDimitry Andric/// Encoding for Normal forms 60fe6060f1SDimitry Andric/// ---------------------------------------------------- 61fe6060f1SDimitry Andric/// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0 62fe6060f1SDimitry Andric/// ---------------------------------------------------- 63fe6060f1SDimitry Andric/// | | | EFFECTIVE ADDRESS 64fe6060f1SDimitry Andric/// x x x x | REG | OP MODE | MODE | REG 65fe6060f1SDimitry Andric/// ---------------------------------------------------- 66fe6060f1SDimitry Andric 6781ad6265SDimitry Andric// $reg, $ccr <- $reg op $reg 6881ad6265SDimitry Andricclass MxBiArOp_R_RR_xEA<string MN, SDNode NODE, MxType DST_TYPE, MxType SRC_TYPE, 6981ad6265SDimitry Andric bits<4> CMD> 7081ad6265SDimitry Andric : MxInst<(outs DST_TYPE.ROp:$dst), (ins DST_TYPE.ROp:$src, SRC_TYPE.ROp:$opd), 7181ad6265SDimitry Andric MN#"."#DST_TYPE.Prefix#"\t$opd, $dst", 7281ad6265SDimitry Andric [(set DST_TYPE.VT:$dst, CCR, (NODE DST_TYPE.VT:$src, SRC_TYPE.VT:$opd))]> { 7381ad6265SDimitry Andric let Inst = (descend 7481ad6265SDimitry Andric CMD, (operand "$dst", 3), 7581ad6265SDimitry Andric !cast<MxOpModeEncoding>("MxOpMode"#DST_TYPE.Size#"_"#DST_TYPE.RLet#"_EA").Value, 7681ad6265SDimitry Andric !cond( 7781ad6265SDimitry Andric !eq(SRC_TYPE.RLet, "r") : (descend 0b00, (operand "$opd", 4)), 7881ad6265SDimitry Andric !eq(SRC_TYPE.RLet, "d") : (descend 0b000, (operand "$opd", 3)) 7981ad6265SDimitry Andric ) 8081ad6265SDimitry Andric ); 8181ad6265SDimitry Andric} 8281ad6265SDimitry Andric 8381ad6265SDimitry Andric/// This Op is similar to the one above except it uses reversed opmode, some 8481ad6265SDimitry Andric/// commands(e.g. eor) do not support dEA or rEA modes and require EAd for 8581ad6265SDimitry Andric/// register only operations. 8681ad6265SDimitry Andric/// NOTE when using dd commands it is irrelevant which opmode to use(as it seems) 8781ad6265SDimitry Andric/// but some opcodes support address register and some do not which creates this 8881ad6265SDimitry Andric/// mess. 8981ad6265SDimitry Andricclass MxBiArOp_R_RR_EAd<string MN, SDNode NODE, MxType TYPE, bits<4> CMD> 9081ad6265SDimitry Andric : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd), 9181ad6265SDimitry Andric MN#"."#TYPE.Prefix#"\t$opd, $dst", 9281ad6265SDimitry Andric [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd))]> { 9381ad6265SDimitry Andric let Inst = (descend 9481ad6265SDimitry Andric CMD, (operand "$opd", 3), 9581ad6265SDimitry Andric !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_EA_"#TYPE.RLet).Value, 9681ad6265SDimitry Andric /*Destination can only be a data register*/ 9781ad6265SDimitry Andric /*MODE*/0b000, 9881ad6265SDimitry Andric /*REGISTER*/(operand "$dst", 3)); 9981ad6265SDimitry Andric} 10081ad6265SDimitry Andric 10181ad6265SDimitry Andriclet mayLoad = 1 in 10281ad6265SDimitry Andricclass MxBiArOp_R_RM<string MN, SDNode NODE, MxType TYPE, MxOperand OPD, ComplexPattern PAT, 10381ad6265SDimitry Andric bits<4> CMD, MxEncMemOp SRC_ENC> 10481ad6265SDimitry Andric : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, OPD:$opd), 10581ad6265SDimitry Andric MN#"."#TYPE.Prefix#"\t$opd, $dst", 10681ad6265SDimitry Andric [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, (TYPE.Load PAT:$opd)))]> { 10781ad6265SDimitry Andric let Inst = (ascend 10881ad6265SDimitry Andric (descend CMD, (operand "$dst", 3), 10981ad6265SDimitry Andric !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_"#TYPE.RLet#"_EA").Value, 11081ad6265SDimitry Andric SRC_ENC.EA), 11181ad6265SDimitry Andric SRC_ENC.Supplement 11281ad6265SDimitry Andric ); 11381ad6265SDimitry Andric} 114fe6060f1SDimitry Andric 115fe6060f1SDimitry Andric/// Encoding for Immediate forms 116fe6060f1SDimitry Andric/// --------------------------------------------------- 117fe6060f1SDimitry Andric/// F E D C B A 9 8 | 7 6 | 5 4 3 | 2 1 0 118fe6060f1SDimitry Andric/// --------------------------------------------------- 119fe6060f1SDimitry Andric/// | | EFFECTIVE ADDRESS 120fe6060f1SDimitry Andric/// x x x x x x x x | SIZE | MODE | REG 121fe6060f1SDimitry Andric/// --------------------------------------------------- 122fe6060f1SDimitry Andric/// 16-BIT WORD DATA | 8-BIT BYTE DATA 123fe6060f1SDimitry Andric/// --------------------------------------------------- 124fe6060f1SDimitry Andric/// 32-BIT LONG DATA 125fe6060f1SDimitry Andric/// --------------------------------------------------- 126fe6060f1SDimitry Andric/// NOTE It is used to store an immediate to memory, imm-to-reg are handled with 127fe6060f1SDimitry Andric/// normal version 128fe6060f1SDimitry Andric 129fe6060f1SDimitry Andric// $reg <- $reg op $imm 13081ad6265SDimitry Andricclass MxBiArOp_R_RI_xEA<string MN, SDNode NODE, MxType TYPE, bits<4> CMD> 131fe6060f1SDimitry Andric : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd), 132fe6060f1SDimitry Andric MN#"."#TYPE.Prefix#"\t$opd, $dst", 13381ad6265SDimitry Andric [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))]> { 13481ad6265SDimitry Andric let Inst = (ascend 13581ad6265SDimitry Andric (descend CMD, (operand "$dst", 3), 13681ad6265SDimitry Andric !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_"#TYPE.RLet#"_EA").Value, 13781ad6265SDimitry Andric MxEncAddrMode_i<"opd", TYPE.Size>.EA), 13881ad6265SDimitry Andric MxEncAddrMode_i<"opd", TYPE.Size>.Supplement 13981ad6265SDimitry Andric ); 14081ad6265SDimitry Andric} 141fe6060f1SDimitry Andric 142fe6060f1SDimitry Andric// Again, there are two ways to write an immediate to Dn register either dEA 14381ad6265SDimitry Andric// opmode or using *I encoding, and again some instructions also support address 144fe6060f1SDimitry Andric// registers some do not. 14581ad6265SDimitry Andricclass MxBiArOp_R_RI<string MN, SDNode NODE, MxType TYPE, bits<4> CMD> 146fe6060f1SDimitry Andric : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.IOp:$opd), 147fe6060f1SDimitry Andric MN#"i."#TYPE.Prefix#"\t$opd, $dst", 14881ad6265SDimitry Andric [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.IPat:$opd))]> { 14981ad6265SDimitry Andric let Inst = (ascend 15081ad6265SDimitry Andric (descend 0b0000, CMD, 15106c3fb27SDimitry Andric !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 15281ad6265SDimitry Andric // The destination cannot be address register, so it's always 15381ad6265SDimitry Andric // the MODE for data register direct mode. 15481ad6265SDimitry Andric /*MODE*/0b000, 15581ad6265SDimitry Andric /*REGISTER*/(operand "$dst", 3)), 15681ad6265SDimitry Andric // Source (i.e. immediate value) encoding 15781ad6265SDimitry Andric MxEncAddrMode_i<"opd", TYPE.Size>.Supplement 15881ad6265SDimitry Andric ); 15981ad6265SDimitry Andric} 160fe6060f1SDimitry Andric} // Constraints 161fe6060f1SDimitry Andric 162fe6060f1SDimitry Andriclet mayLoad = 1, mayStore = 1 in { 163fe6060f1SDimitry Andric 164fe6060f1SDimitry Andric// FIXME MxBiArOp_FMR/FMI cannot consume CCR from MxAdd/MxSub which leads for 165fe6060f1SDimitry Andric// MxAdd to survive the match and subsequent mismatch. 16681ad6265SDimitry Andricclass MxBiArOp_MR<string MN, MxType TYPE, 16781ad6265SDimitry Andric MxOperand MEMOpd, bits<4> CMD, MxEncMemOp DST_ENC> 168fe6060f1SDimitry Andric : MxInst<(outs), (ins MEMOpd:$dst, TYPE.ROp:$opd), 16981ad6265SDimitry Andric MN#"."#TYPE.Prefix#"\t$opd, $dst", []> { 17081ad6265SDimitry Andric let Inst = (ascend 17181ad6265SDimitry Andric (descend CMD, (operand "$opd", 3), 17281ad6265SDimitry Andric !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_EA_"#TYPE.RLet).Value, 17381ad6265SDimitry Andric DST_ENC.EA), 17481ad6265SDimitry Andric DST_ENC.Supplement 17581ad6265SDimitry Andric ); 17681ad6265SDimitry Andric} 177fe6060f1SDimitry Andric 17881ad6265SDimitry Andricclass MxBiArOp_MI<string MN, MxType TYPE, 17981ad6265SDimitry Andric MxOperand MEMOpd, bits<4> CMD, MxEncMemOp DST_ENC> 180fe6060f1SDimitry Andric : MxInst<(outs), (ins MEMOpd:$dst, TYPE.IOp:$opd), 18181ad6265SDimitry Andric MN#"."#TYPE.Prefix#"\t$opd, $dst", []> { 18281ad6265SDimitry Andric let Inst = (ascend 18381ad6265SDimitry Andric (descend 0b0000, CMD, 18406c3fb27SDimitry Andric !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 18581ad6265SDimitry Andric DST_ENC.EA), 18681ad6265SDimitry Andric // Source (i.e. immediate value) encoding 18781ad6265SDimitry Andric MxEncAddrMode_i<"opd", TYPE.Size>.Supplement, 18881ad6265SDimitry Andric // Destination encoding 18981ad6265SDimitry Andric DST_ENC.Supplement 19081ad6265SDimitry Andric ); 19181ad6265SDimitry Andric} 192fe6060f1SDimitry Andric} // mayLoad, mayStore 193fe6060f1SDimitry Andric} // Defs = [CCR] 194fe6060f1SDimitry Andric 195fe6060f1SDimitry Andricmulticlass MxBiArOp_DF<string MN, SDNode NODE, bit isComm, 196fe6060f1SDimitry Andric bits<4> CMD, bits<4> CMDI> { 197fe6060f1SDimitry Andric 19881ad6265SDimitry Andric foreach SZ = [8, 16, 32] in { 199fe6060f1SDimitry Andric // op $mem, $reg 20081ad6265SDimitry Andric def NAME#SZ#"dk" : MxBiArOp_R_RM<MN, NODE, 20181ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 20281ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).KOp, 20381ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).KPat, 20481ad6265SDimitry Andric CMD, MxEncAddrMode_k<"opd">>; 205fe6060f1SDimitry Andric 20681ad6265SDimitry Andric def NAME#SZ#"dq" : MxBiArOp_R_RM<MN, NODE, 20781ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 20881ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).QOp, 20981ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).QPat, 21081ad6265SDimitry Andric CMD, MxEncAddrMode_q<"opd">>; 211fe6060f1SDimitry Andric 21281ad6265SDimitry Andric def NAME#SZ#"dp" : MxBiArOp_R_RM<MN, NODE, 21381ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 21481ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).POp, 21581ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).PPat, 21681ad6265SDimitry Andric CMD, MxEncAddrMode_p<"opd">>; 217fe6060f1SDimitry Andric 21881ad6265SDimitry Andric def NAME#SZ#"df" : MxBiArOp_R_RM<MN, NODE, 21981ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 22081ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).FOp, 22181ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).FPat, 22281ad6265SDimitry Andric CMD, MxEncAddrMode_f<"opd">>; 223fe6060f1SDimitry Andric 22481ad6265SDimitry Andric def NAME#SZ#"dj" : MxBiArOp_R_RM<MN, NODE, 22581ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 22681ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).JOp, 22781ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).JPat, 22881ad6265SDimitry Andric CMD, MxEncAddrMode_j<"opd">>; 229fe6060f1SDimitry Andric // op $imm, $reg 23081ad6265SDimitry Andric def NAME#SZ#"di" : MxBiArOp_R_RI_xEA<MN, NODE, 23181ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 23281ad6265SDimitry Andric CMD>; 233fe6060f1SDimitry Andric // op $reg, $mem 23481ad6265SDimitry Andric def NAME#SZ#"pd" : MxBiArOp_MR<MN, 23581ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 23681ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).POp, 23781ad6265SDimitry Andric CMD, MxEncAddrMode_p<"dst">>; 238fe6060f1SDimitry Andric 23981ad6265SDimitry Andric def NAME#SZ#"fd" : MxBiArOp_MR<MN, 24081ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 24181ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).FOp, 24281ad6265SDimitry Andric CMD, MxEncAddrMode_f<"dst">>; 243fe6060f1SDimitry Andric 24481ad6265SDimitry Andric def NAME#SZ#"jd" : MxBiArOp_MR<MN, 24581ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 24681ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).JOp, 24781ad6265SDimitry Andric CMD, MxEncAddrMode_j<"dst">>; 248fe6060f1SDimitry Andric // op $imm, $mem 24981ad6265SDimitry Andric def NAME#SZ#"pi" : MxBiArOp_MI<MN, 25081ad6265SDimitry Andric !cast<MxType>("MxType"#SZ), 25181ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).POp, 25281ad6265SDimitry Andric CMDI, MxEncAddrMode_p<"dst">>; 253fe6060f1SDimitry Andric 25481ad6265SDimitry Andric def NAME#SZ#"fi" : MxBiArOp_MI<MN, 25581ad6265SDimitry Andric !cast<MxType>("MxType"#SZ), 25681ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).FOp, 25781ad6265SDimitry Andric CMDI, MxEncAddrMode_f<"dst">>; 258fe6060f1SDimitry Andric 25981ad6265SDimitry Andric def NAME#SZ#"ji" : MxBiArOp_MI<MN, 26081ad6265SDimitry Andric !cast<MxType>("MxType"#SZ), 26181ad6265SDimitry Andric !cast<MxType>("MxType"#SZ).JOp, 26281ad6265SDimitry Andric CMDI, MxEncAddrMode_j<"dst">>; 26381ad6265SDimitry Andric // op $reg, $reg 26481ad6265SDimitry Andric let isCommutable = isComm in 26581ad6265SDimitry Andric def NAME#SZ#"dd" : MxBiArOp_R_RR_xEA<MN, NODE, 26681ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 26781ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 26881ad6265SDimitry Andric CMD>; 26981ad6265SDimitry Andric } // foreach SZ 270fe6060f1SDimitry Andric 27181ad6265SDimitry Andric foreach SZ = [16, 32] in 27281ad6265SDimitry Andric def NAME#SZ#"dr" : MxBiArOp_R_RR_xEA<MN, NODE, 27381ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 27481ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"r"), 27581ad6265SDimitry Andric CMD>; 276fe6060f1SDimitry Andric 277fe6060f1SDimitry Andric} // MxBiArOp_DF 278fe6060f1SDimitry Andric 279fe6060f1SDimitry Andric 280fe6060f1SDimitry Andric// These special snowflakes allowed to match address registers but since *A 281fe6060f1SDimitry Andric// operations do not produce CCR we should not match them against Mx nodes that 282fe6060f1SDimitry Andric// produce it. 283fe6060f1SDimitry Andriclet Pattern = [(null_frag)] in 28404eeddc0SDimitry Andricmulticlass MxBiArOp_AF<string MN, SDNode NODE, bits<4> CMD> { 285fe6060f1SDimitry Andric 28681ad6265SDimitry Andric def NAME#"32ak" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.KOp, MxType32.KPat, 28781ad6265SDimitry Andric CMD, MxEncAddrMode_k<"opd">>; 28881ad6265SDimitry Andric def NAME#"32aq" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.QOp, MxType32.QPat, 28981ad6265SDimitry Andric CMD, MxEncAddrMode_q<"opd">>; 29081ad6265SDimitry Andric def NAME#"32af" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.FOp, MxType32.FPat, 29181ad6265SDimitry Andric CMD, MxEncAddrMode_f<"opd">>; 29281ad6265SDimitry Andric def NAME#"32ap" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.POp, MxType32.PPat, 29381ad6265SDimitry Andric CMD, MxEncAddrMode_p<"opd">>; 29481ad6265SDimitry Andric def NAME#"32aj" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.JOp, MxType32.JPat, 29581ad6265SDimitry Andric CMD, MxEncAddrMode_j<"opd">>; 29606c3fb27SDimitry Andric def NAME#"32ab" : MxBiArOp_R_RM<MN, NODE, MxType32a, MxType32.BOp, MxType32.BPat, 29706c3fb27SDimitry Andric CMD, MxEncAddrMode_abs<"opd", true>>; 29881ad6265SDimitry Andric def NAME#"32ai" : MxBiArOp_R_RI_xEA<MN, NODE, MxType32a, CMD>; 299fe6060f1SDimitry Andric 30081ad6265SDimitry Andric def NAME#"32ar" : MxBiArOp_R_RR_xEA<MN, NODE, MxType32a, MxType32r, CMD>; 301fe6060f1SDimitry Andric 302fe6060f1SDimitry Andric} // MxBiArOp_AF 303fe6060f1SDimitry Andric 304fe6060f1SDimitry Andric// NOTE These naturally produce CCR 305fe6060f1SDimitry Andric 30681ad6265SDimitry Andric//===----------------------------------------------------------------------===// 30781ad6265SDimitry Andric// Add/Sub 30881ad6265SDimitry Andric//===----------------------------------------------------------------------===// 30981ad6265SDimitry Andric 310fe6060f1SDimitry Andricdefm ADD : MxBiArOp_DF<"add", MxAdd, 1, 0xD, 0x6>; 31104eeddc0SDimitry Andricdefm ADD : MxBiArOp_AF<"adda", MxAdd, 0xD>; 312fe6060f1SDimitry Andricdefm SUB : MxBiArOp_DF<"sub", MxSub, 0, 0x9, 0x4>; 31304eeddc0SDimitry Andricdefm SUB : MxBiArOp_AF<"suba", MxSub, 0x9>; 314fe6060f1SDimitry Andric 31506c3fb27SDimitry Andric// This pattern is used to enable the instruction selector to select ADD32ab 31606c3fb27SDimitry Andric// for global values that are allocated in thread-local storage, i.e.: 31706c3fb27SDimitry Andric// t8: i32 = ISD::ADD GLOBAL_OFFSET_TABLE, TargetGlobalTLSAddress:i32<ptr @myvar> 31806c3fb27SDimitry Andric// ====> 31906c3fb27SDimitry Andric// t8: i32,i8 = ADD32ab GLOBAL_OFFSET_TABLE, TargetGlobalTLSAddress:i32<ptr @myvar> 32006c3fb27SDimitry Andricdef : Pat<(add MxARD32:$src, tglobaltlsaddr:$opd), (ADD32ab MxARD32:$src, MxAL32:$opd)>; 321fe6060f1SDimitry Andric 322fe6060f1SDimitry Andriclet Uses = [CCR], Defs = [CCR] in { 323fe6060f1SDimitry Andriclet Constraints = "$src = $dst" in { 324fe6060f1SDimitry Andric 32581ad6265SDimitry Andric/// Encoding for Extended forms 32681ad6265SDimitry Andric/// ------------------------------------------------------ 32781ad6265SDimitry Andric/// F E D C | B A 9 | 8 | 7 6 | 5 4 | 3 | 2 1 0 32881ad6265SDimitry Andric/// ------------------------------------------------------ 32981ad6265SDimitry Andric/// x x x x | REG Rx | 1 | SIZE | 0 0 | M | REG Ry 33081ad6265SDimitry Andric/// ------------------------------------------------------ 33181ad6265SDimitry Andric/// Rx - destination 33281ad6265SDimitry Andric/// Ry - source 33381ad6265SDimitry Andric/// M - address mode switch 33481ad6265SDimitry Andric 335fe6060f1SDimitry Andric// $reg, ccr <- $reg op $reg op ccr 33681ad6265SDimitry Andricclass MxBiArOp_R_RRX<string MN, SDNode NODE, MxType TYPE, bits<4> CMD> 337fe6060f1SDimitry Andric : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src, TYPE.ROp:$opd), 338fe6060f1SDimitry Andric MN#"."#TYPE.Prefix#"\t$opd, $dst", 33981ad6265SDimitry Andric [(set TYPE.VT:$dst, CCR, (NODE TYPE.VT:$src, TYPE.VT:$opd, CCR))]> { 34081ad6265SDimitry Andric let Inst = (descend CMD, 34181ad6265SDimitry Andric // Destination register 34281ad6265SDimitry Andric (operand "$dst", 3), 34381ad6265SDimitry Andric 0b1, 34481ad6265SDimitry Andric // SIZE 34581ad6265SDimitry Andric !cond(!eq(TYPE.Size, 8): 0b00, 34681ad6265SDimitry Andric !eq(TYPE.Size, 16): 0b01, 34781ad6265SDimitry Andric !eq(TYPE.Size, 32): 0b10), 34881ad6265SDimitry Andric 0b00, /*R/M*/0b0, 34981ad6265SDimitry Andric // Source register 35081ad6265SDimitry Andric (operand "$opd", 3) 35181ad6265SDimitry Andric ); 35281ad6265SDimitry Andric} 353fe6060f1SDimitry Andric} // Constraints 354fe6060f1SDimitry Andric} // Uses, Defs 355fe6060f1SDimitry Andric 356fe6060f1SDimitry Andricmulticlass MxBiArOp_RFF<string MN, SDNode NODE, bit isComm, bits<4> CMD> { 357fe6060f1SDimitry Andric 358fe6060f1SDimitry Andriclet isCommutable = isComm in { 35981ad6265SDimitry Andric foreach SZ = [8, 16, 32] in 36081ad6265SDimitry Andric def NAME#SZ#"dd" : MxBiArOp_R_RRX<MN, NODE, !cast<MxType>("MxType"#SZ#"d"), CMD>; 361fe6060f1SDimitry Andric} // isComm 362fe6060f1SDimitry Andric 363fe6060f1SDimitry Andric} // MxBiArOp_RFF 364fe6060f1SDimitry Andric 365fe6060f1SDimitry Andric// NOTE These consume and produce CCR 366fe6060f1SDimitry Andricdefm ADDX : MxBiArOp_RFF<"addx", MxAddX, 1, 0xD>; 367fe6060f1SDimitry Andricdefm SUBX : MxBiArOp_RFF<"subx", MxSubX, 0, 0x9>; 368fe6060f1SDimitry Andric 369fe6060f1SDimitry Andric 370fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 371fe6060f1SDimitry Andric// And/Xor/Or 372fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 373fe6060f1SDimitry Andric 374fe6060f1SDimitry Andricdefm AND : MxBiArOp_DF<"and", MxAnd, 1, 0xC, 0x2>; 375fe6060f1SDimitry Andricdefm OR : MxBiArOp_DF<"or", MxOr, 1, 0x8, 0x0>; 376fe6060f1SDimitry Andric 377fe6060f1SDimitry Andricmulticlass MxBiArOp_DF_EAd<string MN, SDNode NODE, bits<4> CMD, bits<4> CMDI> { 37881ad6265SDimitry Andric foreach SZ = [8, 16, 32] in { 37981ad6265SDimitry Andric let isCommutable = 1 in 38081ad6265SDimitry Andric def NAME#SZ#"dd" : MxBiArOp_R_RR_EAd<MN, NODE, 38181ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 38281ad6265SDimitry Andric CMD>; 383fe6060f1SDimitry Andric 38481ad6265SDimitry Andric def NAME#SZ#"di" : MxBiArOp_R_RI<MN, NODE, 38581ad6265SDimitry Andric !cast<MxType>("MxType"#SZ#"d"), 38681ad6265SDimitry Andric CMDI>; 38781ad6265SDimitry Andric } // foreach SZ 388fe6060f1SDimitry Andric} // MxBiArOp_DF_EAd 389fe6060f1SDimitry Andric 390fe6060f1SDimitry Andricdefm XOR : MxBiArOp_DF_EAd<"eor", MxXor, 0xB, 0xA>; 391fe6060f1SDimitry Andric 392fe6060f1SDimitry Andric 393fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 394fe6060f1SDimitry Andric// CMP 395fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 396fe6060f1SDimitry Andric 397fe6060f1SDimitry Andriclet Defs = [CCR] in { 39881ad6265SDimitry Andricclass MxCmp_RR<MxType LHS_TYPE, MxType RHS_TYPE = LHS_TYPE> 399349cc55cSDimitry Andric : MxInst<(outs), (ins LHS_TYPE.ROp:$lhs, RHS_TYPE.ROp:$rhs), 400349cc55cSDimitry Andric "cmp."#RHS_TYPE.Prefix#"\t$lhs, $rhs", 40181ad6265SDimitry Andric [(set CCR, (MxCmp LHS_TYPE.VT:$lhs, RHS_TYPE.VT:$rhs))]> { 40281ad6265SDimitry Andric let Inst = (descend 0b1011, 40381ad6265SDimitry Andric // REGISTER 40481ad6265SDimitry Andric (operand "$rhs", 3), 40581ad6265SDimitry Andric // OPMODE 40681ad6265SDimitry Andric !cast<MxOpModeEncoding>("MxOpMode"#RHS_TYPE.Size#"_"#RHS_TYPE.RLet#"_EA").Value, 40781ad6265SDimitry Andric // MODE without last bit 40881ad6265SDimitry Andric 0b00, 40981ad6265SDimitry Andric // REGISTER prefixed by D/A bit 41081ad6265SDimitry Andric (operand "$lhs", 4) 41181ad6265SDimitry Andric ); 41281ad6265SDimitry Andric} 413fe6060f1SDimitry Andric 414fe6060f1SDimitry Andricclass MxCmp_RI<MxType TYPE> 415fe6060f1SDimitry Andric : MxInst<(outs), (ins TYPE.IOp:$imm, TYPE.ROp:$reg), 416fe6060f1SDimitry Andric "cmpi."#TYPE.Prefix#"\t$imm, $reg", 41781ad6265SDimitry Andric [(set CCR, (MxCmp TYPE.IPat:$imm, TYPE.VT:$reg))]> { 41881ad6265SDimitry Andric let Inst = (ascend 41981ad6265SDimitry Andric (descend 0b00001100, 42006c3fb27SDimitry Andric !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 42181ad6265SDimitry Andric // The destination cannot be address register, so it's always 42281ad6265SDimitry Andric // the MODE for data register direct mode. 42381ad6265SDimitry Andric /*MODE*/0b000, 42481ad6265SDimitry Andric /*REGISTER*/(operand "$reg", 3)), 42581ad6265SDimitry Andric // Source (i.e. immediate value) encoding 42681ad6265SDimitry Andric MxEncAddrMode_i<"imm", TYPE.Size>.Supplement 42781ad6265SDimitry Andric ); 42881ad6265SDimitry Andric} 429fe6060f1SDimitry Andric 430fe6060f1SDimitry Andriclet mayLoad = 1 in { 431fe6060f1SDimitry Andric 432fe6060f1SDimitry Andricclass MxCmp_MI<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat, 43381ad6265SDimitry Andric MxEncMemOp MEM_ENC> 434fe6060f1SDimitry Andric : MxInst<(outs), (ins TYPE.IOp:$imm, MEMOpd:$mem), 435fe6060f1SDimitry Andric "cmpi."#TYPE.Prefix#"\t$imm, $mem", 43681ad6265SDimitry Andric [(set CCR, (MxCmp TYPE.IPat:$imm, (load MEMPat:$mem)))]> { 43781ad6265SDimitry Andric let Inst = (ascend 43881ad6265SDimitry Andric (descend 0b00001100, 43906c3fb27SDimitry Andric !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 44081ad6265SDimitry Andric MEM_ENC.EA), 44181ad6265SDimitry Andric // Source (i.e. immediate value) encoding 44281ad6265SDimitry Andric MxEncAddrMode_i<"imm", TYPE.Size>.Supplement, 44381ad6265SDimitry Andric // Destination (i.e. memory operand) encoding 44481ad6265SDimitry Andric MEM_ENC.Supplement 44581ad6265SDimitry Andric ); 44681ad6265SDimitry Andric} 447fe6060f1SDimitry Andric 44881ad6265SDimitry Andric// FIXME: What about abs.W? 449fe6060f1SDimitry Andricclass MxCmp_BI<MxType TYPE> 450fe6060f1SDimitry Andric : MxInst<(outs), (ins TYPE.IOp:$imm, MxAL32:$abs), 451fe6060f1SDimitry Andric "cmpi."#TYPE.Prefix#"\t$imm, $abs", 452fe6060f1SDimitry Andric [(set CCR, (MxCmp TYPE.IPat:$imm, 45381ad6265SDimitry Andric (load (i32 (MxWrapper tglobaladdr:$abs)))))]> { 45481ad6265SDimitry Andric defvar AbsEncoding = MxEncAddrMode_abs<"abs", true>; 45581ad6265SDimitry Andric let Inst = (ascend 45681ad6265SDimitry Andric (descend 0b00001100, 45706c3fb27SDimitry Andric !cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 45881ad6265SDimitry Andric AbsEncoding.EA), 45981ad6265SDimitry Andric // Source (i.e. immediate value) encoding 46081ad6265SDimitry Andric MxEncAddrMode_i<"imm", TYPE.Size>.Supplement, 46181ad6265SDimitry Andric // Destination (i.e. memory operand) encoding 46281ad6265SDimitry Andric AbsEncoding.Supplement 46381ad6265SDimitry Andric ); 46481ad6265SDimitry Andric} 465fe6060f1SDimitry Andric 466fe6060f1SDimitry Andricclass MxCmp_RM<MxType TYPE, MxOperand MEMOpd, ComplexPattern MEMPat, 46781ad6265SDimitry Andric MxEncMemOp MEM_ENC> 468fe6060f1SDimitry Andric : MxInst<(outs), (ins TYPE.ROp:$reg, MEMOpd:$mem), 469fe6060f1SDimitry Andric "cmp."#TYPE.Prefix#"\t$mem, $reg", 47081ad6265SDimitry Andric [(set CCR, (MxCmp (load MEMPat:$mem), TYPE.ROp:$reg))]> { 47181ad6265SDimitry Andric let Inst = (ascend 47281ad6265SDimitry Andric (descend 0b1011, 47381ad6265SDimitry Andric // REGISTER 47481ad6265SDimitry Andric (operand "$reg", 3), 47581ad6265SDimitry Andric // OPMODE 47681ad6265SDimitry Andric !cast<MxOpModeEncoding>("MxOpMode"#TYPE.Size#"_d_EA").Value, 47781ad6265SDimitry Andric MEM_ENC.EA), 47881ad6265SDimitry Andric MEM_ENC.Supplement 47981ad6265SDimitry Andric ); 48081ad6265SDimitry Andric} 481fe6060f1SDimitry Andric} // let mayLoad = 1 482fe6060f1SDimitry Andric 483fe6060f1SDimitry Andric} // let Defs = [CCR] 484fe6060f1SDimitry Andric 485fe6060f1SDimitry Andricmulticlass MMxCmp_RM<MxType TYPE> { 48681ad6265SDimitry Andric def NAME#TYPE.KOp.Letter : MxCmp_RM<TYPE, TYPE.KOp, TYPE.KPat, MxEncAddrMode_k<"mem">>; 48781ad6265SDimitry Andric def NAME#TYPE.QOp.Letter : MxCmp_RM<TYPE, TYPE.QOp, TYPE.QPat, MxEncAddrMode_q<"mem">>; 48881ad6265SDimitry Andric def NAME#TYPE.POp.Letter : MxCmp_RM<TYPE, TYPE.POp, TYPE.PPat, MxEncAddrMode_p<"mem">>; 48981ad6265SDimitry Andric def NAME#TYPE.FOp.Letter : MxCmp_RM<TYPE, TYPE.FOp, TYPE.FPat, MxEncAddrMode_f<"mem">>; 49081ad6265SDimitry Andric def NAME#TYPE.JOp.Letter : MxCmp_RM<TYPE, TYPE.JOp, TYPE.JPat, MxEncAddrMode_j<"mem">>; 491fe6060f1SDimitry Andric} 492fe6060f1SDimitry Andric 493fe6060f1SDimitry Andricmulticlass MMxCmp_MI<MxType TYPE> { 49481ad6265SDimitry Andric def NAME#TYPE.KOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.KOp, TYPE.KPat, 49581ad6265SDimitry Andric MxEncAddrMode_k<"mem">>; 49681ad6265SDimitry Andric def NAME#TYPE.QOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.QOp, TYPE.QPat, 49781ad6265SDimitry Andric MxEncAddrMode_q<"mem">>; 49881ad6265SDimitry Andric def NAME#TYPE.POp.Letter#"i" : MxCmp_MI<TYPE, TYPE.POp, TYPE.PPat, 49981ad6265SDimitry Andric MxEncAddrMode_p<"mem">>; 50081ad6265SDimitry Andric def NAME#TYPE.FOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.FOp, TYPE.FPat, 50181ad6265SDimitry Andric MxEncAddrMode_f<"mem">>; 50281ad6265SDimitry Andric def NAME#TYPE.JOp.Letter#"i" : MxCmp_MI<TYPE, TYPE.JOp, TYPE.JPat, 50381ad6265SDimitry Andric MxEncAddrMode_j<"mem">>; 504fe6060f1SDimitry Andric} 505fe6060f1SDimitry Andric 506fe6060f1SDimitry Andricforeach S = [8, 16, 32] in { 507fe6060f1SDimitry Andric def CMP#S#di : MxCmp_RI<!cast<MxType>("MxType"#S#"d")>; 508fe6060f1SDimitry Andric def CMP#S#bi : MxCmp_BI<!cast<MxType>("MxType"#S#"d")>; 509fe6060f1SDimitry Andric} // foreach 510fe6060f1SDimitry Andric 511349cc55cSDimitry Andricdef CMP8dd : MxCmp_RR<MxType8d>; 512349cc55cSDimitry Andricforeach S = [16, 32] in { 513349cc55cSDimitry Andric def CMP#S#dr : MxCmp_RR<!cast<MxType>("MxType"#S#"r"), 514349cc55cSDimitry Andric !cast<MxType>("MxType"#S#"d")>; 515349cc55cSDimitry Andric} 516349cc55cSDimitry Andric 517fe6060f1SDimitry Andric// cmp mem, Dn 518fe6060f1SDimitry Andricdefm CMP8d : MMxCmp_RM<MxType8d>; 519fe6060f1SDimitry Andricdefm CMP16d : MMxCmp_RM<MxType16d>; 520fe6060f1SDimitry Andricdefm CMP32d : MMxCmp_RM<MxType32d>; 521fe6060f1SDimitry Andric 522fe6060f1SDimitry Andric// cmp #imm, mem 523fe6060f1SDimitry Andricdefm CMP8 : MMxCmp_MI<MxType8d>; 524fe6060f1SDimitry Andricdefm CMP16 : MMxCmp_MI<MxType16d>; 525fe6060f1SDimitry Andricdefm CMP32 : MMxCmp_MI<MxType32d>; 526fe6060f1SDimitry Andric 527fe6060f1SDimitry Andric 528fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 529fe6060f1SDimitry Andric// EXT 530fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 531fe6060f1SDimitry Andric 532fe6060f1SDimitry Andric/// --------------------------------------------------- 533fe6060f1SDimitry Andric/// F E D C B A 9 | 8 7 6 | 5 4 3 | 2 1 0 534fe6060f1SDimitry Andric/// --------------------------------------------------- 535fe6060f1SDimitry Andric/// 0 1 0 0 1 0 0 | OPMODE | 0 0 0 | REG 536fe6060f1SDimitry Andric/// --------------------------------------------------- 537fe6060f1SDimitry Andriclet Defs = [CCR] in 538fe6060f1SDimitry Andriclet Constraints = "$src = $dst" in 539fe6060f1SDimitry Andricclass MxExt<MxType TO, MxType FROM> 540fe6060f1SDimitry Andric : MxInst<(outs TO.ROp:$dst), (ins TO.ROp:$src), 54181ad6265SDimitry Andric "ext."#TO.Prefix#"\t$src", []> { 54281ad6265SDimitry Andric let Inst = (descend 0b0100100, 54381ad6265SDimitry Andric // OPMODE 54481ad6265SDimitry Andric !cond( 54581ad6265SDimitry Andric // byte -> word 54681ad6265SDimitry Andric !and(!eq(FROM.Size, 8), !eq(TO.Size, 16)): 0b010, 54781ad6265SDimitry Andric // word -> long 54881ad6265SDimitry Andric !and(!eq(FROM.Size, 16), !eq(TO.Size, 32)): 0b011, 54981ad6265SDimitry Andric // byte -> long 55081ad6265SDimitry Andric !and(!eq(FROM.Size, 8), !eq(TO.Size, 32)): 0b111 55181ad6265SDimitry Andric ), 55281ad6265SDimitry Andric 0b000, 55381ad6265SDimitry Andric // REGISTER 55481ad6265SDimitry Andric (operand "$src", 3) 55581ad6265SDimitry Andric ); 55681ad6265SDimitry Andric} 557fe6060f1SDimitry Andric 558fe6060f1SDimitry Andricdef EXT16 : MxExt<MxType16d, MxType8d>; 559fe6060f1SDimitry Andricdef EXT32 : MxExt<MxType32d, MxType16d>; 560fe6060f1SDimitry Andric 561fe6060f1SDimitry Andricdef : Pat<(sext_inreg i16:$src, i8), (EXT16 $src)>; 562fe6060f1SDimitry Andricdef : Pat<(sext_inreg i32:$src, i16), (EXT32 $src)>; 563fe6060f1SDimitry Andricdef : Pat<(sext_inreg i32:$src, i8), 564fe6060f1SDimitry Andric (EXT32 (MOVXd32d16 (EXT16 (EXTRACT_SUBREG $src, MxSubRegIndex16Lo))))>; 565fe6060f1SDimitry Andric 566fe6060f1SDimitry Andric 567fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 568fe6060f1SDimitry Andric// DIV/MUL 569fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 570fe6060f1SDimitry Andric 571fe6060f1SDimitry Andric/// Word operation: 572fe6060f1SDimitry Andric/// ---------------------------------------------------- 573fe6060f1SDimitry Andric/// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0 574fe6060f1SDimitry Andric/// ---------------------------------------------------- 575fe6060f1SDimitry Andric/// | | | EFFECTIVE ADDRESS 576fe6060f1SDimitry Andric/// x x x x | REG | OP MODE | MODE | REG 577fe6060f1SDimitry Andric/// ---------------------------------------------------- 578fe6060f1SDimitry Andriclet Defs = [CCR] in { 579fe6060f1SDimitry Andriclet Constraints = "$src = $dst" in { 58081ad6265SDimitry Andric// $dreg <- $dreg op $dreg 58181ad6265SDimitry Andricclass MxDiMuOp_DD<string MN, bits<4> CMD, bit SIGNED = false, 582fe6060f1SDimitry Andric MxOperand DST, MxOperand OPD> 58381ad6265SDimitry Andric : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", []> { 58481ad6265SDimitry Andric let Inst = (descend CMD, 58581ad6265SDimitry Andric // REGISTER 58681ad6265SDimitry Andric (operand "$dst", 3), 58781ad6265SDimitry Andric !if(SIGNED, 0b111, 0b011), 58881ad6265SDimitry Andric /*MODE*/0b000, /*REGISTER*/(operand "$opd", 3) 58981ad6265SDimitry Andric ); 59081ad6265SDimitry Andric} 591fe6060f1SDimitry Andric 59206c3fb27SDimitry Andric// $dreg <- $dreg op $dreg 593647cbc5dSDimitry Andricclass MxDiMuOp_DD_Long<string MN, SDNode NODE, bits<10> CMD, bit SIGNED = false> 594647cbc5dSDimitry Andric : MxInst<(outs MxDRD32:$dst), (ins MxDRD32:$src, MxDRD32:$opd), MN#"\t$opd, $dst", 595647cbc5dSDimitry Andric [(set i32:$dst, CCR, (NODE i32:$src, i32:$opd))]> { 59606c3fb27SDimitry Andric let Inst = (ascend 59706c3fb27SDimitry Andric (descend CMD, 59806c3fb27SDimitry Andric /*MODE*/0b000, /*REGISTER*/(operand "$opd", 3)), 59906c3fb27SDimitry Andric (descend 0b0, 60006c3fb27SDimitry Andric // REGISTER 60106c3fb27SDimitry Andric (operand "$dst", 3), 60206c3fb27SDimitry Andric !if(SIGNED, 0b1, 0b0), 60306c3fb27SDimitry Andric /*SIZE*/0b0, 0b0000000, 60406c3fb27SDimitry Andric // Dr REGISTER 60506c3fb27SDimitry Andric 0b000) 60606c3fb27SDimitry Andric ); 60706c3fb27SDimitry Andric} 60806c3fb27SDimitry Andric 609fe6060f1SDimitry Andric// $reg <- $reg op $imm 61081ad6265SDimitry Andricclass MxDiMuOp_DI<string MN, bits<4> CMD, bit SIGNED = false, 611fe6060f1SDimitry Andric MxOperand DST, MxOperand OPD> 61281ad6265SDimitry Andric : MxInst<(outs DST:$dst), (ins DST:$src, OPD:$opd), MN#"\t$opd, $dst", []> { 61381ad6265SDimitry Andric // FIXME: Support immediates with different widths. 61481ad6265SDimitry Andric defvar ImmEnc = MxEncAddrMode_i<"opd", 16>; 61581ad6265SDimitry Andric let Inst = (ascend 61681ad6265SDimitry Andric (descend CMD, 61781ad6265SDimitry Andric // REGISTER 61881ad6265SDimitry Andric (operand "$dst", 3), 61981ad6265SDimitry Andric !if(SIGNED, 0b111, 0b011), ImmEnc.EA), 62081ad6265SDimitry Andric ImmEnc.Supplement 62181ad6265SDimitry Andric ); 62281ad6265SDimitry Andric} 623fe6060f1SDimitry Andric} // let Constraints 624fe6060f1SDimitry Andric} // Defs = [CCR] 625fe6060f1SDimitry Andric 626647cbc5dSDimitry Andricmulticlass MxDiMuOp<string MN, bits<4> CMD> { 62781ad6265SDimitry Andric def "S"#NAME#"d32d16" : MxDiMuOp_DD<MN#"s", CMD, /*SIGNED*/true, MxDRD32, MxDRD16>; 62881ad6265SDimitry Andric def "U"#NAME#"d32d16" : MxDiMuOp_DD<MN#"u", CMD, /*SIGNED*/false, MxDRD32, MxDRD16>; 629fe6060f1SDimitry Andric 63081ad6265SDimitry Andric def "S"#NAME#"d32i16" : MxDiMuOp_DI<MN#"s", CMD, /*SIGNED*/true, MxDRD32, Mxi16imm>; 63181ad6265SDimitry Andric def "U"#NAME#"d32i16" : MxDiMuOp_DI<MN#"u", CMD, /*SIGNED*/false, MxDRD32, Mxi16imm>; 632fe6060f1SDimitry Andric} 633fe6060f1SDimitry Andric 634fe6060f1SDimitry Andricdefm DIV : MxDiMuOp<"div", 0x8>; 635fe6060f1SDimitry Andric 636647cbc5dSDimitry Andricdef SDIVd32d32 : MxDiMuOp_DD_Long<"divs.l", sdiv, 0x131, /*SIGNED*/true>; 637647cbc5dSDimitry Andricdef UDIVd32d32 : MxDiMuOp_DD_Long<"divu.l", udiv, 0x131, /*SIGNED*/false>; 63806c3fb27SDimitry Andric 639fe6060f1SDimitry Andric// This is used to cast immediates to 16-bits for operations which don't 640fe6060f1SDimitry Andric// support smaller immediate sizes. 641fe6060f1SDimitry Andricdef as_i16imm : SDNodeXForm<imm, [{ 642fe6060f1SDimitry Andric return CurDAG->getTargetConstant(N->getSExtValue(), SDLoc(N), MVT::i16); 643fe6060f1SDimitry Andric}]>; 644fe6060f1SDimitry Andric 645fe6060f1SDimitry Andric// RR i8 646fe6060f1SDimitry Andricdef : Pat<(sdiv i8:$dst, i8:$opd), 647fe6060f1SDimitry Andric (EXTRACT_SUBREG 648fe6060f1SDimitry Andric (SDIVd32d16 (MOVSXd32d8 $dst), (MOVSXd16d8 $opd)), 649fe6060f1SDimitry Andric MxSubRegIndex8Lo)>; 650fe6060f1SDimitry Andric 651fe6060f1SDimitry Andricdef : Pat<(udiv i8:$dst, i8:$opd), 652fe6060f1SDimitry Andric (EXTRACT_SUBREG 653fe6060f1SDimitry Andric (UDIVd32d16 (MOVZXd32d8 $dst), (MOVZXd16d8 $opd)), 654fe6060f1SDimitry Andric MxSubRegIndex8Lo)>; 655fe6060f1SDimitry Andric 656fe6060f1SDimitry Andricdef : Pat<(srem i8:$dst, i8:$opd), 657fe6060f1SDimitry Andric (EXTRACT_SUBREG 658fe6060f1SDimitry Andric (ASR32di (ASR32di (SDIVd32d16 (MOVSXd32d8 $dst), (MOVSXd16d8 $opd)), 8), 8), 659fe6060f1SDimitry Andric MxSubRegIndex8Lo)>; 660fe6060f1SDimitry Andric 661fe6060f1SDimitry Andricdef : Pat<(urem i8:$dst, i8:$opd), 662fe6060f1SDimitry Andric (EXTRACT_SUBREG 663fe6060f1SDimitry Andric (LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d8 $dst), (MOVZXd16d8 $opd)), 8), 8), 664fe6060f1SDimitry Andric MxSubRegIndex8Lo)>; 665fe6060f1SDimitry Andric 666fe6060f1SDimitry Andric// RR i16 667fe6060f1SDimitry Andricdef : Pat<(sdiv i16:$dst, i16:$opd), 668fe6060f1SDimitry Andric (EXTRACT_SUBREG 669fe6060f1SDimitry Andric (SDIVd32d16 (MOVSXd32d16 $dst), $opd), 670fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 671fe6060f1SDimitry Andric 672fe6060f1SDimitry Andricdef : Pat<(udiv i16:$dst, i16:$opd), 673fe6060f1SDimitry Andric (EXTRACT_SUBREG 674fe6060f1SDimitry Andric (UDIVd32d16 (MOVZXd32d16 $dst), $opd), 675fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 676fe6060f1SDimitry Andric 677fe6060f1SDimitry Andricdef : Pat<(srem i16:$dst, i16:$opd), 678fe6060f1SDimitry Andric (EXTRACT_SUBREG 679fe6060f1SDimitry Andric (ASR32di (ASR32di (SDIVd32d16 (MOVSXd32d16 $dst), $opd), 8), 8), 680fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 681fe6060f1SDimitry Andric 682fe6060f1SDimitry Andricdef : Pat<(urem i16:$dst, i16:$opd), 683fe6060f1SDimitry Andric (EXTRACT_SUBREG 684fe6060f1SDimitry Andric (LSR32di (LSR32di (UDIVd32d16 (MOVZXd32d16 $dst), $opd), 8), 8), 685fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 686fe6060f1SDimitry Andric 687fe6060f1SDimitry Andric// RI i8 688647cbc5dSDimitry Andricdef : Pat<(sdiv i8:$dst, Mxi8immSExt8:$opd), 689fe6060f1SDimitry Andric (EXTRACT_SUBREG 690fe6060f1SDimitry Andric (SDIVd32i16 (MOVSXd32d8 $dst), (as_i16imm $opd)), 691fe6060f1SDimitry Andric MxSubRegIndex8Lo)>; 692fe6060f1SDimitry Andric 693647cbc5dSDimitry Andricdef : Pat<(udiv i8:$dst, Mxi8immSExt8:$opd), 694fe6060f1SDimitry Andric (EXTRACT_SUBREG 695fe6060f1SDimitry Andric (UDIVd32i16 (MOVZXd32d8 $dst), (as_i16imm $opd)), 696fe6060f1SDimitry Andric MxSubRegIndex8Lo)>; 697fe6060f1SDimitry Andric 698647cbc5dSDimitry Andricdef : Pat<(srem i8:$dst, Mxi8immSExt8:$opd), 699fe6060f1SDimitry Andric (EXTRACT_SUBREG 700fe6060f1SDimitry Andric (ASR32di (ASR32di (SDIVd32i16 (MOVSXd32d8 $dst), (as_i16imm $opd)), 8), 8), 701fe6060f1SDimitry Andric MxSubRegIndex8Lo)>; 702fe6060f1SDimitry Andric 703647cbc5dSDimitry Andricdef : Pat<(urem i8:$dst, Mxi8immSExt8:$opd), 704fe6060f1SDimitry Andric (EXTRACT_SUBREG 705fe6060f1SDimitry Andric (LSR32di (LSR32di (UDIVd32i16 (MOVZXd32d8 $dst), (as_i16imm $opd)), 8), 8), 706fe6060f1SDimitry Andric MxSubRegIndex8Lo)>; 707fe6060f1SDimitry Andric 708fe6060f1SDimitry Andric// RI i16 709647cbc5dSDimitry Andricdef : Pat<(sdiv i16:$dst, Mxi16immSExt16:$opd), 710fe6060f1SDimitry Andric (EXTRACT_SUBREG 711fe6060f1SDimitry Andric (SDIVd32i16 (MOVSXd32d16 $dst), imm:$opd), 712fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 713fe6060f1SDimitry Andric 714647cbc5dSDimitry Andricdef : Pat<(udiv i16:$dst, Mxi16immSExt16:$opd), 715fe6060f1SDimitry Andric (EXTRACT_SUBREG 716fe6060f1SDimitry Andric (UDIVd32i16 (MOVZXd32d16 $dst), imm:$opd), 717fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 718fe6060f1SDimitry Andric 719647cbc5dSDimitry Andricdef : Pat<(srem i16:$dst, Mxi16immSExt16:$opd), 720fe6060f1SDimitry Andric (EXTRACT_SUBREG 721fe6060f1SDimitry Andric (ASR32di (ASR32di (SDIVd32i16 (MOVSXd32d16 $dst), imm:$opd), 8), 8), 722fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 723fe6060f1SDimitry Andric 724647cbc5dSDimitry Andricdef : Pat<(urem i16:$dst, Mxi16immSExt16:$opd), 725fe6060f1SDimitry Andric (EXTRACT_SUBREG 726fe6060f1SDimitry Andric (LSR32di (LSR32di (UDIVd32i16 (MOVZXd32d16 $dst), imm:$opd), 8), 8), 727fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 728fe6060f1SDimitry Andric 729fe6060f1SDimitry Andric 730647cbc5dSDimitry Andricdefm MUL : MxDiMuOp<"mul", 0xC>; 731fe6060f1SDimitry Andric 732647cbc5dSDimitry Andricdef SMULd32d32 : MxDiMuOp_DD_Long<"muls.l", MxSMul, 0x130, /*SIGNED*/true>; 733647cbc5dSDimitry Andricdef UMULd32d32 : MxDiMuOp_DD_Long<"mulu.l", MxUMul, 0x130, /*SIGNED*/false>; 73406c3fb27SDimitry Andric 735fe6060f1SDimitry Andric// RR 736fe6060f1SDimitry Andricdef : Pat<(mul i16:$dst, i16:$opd), 737fe6060f1SDimitry Andric (EXTRACT_SUBREG 738fe6060f1SDimitry Andric (SMULd32d16 (MOVXd32d16 $dst), $opd), 739fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 740fe6060f1SDimitry Andric 741fe6060f1SDimitry Andricdef : Pat<(mulhs i16:$dst, i16:$opd), 742fe6060f1SDimitry Andric (EXTRACT_SUBREG 743fe6060f1SDimitry Andric (ASR32di (ASR32di (SMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8), 744fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 745fe6060f1SDimitry Andric 746fe6060f1SDimitry Andricdef : Pat<(mulhu i16:$dst, i16:$opd), 747fe6060f1SDimitry Andric (EXTRACT_SUBREG 748fe6060f1SDimitry Andric (LSR32di (LSR32di (UMULd32d16 (MOVXd32d16 $dst), $opd), 8), 8), 749fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 750fe6060f1SDimitry Andric 75106c3fb27SDimitry Andricdef : Pat<(mul i32:$dst, i32:$opd), (SMULd32d32 $dst, $opd)>; 75206c3fb27SDimitry Andric 753fe6060f1SDimitry Andric 754fe6060f1SDimitry Andric// RI 755647cbc5dSDimitry Andricdef : Pat<(mul i16:$dst, Mxi16immSExt16:$opd), 756fe6060f1SDimitry Andric (EXTRACT_SUBREG 757fe6060f1SDimitry Andric (SMULd32i16 (MOVXd32d16 $dst), imm:$opd), 758fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 759fe6060f1SDimitry Andric 760647cbc5dSDimitry Andricdef : Pat<(mulhs i16:$dst, Mxi16immSExt16:$opd), 761fe6060f1SDimitry Andric (EXTRACT_SUBREG 762fe6060f1SDimitry Andric (ASR32di (ASR32di (SMULd32i16 (MOVXd32d16 $dst), imm:$opd), 8), 8), 763fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 764fe6060f1SDimitry Andric 765647cbc5dSDimitry Andricdef : Pat<(mulhu i16:$dst, Mxi16immSExt16:$opd), 766fe6060f1SDimitry Andric (EXTRACT_SUBREG 767fe6060f1SDimitry Andric (LSR32di (LSR32di (UMULd32i16 (MOVXd32d16 $dst), imm:$opd), 8), 8), 768fe6060f1SDimitry Andric MxSubRegIndex16Lo)>; 769fe6060f1SDimitry Andric 770fe6060f1SDimitry Andric 771fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 772*0fca6ea1SDimitry Andric// NEG/NEGX/NOT 773fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 774fe6060f1SDimitry Andric 775fe6060f1SDimitry Andric/// ------------+------------+------+---------+--------- 776fe6060f1SDimitry Andric/// F E D C | B A 9 8 | 7 6 | 5 4 3 | 2 1 0 777fe6060f1SDimitry Andric/// ------------+------------+------+------------------- 778fe6060f1SDimitry Andric/// | | | EFFECTIVE ADDRESS 779fe6060f1SDimitry Andric/// 0 1 0 0 | x x x x | SIZE | MODE | REG 780fe6060f1SDimitry Andric/// ------------+------------+------+---------+--------- 781fe6060f1SDimitry Andriclet Defs = [CCR] in { 782fe6060f1SDimitry Andriclet Constraints = "$src = $dst" in { 783fe6060f1SDimitry Andric 784fe6060f1SDimitry Andricclass MxNeg_D<MxType TYPE> 785fe6060f1SDimitry Andric : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src), 786fe6060f1SDimitry Andric "neg."#TYPE.Prefix#"\t$dst", 78781ad6265SDimitry Andric [(set TYPE.VT:$dst, (ineg TYPE.VT:$src))]> { 78881ad6265SDimitry Andric let Inst = (descend 0b01000100, 78906c3fb27SDimitry Andric /*SIZE*/!cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 79081ad6265SDimitry Andric //MODE without last bit 79181ad6265SDimitry Andric 0b00, 79281ad6265SDimitry Andric //REGISTER prefixed by D/A bit 79381ad6265SDimitry Andric (operand "$dst", 4) 79481ad6265SDimitry Andric ); 79581ad6265SDimitry Andric} 796fe6060f1SDimitry Andric 797fe6060f1SDimitry Andriclet Uses = [CCR] in { 798fe6060f1SDimitry Andricclass MxNegX_D<MxType TYPE> 799fe6060f1SDimitry Andric : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src), 800fe6060f1SDimitry Andric "negx."#TYPE.Prefix#"\t$dst", 80181ad6265SDimitry Andric [(set TYPE.VT:$dst, (MxSubX 0, TYPE.VT:$src, CCR))]> { 80281ad6265SDimitry Andric let Inst = (descend 0b01000000, 80306c3fb27SDimitry Andric /*SIZE*/!cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 80481ad6265SDimitry Andric //MODE without last bit 80581ad6265SDimitry Andric 0b00, 80681ad6265SDimitry Andric //REGISTER prefixed by D/A bit 80781ad6265SDimitry Andric (operand "$dst", 4) 80881ad6265SDimitry Andric ); 80981ad6265SDimitry Andric} 810fe6060f1SDimitry Andric} 811fe6060f1SDimitry Andric 812*0fca6ea1SDimitry Andricclass MxNot_D<MxType TYPE> 813*0fca6ea1SDimitry Andric : MxInst<(outs TYPE.ROp:$dst), (ins TYPE.ROp:$src), 814*0fca6ea1SDimitry Andric "not."#TYPE.Prefix#"\t$dst", 815*0fca6ea1SDimitry Andric [(set TYPE.VT:$dst, (not TYPE.VT:$src))]> { 816*0fca6ea1SDimitry Andric let Inst = (descend 0b01000110, 817*0fca6ea1SDimitry Andric /*SIZE*/!cast<MxEncSize>("MxEncSize"#TYPE.Size).Value, 818*0fca6ea1SDimitry Andric //MODE without last bit 819*0fca6ea1SDimitry Andric 0b00, 820*0fca6ea1SDimitry Andric //REGISTER prefixed by D/A bit 821*0fca6ea1SDimitry Andric (operand "$dst", 4) 822*0fca6ea1SDimitry Andric ); 823*0fca6ea1SDimitry Andric} 824*0fca6ea1SDimitry Andric 825fe6060f1SDimitry Andric} // let Constraints 826fe6060f1SDimitry Andric} // let Defs = [CCR] 827fe6060f1SDimitry Andric 828fe6060f1SDimitry Andricforeach S = [8, 16, 32] in { 829fe6060f1SDimitry Andric def NEG#S#d : MxNeg_D<!cast<MxType>("MxType"#S#"d")>; 830fe6060f1SDimitry Andric def NEGX#S#d : MxNegX_D<!cast<MxType>("MxType"#S#"d")>; 831*0fca6ea1SDimitry Andric def NOT#S#d : MxNot_D<!cast<MxType>("MxType"#S#"d")>; 832fe6060f1SDimitry Andric} 833fe6060f1SDimitry Andric 834fe6060f1SDimitry Andricdef : Pat<(MxSub 0, i8 :$src), (NEG8d MxDRD8 :$src)>; 835fe6060f1SDimitry Andricdef : Pat<(MxSub 0, i16:$src), (NEG16d MxDRD16:$src)>; 836fe6060f1SDimitry Andricdef : Pat<(MxSub 0, i32:$src), (NEG32d MxDRD32:$src)>; 83706c3fb27SDimitry Andric// SExt of i1 values. 83806c3fb27SDimitry Andric// Although we specify `ZeroOrOneBooleanContent` for boolean content, 83906c3fb27SDimitry Andric// we're still adding an AND here as we don't know the origin of the i1 value. 84006c3fb27SDimitry Andricdef : Pat<(sext_inreg i8:$src, i1), (NEG8d (AND8di MxDRD8:$src, 1))>; 84106c3fb27SDimitry Andricdef : Pat<(sext_inreg i16:$src, i1), (NEG16d (AND16di MxDRD16:$src, 1))>; 84206c3fb27SDimitry Andricdef : Pat<(sext_inreg i32:$src, i1), (NEG32d (AND32di MxDRD32:$src, 1))>; 843fe6060f1SDimitry Andric 844fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 845fe6060f1SDimitry Andric// no-CCR Patterns 846fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 847fe6060f1SDimitry Andric 848fe6060f1SDimitry Andric/// Basically the reason for this stuff is that add and addc share the same 849fe6060f1SDimitry Andric/// operand types constraints for whatever reasons and I had to define a common 850fe6060f1SDimitry Andric/// MxAdd and MxSub instructions that produce CCR and then pattern-map add and addc 851fe6060f1SDimitry Andric/// to it. 852fe6060f1SDimitry Andric/// NOTE On the other hand I see no reason why I cannot just drop explicit CCR 853fe6060f1SDimitry Andric/// result. Anyway works for now, hopefully I will better understand how this stuff 854fe6060f1SDimitry Andric/// is designed later 855fe6060f1SDimitry Andricforeach N = ["add", "addc"] in { 856fe6060f1SDimitry Andric 857fe6060f1SDimitry Andric // add reg, reg 858fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd), 859fe6060f1SDimitry Andric (ADD8dd MxDRD8 :$src, MxDRD8 :$opd)>; 860fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd), 861349cc55cSDimitry Andric (ADD16dr MxXRD16:$src, MxDRD16:$opd)>; 862fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd), 863349cc55cSDimitry Andric (ADD32dr MxXRD32:$src, MxDRD32:$opd)>; 864fe6060f1SDimitry Andric 865fe6060f1SDimitry Andric // add (An), reg 866fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)), 867fe6060f1SDimitry Andric (ADD8dj MxDRD8:$src, MxType8.JOp:$opd)>; 868fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)), 869fe6060f1SDimitry Andric (ADD16dj MxDRD16:$src, MxType16.JOp:$opd)>; 870fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)), 871349cc55cSDimitry Andric (ADD32dj MxDRD32:$src, MxType32.JOp:$opd)>; 872fe6060f1SDimitry Andric 873fe6060f1SDimitry Andric // add (i,An), reg 874fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)), 875fe6060f1SDimitry Andric (ADD8dp MxDRD8:$src, MxType8.POp:$opd)>; 876fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)), 877fe6060f1SDimitry Andric (ADD16dp MxDRD16:$src, MxType16.POp:$opd)>; 878fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)), 879349cc55cSDimitry Andric (ADD32dp MxDRD32:$src, MxType32.POp:$opd)>; 880fe6060f1SDimitry Andric 881fe6060f1SDimitry Andric // add (i,An,Xn), reg 882fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)), 883fe6060f1SDimitry Andric (ADD8df MxDRD8:$src, MxType8.FOp:$opd)>; 884fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)), 885fe6060f1SDimitry Andric (ADD16df MxDRD16:$src, MxType16.FOp:$opd)>; 886fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)), 887349cc55cSDimitry Andric (ADD32df MxDRD32:$src, MxType32.FOp:$opd)>; 888fe6060f1SDimitry Andric 889fe6060f1SDimitry Andric // add reg, imm 890647cbc5dSDimitry Andric def : Pat<(!cast<SDNode>(N) i8: $src, Mxi8immSExt8:$opd), 891fe6060f1SDimitry Andric (ADD8di MxDRD8 :$src, imm:$opd)>; 892647cbc5dSDimitry Andric def : Pat<(!cast<SDNode>(N) i16:$src, Mxi16immSExt16:$opd), 893fe6060f1SDimitry Andric (ADD16di MxDRD16:$src, imm:$opd)>; 894fe6060f1SDimitry Andric 895fe6060f1SDimitry Andric // LEAp is more complex and thus will be selected over normal ADD32ri but it cannot 896fe6060f1SDimitry Andric // be used with data registers, here by adding complexity to a simple ADD32ri insts 897fe6060f1SDimitry Andric // we make sure it will be selected over LEAp 898fe6060f1SDimitry Andric let AddedComplexity = 15 in { 899647cbc5dSDimitry Andric def : Pat<(!cast<SDNode>(N) i32:$src, Mxi32immSExt32:$opd), 900349cc55cSDimitry Andric (ADD32di MxDRD32:$src, imm:$opd)>; 901fe6060f1SDimitry Andric } // AddedComplexity = 15 902fe6060f1SDimitry Andric 903fe6060f1SDimitry Andric // add imm, (An) 904fe6060f1SDimitry Andric def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd), 905fe6060f1SDimitry Andric MxType8.JPat:$dst), 906fe6060f1SDimitry Andric (ADD8ji MxType8.JOp:$dst, imm:$opd)>; 907fe6060f1SDimitry Andric def : Pat<(store (!cast<SDNode>(N) (load MxType16.JPat:$dst), MxType16.IPat:$opd), 908fe6060f1SDimitry Andric MxType16.JPat:$dst), 909fe6060f1SDimitry Andric (ADD16ji MxType16.JOp:$dst, imm:$opd)>; 910fe6060f1SDimitry Andric def : Pat<(store (!cast<SDNode>(N) (load MxType32.JPat:$dst), MxType32.IPat:$opd), 911fe6060f1SDimitry Andric MxType32.JPat:$dst), 912fe6060f1SDimitry Andric (ADD32ji MxType32.JOp:$dst, imm:$opd)>; 913fe6060f1SDimitry Andric 914fe6060f1SDimitry Andric} // foreach add, addc 915fe6060f1SDimitry Andric 916fe6060f1SDimitry Andricdef : Pat<(adde i8 :$src, i8 :$opd), (ADDX8dd MxDRD8 :$src, MxDRD8 :$opd)>; 917fe6060f1SDimitry Andricdef : Pat<(adde i16:$src, i16:$opd), (ADDX16dd MxDRD16:$src, MxDRD16:$opd)>; 918fe6060f1SDimitry Andricdef : Pat<(adde i32:$src, i32:$opd), (ADDX32dd MxDRD32:$src, MxDRD32:$opd)>; 919fe6060f1SDimitry Andric 920fe6060f1SDimitry Andric 921fe6060f1SDimitry Andric 922fe6060f1SDimitry Andricforeach N = ["sub", "subc"] in { 923fe6060f1SDimitry Andric 924fe6060f1SDimitry Andric // sub reg, reg 925fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) i8 :$src, i8 :$opd), 926fe6060f1SDimitry Andric (SUB8dd MxDRD8 :$src, MxDRD8 :$opd)>; 927fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) i16:$src, i16:$opd), 928fe6060f1SDimitry Andric (SUB16dd MxDRD16:$src, MxDRD16:$opd)>; 929fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) i32:$src, i32:$opd), 930349cc55cSDimitry Andric (SUB32dd MxDRD32:$src, MxDRD32:$opd)>; 931fe6060f1SDimitry Andric 932fe6060f1SDimitry Andric 933fe6060f1SDimitry Andric // sub (An), reg 934fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.JPat:$opd)), 935fe6060f1SDimitry Andric (SUB8dj MxDRD8:$src, MxType8.JOp:$opd)>; 936fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.JPat:$opd)), 937fe6060f1SDimitry Andric (SUB16dj MxDRD16:$src, MxType16.JOp:$opd)>; 938fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.JPat:$opd)), 939349cc55cSDimitry Andric (SUB32dj MxDRD32:$src, MxType32.JOp:$opd)>; 940fe6060f1SDimitry Andric 941fe6060f1SDimitry Andric // sub (i,An), reg 942fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.PPat:$opd)), 943fe6060f1SDimitry Andric (SUB8dp MxDRD8:$src, MxType8.POp:$opd)>; 944fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.PPat:$opd)), 945fe6060f1SDimitry Andric (SUB16dp MxDRD16:$src, MxType16.POp:$opd)>; 946fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.PPat:$opd)), 947349cc55cSDimitry Andric (SUB32dp MxDRD32:$src, MxType32.POp:$opd)>; 948fe6060f1SDimitry Andric 949fe6060f1SDimitry Andric // sub (i,An,Xn), reg 950fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType8.VT:$src, (Mxloadi8 MxType8.FPat:$opd)), 951fe6060f1SDimitry Andric (SUB8df MxDRD8:$src, MxType8.FOp:$opd)>; 952fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType16.VT:$src, (Mxloadi16 MxType16.FPat:$opd)), 953fe6060f1SDimitry Andric (SUB16df MxDRD16:$src, MxType16.FOp:$opd)>; 954fe6060f1SDimitry Andric def : Pat<(!cast<SDNode>(N) MxType32.VT:$src, (Mxloadi32 MxType32.FPat:$opd)), 955349cc55cSDimitry Andric (SUB32df MxDRD32:$src, MxType32.FOp:$opd)>; 956fe6060f1SDimitry Andric 957fe6060f1SDimitry Andric // sub reg, imm 958647cbc5dSDimitry Andric def : Pat<(!cast<SDNode>(N) i8 :$src, Mxi8immSExt8 :$opd), 959fe6060f1SDimitry Andric (SUB8di MxDRD8 :$src, imm:$opd)>; 960647cbc5dSDimitry Andric def : Pat<(!cast<SDNode>(N) i16:$src, Mxi16immSExt16:$opd), 961fe6060f1SDimitry Andric (SUB16di MxDRD16:$src, imm:$opd)>; 962647cbc5dSDimitry Andric def : Pat<(!cast<SDNode>(N) i32:$src, Mxi32immSExt32:$opd), 963349cc55cSDimitry Andric (SUB32di MxDRD32:$src, imm:$opd)>; 964fe6060f1SDimitry Andric 965fe6060f1SDimitry Andric // sub imm, (An) 966fe6060f1SDimitry Andric def : Pat<(store (!cast<SDNode>(N) (load MxType8.JPat:$dst), MxType8.IPat:$opd), 967fe6060f1SDimitry Andric MxType8.JPat:$dst), 968fe6060f1SDimitry Andric (SUB8ji MxType8.JOp:$dst, imm:$opd)>; 969fe6060f1SDimitry Andric def : Pat<(store (!cast<SDNode>(N) (load MxType16.JPat:$dst), MxType16.IPat:$opd), 970fe6060f1SDimitry Andric MxType16.JPat:$dst), 971fe6060f1SDimitry Andric (SUB16ji MxType16.JOp:$dst, imm:$opd)>; 972fe6060f1SDimitry Andric def : Pat<(store (!cast<SDNode>(N) (load MxType32.JPat:$dst), MxType32.IPat:$opd), 973fe6060f1SDimitry Andric MxType32.JPat:$dst), 974fe6060f1SDimitry Andric (SUB32ji MxType32.JOp:$dst, imm:$opd)>; 975fe6060f1SDimitry Andric 976fe6060f1SDimitry Andric} // foreach sub, subx 977fe6060f1SDimitry Andric 978fe6060f1SDimitry Andricdef : Pat<(sube i8 :$src, i8 :$opd), (SUBX8dd MxDRD8 :$src, MxDRD8 :$opd)>; 979fe6060f1SDimitry Andricdef : Pat<(sube i16:$src, i16:$opd), (SUBX16dd MxDRD16:$src, MxDRD16:$opd)>; 980fe6060f1SDimitry Andricdef : Pat<(sube i32:$src, i32:$opd), (SUBX32dd MxDRD32:$src, MxDRD32:$opd)>; 981fe6060f1SDimitry Andric 982fe6060f1SDimitry Andricmulticlass BitwisePat<string INST, SDNode OP> { 983fe6060f1SDimitry Andric // op reg, reg 984fe6060f1SDimitry Andric def : Pat<(OP i8 :$src, i8 :$opd), 985fe6060f1SDimitry Andric (!cast<MxInst>(INST#"8dd") MxDRD8 :$src, MxDRD8 :$opd)>; 986fe6060f1SDimitry Andric def : Pat<(OP i16:$src, i16:$opd), 987fe6060f1SDimitry Andric (!cast<MxInst>(INST#"16dd") MxDRD16:$src, MxDRD16:$opd)>; 988fe6060f1SDimitry Andric def : Pat<(OP i32:$src, i32:$opd), 989fe6060f1SDimitry Andric (!cast<MxInst>(INST#"32dd") MxDRD32:$src, MxDRD32:$opd)>; 990fe6060f1SDimitry Andric // op reg, imm 991647cbc5dSDimitry Andric def : Pat<(OP i8: $src, Mxi8immSExt8 :$opd), 992fe6060f1SDimitry Andric (!cast<MxInst>(INST#"8di") MxDRD8 :$src, imm:$opd)>; 993647cbc5dSDimitry Andric def : Pat<(OP i16:$src, Mxi16immSExt16:$opd), 994fe6060f1SDimitry Andric (!cast<MxInst>(INST#"16di") MxDRD16:$src, imm:$opd)>; 995647cbc5dSDimitry Andric def : Pat<(OP i32:$src, Mxi32immSExt32:$opd), 996fe6060f1SDimitry Andric (!cast<MxInst>(INST#"32di") MxDRD32:$src, imm:$opd)>; 997fe6060f1SDimitry Andric} 998fe6060f1SDimitry Andric 999fe6060f1SDimitry Andricdefm : BitwisePat<"AND", and>; 1000fe6060f1SDimitry Andricdefm : BitwisePat<"OR", or>; 1001fe6060f1SDimitry Andricdefm : BitwisePat<"XOR", xor>; 100206c3fb27SDimitry Andric 100306c3fb27SDimitry Andric//===----------------------------------------------------------------------===// 100406c3fb27SDimitry Andric// Floating point arithmetic instruction 100506c3fb27SDimitry Andric//===----------------------------------------------------------------------===// 100606c3fb27SDimitry Andric 100706c3fb27SDimitry Andriclet Defs = [FPS] in 100806c3fb27SDimitry Andricclass MxFArithBase_FF<dag outs, dag ins, string asm, string rounding, 100906c3fb27SDimitry Andric list<dag> patterns> 101006c3fb27SDimitry Andric : MxInst<outs, ins, asm, patterns> { 101106c3fb27SDimitry Andric let Uses = !if(!eq(rounding, ""), [FPC], []); 101206c3fb27SDimitry Andric 101306c3fb27SDimitry Andric let Predicates = !if(!eq(rounding, ""), [AtLeastM68881], [AtLeastM68040]); 101406c3fb27SDimitry Andric} 101506c3fb27SDimitry Andric 101606c3fb27SDimitry Andricclass MxFPOpModeSelector<string rounding, bits<7> single, bits<7> double, 101706c3fb27SDimitry Andric bits<7> extended> { 101806c3fb27SDimitry Andric bits<7> Mode = !cond(!eq(rounding, "s"): single, 101906c3fb27SDimitry Andric !eq(rounding, "d"): double, 102006c3fb27SDimitry Andric !eq(rounding, ""): extended); 102106c3fb27SDimitry Andric} 102206c3fb27SDimitry Andric 102306c3fb27SDimitry Andric//===----------------------------------------------------------------------===// 102406c3fb27SDimitry Andric// Unary floating point instruction 102506c3fb27SDimitry Andric//===----------------------------------------------------------------------===// 102606c3fb27SDimitry Andric 102706c3fb27SDimitry Andricclass MxFUnary_FF<MxOpBundle Opnd, string rounding, 102806c3fb27SDimitry Andric string mnemonic, bits<7> opmode> 102906c3fb27SDimitry Andric : MxFArithBase_FF<(outs Opnd.Op:$dst), (ins Opnd.Op:$src), 103006c3fb27SDimitry Andric "f"#rounding#mnemonic#".x\t$src, $dst", rounding, [(null_frag)]> { 103106c3fb27SDimitry Andric let Inst = (ascend 103206c3fb27SDimitry Andric (descend 0b1111, 103306c3fb27SDimitry Andric /*COPROCESSOR ID*/0b001, 103406c3fb27SDimitry Andric 0b000, 103506c3fb27SDimitry Andric /*MODE+REGISTER*/0b000000), 103606c3fb27SDimitry Andric (descend 0b0, /* R/M */ 0b0, 0b0, 103706c3fb27SDimitry Andric /*SOURCE SPECIFIER*/ 103806c3fb27SDimitry Andric (operand "$src", 3), 103906c3fb27SDimitry Andric /*DESTINATION*/ 104006c3fb27SDimitry Andric (operand "$dst", 3), 104106c3fb27SDimitry Andric /*OPMODE*/ 104206c3fb27SDimitry Andric opmode) 104306c3fb27SDimitry Andric ); 104406c3fb27SDimitry Andric} 104506c3fb27SDimitry Andric 104606c3fb27SDimitry Andricmulticlass MxFUnaryOp<string mnemonic, bits<7> single, bits<7> double, 104706c3fb27SDimitry Andric bits<7> extended> { 104806c3fb27SDimitry Andric foreach rounding = ["", "s", "d"] in { 104906c3fb27SDimitry Andric defvar opmode = MxFPOpModeSelector<rounding, single, double, extended>.Mode; 105006c3fb27SDimitry Andric 105106c3fb27SDimitry Andric def F # !toupper(rounding) # !substr(NAME, 1) # "80fp_fp" 105206c3fb27SDimitry Andric : MxFUnary_FF<MxOp80AddrMode_fpr, rounding, mnemonic, opmode>; 105306c3fb27SDimitry Andric 105406c3fb27SDimitry Andric let isCodeGenOnly = 1 in 105506c3fb27SDimitry Andric foreach size = [32, 64] in 105606c3fb27SDimitry Andric def F # !toupper(rounding) # !substr(NAME, 1) # size # "fp_fp" 105706c3fb27SDimitry Andric : MxFUnary_FF<!cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr"), 105806c3fb27SDimitry Andric rounding, mnemonic, opmode>; 105906c3fb27SDimitry Andric } 106006c3fb27SDimitry Andric} 106106c3fb27SDimitry Andric 106206c3fb27SDimitry Andricdefm FABS : MxFUnaryOp<"abs", 0b1011000, 0b1011100, 0b0011000>; 106306c3fb27SDimitry Andricdefm FNEG : MxFUnaryOp<"neg", 0b1011010, 0b1011110, 0b0011010>; 106406c3fb27SDimitry Andric 106506c3fb27SDimitry Andric//===----------------------------------------------------------------------===// 106606c3fb27SDimitry Andric// Binary floating point instruction 106706c3fb27SDimitry Andric//===----------------------------------------------------------------------===// 106806c3fb27SDimitry Andric 106906c3fb27SDimitry Andriclet Constraints = "$src = $dst" in 107006c3fb27SDimitry Andricclass MxFBinary_FF<MxOpBundle Opnd, string rounding, 107106c3fb27SDimitry Andric string mnemonic, bits<7> opmode> 107206c3fb27SDimitry Andric : MxFArithBase_FF<(outs Opnd.Op:$dst), (ins Opnd.Op:$src, Opnd.Op:$opd), 107306c3fb27SDimitry Andric "f"#rounding#mnemonic#".x\t$opd, $dst", rounding, [(null_frag)]> { 107406c3fb27SDimitry Andric let Inst = (ascend 107506c3fb27SDimitry Andric (descend 0b1111, 107606c3fb27SDimitry Andric /*COPROCESSOR ID*/0b001, 107706c3fb27SDimitry Andric 0b000, 107806c3fb27SDimitry Andric /*MODE+REGISTER*/0b000000), 107906c3fb27SDimitry Andric (descend 0b0, /* R/M */ 0b0, 0b0, 108006c3fb27SDimitry Andric /*SOURCE SPECIFIER*/ 108106c3fb27SDimitry Andric (operand "$opd", 3), 108206c3fb27SDimitry Andric /*DESTINATION*/ 108306c3fb27SDimitry Andric (operand "$dst", 3), 108406c3fb27SDimitry Andric /*OPMODE*/ 108506c3fb27SDimitry Andric opmode) 108606c3fb27SDimitry Andric ); 108706c3fb27SDimitry Andric} 108806c3fb27SDimitry Andric 108906c3fb27SDimitry Andricmulticlass MxFBinaryOp<string mnemonic, bits<7> single, bits<7> double, 109006c3fb27SDimitry Andric bits<7> extended> { 109106c3fb27SDimitry Andric foreach rounding = ["", "s", "d"] in { 109206c3fb27SDimitry Andric defvar opmode = MxFPOpModeSelector<rounding, single, double, extended>.Mode; 109306c3fb27SDimitry Andric 109406c3fb27SDimitry Andric def F # !toupper(rounding) # !substr(NAME, 1) # "80fp_fp" 109506c3fb27SDimitry Andric : MxFBinary_FF<MxOp80AddrMode_fpr, rounding, mnemonic, opmode>; 109606c3fb27SDimitry Andric 109706c3fb27SDimitry Andric let isCodeGenOnly = 1 in 109806c3fb27SDimitry Andric foreach size = [32, 64] in 109906c3fb27SDimitry Andric def F # !toupper(rounding) # !substr(NAME, 1) # size # "fp_fp" 110006c3fb27SDimitry Andric : MxFBinary_FF<!cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr"), 110106c3fb27SDimitry Andric rounding, mnemonic, opmode>; 110206c3fb27SDimitry Andric } 110306c3fb27SDimitry Andric} 110406c3fb27SDimitry Andric 110506c3fb27SDimitry Andricdefm FADD : MxFBinaryOp<"add", 0b1100010, 0b1100110, 0b0100010>; 110606c3fb27SDimitry Andricdefm FSUB : MxFBinaryOp<"sub", 0b1101000, 0b1101100, 0b0101000>; 110706c3fb27SDimitry Andricdefm FMUL : MxFBinaryOp<"mul", 0b1100011, 0b1100111, 0b0100011>; 110806c3fb27SDimitry Andricdefm FDIV : MxFBinaryOp<"div", 0b1100000, 0b1100100, 0b0100000>; 1109