104eeddc0SDimitry Andric//===-- M68kInstrData.td - M68k Data Movement Instructions -*- 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 Motorola 680x0 data movement instructions which are 11fe6060f1SDimitry Andric/// the basic means of transferring and storing addresses and data. Here is the 12fe6060f1SDimitry Andric/// current status of the file: 13fe6060f1SDimitry Andric/// 14fe6060f1SDimitry Andric/// Machine: 15fe6060f1SDimitry Andric/// 16fe6060f1SDimitry Andric/// EXG [ ] FMOVE [ ] FSMOVE [ ] FDMOVE [ ] FMOVEM [ ] 17fe6060f1SDimitry Andric/// LEA [~] PEA [ ] MOVE [~] MOVE16 [ ] MOVEA [ ] 18bdd1243dSDimitry Andric/// MOVEM [ ] MOVEP [ ] MOVEQ [ ] LINK [~] UNLK [~] 19fe6060f1SDimitry Andric/// 20fe6060f1SDimitry Andric/// Pseudo: 21fe6060f1SDimitry Andric/// 22fe6060f1SDimitry Andric/// MOVSX [x] MOVZX [x] MOVX [x] 23fe6060f1SDimitry Andric/// 24fe6060f1SDimitry Andric/// Map: 25fe6060f1SDimitry Andric/// 26fe6060f1SDimitry Andric/// [ ] - was not touched at all 27fe6060f1SDimitry Andric/// [!] - requires extarnal stuff implemented 28fe6060f1SDimitry Andric/// [~] - in progress but usable 29fe6060f1SDimitry Andric/// [x] - done 30fe6060f1SDimitry Andric/// 31fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 32fe6060f1SDimitry Andric 33fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 34fe6060f1SDimitry Andric// MOVE 35fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 36fe6060f1SDimitry Andric 37fe6060f1SDimitry Andric/// ----------------------------------------------------- 38fe6060f1SDimitry Andric/// F E | D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0 39fe6060f1SDimitry Andric/// ----------------------------------------------------- 40fe6060f1SDimitry Andric/// | | DESTINATION | SOURCE 41fe6060f1SDimitry Andric/// 0 0 | SIZE | REG | MODE | MODE | REG 42fe6060f1SDimitry Andric/// ----------------------------------------------------- 43fe6060f1SDimitry Andric/// 44fe6060f1SDimitry Andric/// NOTE Move requires EA X version for direct register destination(0) 45fe6060f1SDimitry Andric 4681ad6265SDimitry Andric// MOVE has a different size encoding. 4781ad6265SDimitry Andricclass MxMoveSize<bits<2> value> { 4881ad6265SDimitry Andric bits<2> Value = value; 4981ad6265SDimitry Andric} 50fe6060f1SDimitry Andricdef MxMoveSize8 : MxMoveSize<0b01>; 51fe6060f1SDimitry Andricdef MxMoveSize16 : MxMoveSize<0b11>; 52fe6060f1SDimitry Andricdef MxMoveSize32 : MxMoveSize<0b10>; 53fe6060f1SDimitry Andric 5481ad6265SDimitry Andricclass MxMoveEncoding<MxMoveSize size, MxEncMemOp dst_enc, MxEncMemOp src_enc> { 5581ad6265SDimitry Andric dag Value = (ascend 5681ad6265SDimitry Andric (descend 0b00, size.Value, 5781ad6265SDimitry Andric !cond( 5881ad6265SDimitry Andric !eq(!getdagop(dst_enc.EA), descend): !setdagop(dst_enc.EA, ascend), 5981ad6265SDimitry Andric !eq(!getdagop(dst_enc.EA), ascend): !setdagop(dst_enc.EA, descend)), 6081ad6265SDimitry Andric src_enc.EA), 6181ad6265SDimitry Andric // Source extension 6281ad6265SDimitry Andric src_enc.Supplement, 6381ad6265SDimitry Andric // Destination extension 6481ad6265SDimitry Andric dst_enc.Supplement 6581ad6265SDimitry Andric ); 6681ad6265SDimitry Andric} 67fe6060f1SDimitry Andric 6881ad6265SDimitry Andric// Special encoding for Xn 6981ad6265SDimitry Andricclass MxMoveEncAddrMode_r<string reg_opnd> : MxEncMemOp { 7081ad6265SDimitry Andric let EA = (descend (descend 0b00, (slice "$"#reg_opnd, 3, 3)), 7181ad6265SDimitry Andric (operand "$"#reg_opnd, 3)); 7281ad6265SDimitry Andric} 7381ad6265SDimitry Andric 7481ad6265SDimitry Andric// TODO: Generalize and adopt this utility in other .td files as well. 7581ad6265SDimitry Andricmulticlass MxMoveOperandEncodings<string opnd_name> { 7681ad6265SDimitry Andric // Dn 7781ad6265SDimitry Andric def MxMove#NAME#OpEnc_d : MxEncAddrMode_d<opnd_name>; 7881ad6265SDimitry Andric // An 7981ad6265SDimitry Andric def MxMove#NAME#OpEnc_a : MxEncAddrMode_a<opnd_name>; 8081ad6265SDimitry Andric // Xn 8181ad6265SDimitry Andric def MxMove#NAME#OpEnc_r : MxMoveEncAddrMode_r<opnd_name>; 8281ad6265SDimitry Andric // (An)+ 8381ad6265SDimitry Andric def MxMove#NAME#OpEnc_o : MxEncAddrMode_o<opnd_name>; 8481ad6265SDimitry Andric // -(An) 8581ad6265SDimitry Andric def MxMove#NAME#OpEnc_e : MxEncAddrMode_e<opnd_name>; 8681ad6265SDimitry Andric // (i,PC,Xn) 8781ad6265SDimitry Andric def MxMove#NAME#OpEnc_k : MxEncAddrMode_k<opnd_name>; 8881ad6265SDimitry Andric // (i,PC) 8981ad6265SDimitry Andric def MxMove#NAME#OpEnc_q : MxEncAddrMode_q<opnd_name>; 9081ad6265SDimitry Andric // (i,An,Xn) 9181ad6265SDimitry Andric def MxMove#NAME#OpEnc_f : MxEncAddrMode_f<opnd_name>; 9281ad6265SDimitry Andric // (i,An) 9381ad6265SDimitry Andric def MxMove#NAME#OpEnc_p : MxEncAddrMode_p<opnd_name>; 9481ad6265SDimitry Andric // (ABS).L 9581ad6265SDimitry Andric def MxMove#NAME#OpEnc_b : MxEncAddrMode_abs<opnd_name, /*W/L=*/true>; 9681ad6265SDimitry Andric // (An) 9781ad6265SDimitry Andric def MxMove#NAME#OpEnc_j : MxEncAddrMode_j<opnd_name>; 9881ad6265SDimitry Andric} 9981ad6265SDimitry Andric 10081ad6265SDimitry Andricdefm Src : MxMoveOperandEncodings<"src">; 10181ad6265SDimitry Andricdefm Dst : MxMoveOperandEncodings<"dst">; 10281ad6265SDimitry Andric 10381ad6265SDimitry Andricdefvar MxMoveSupportedAMs = ["o", "e", "k", "q", "f", "p", "b", "j"]; 10481ad6265SDimitry Andric 10581ad6265SDimitry Andriclet Defs = [CCR] in 10681ad6265SDimitry Andricclass MxMove<string size, dag outs, dag ins, list<dag> pattern, MxMoveEncoding enc> 10781ad6265SDimitry Andric : MxInst<outs, ins, "move."#size#"\t$src, $dst", pattern> { 10881ad6265SDimitry Andric let Inst = enc.Value; 10981ad6265SDimitry Andric} 11081ad6265SDimitry Andric 11181ad6265SDimitry Andric// R <- R 11281ad6265SDimitry Andricclass MxMove_RR<MxType TYPE, string DST_REG, string SRC_REG, 11381ad6265SDimitry Andric MxMoveEncoding ENC, 11481ad6265SDimitry Andric MxOpBundle DST = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_REG), 11581ad6265SDimitry Andric MxOpBundle SRC = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#SRC_REG)> 11681ad6265SDimitry Andric : MxMove<TYPE.Prefix, 11781ad6265SDimitry Andric (outs DST.Op:$dst), (ins SRC.Op:$src), 118fe6060f1SDimitry Andric [(null_frag)], ENC>; 119fe6060f1SDimitry Andric 12081ad6265SDimitry Andricforeach DST_REG = ["r", "a"] in { 12181ad6265SDimitry Andric foreach SRC_REG = ["r", "a"] in 12281ad6265SDimitry Andric foreach TYPE = [MxType16, MxType32] in 12381ad6265SDimitry Andric def MOV # TYPE.Size # DST_REG # SRC_REG # TYPE.Postfix 12481ad6265SDimitry Andric : MxMove_RR<TYPE, DST_REG, SRC_REG, 12581ad6265SDimitry Andric MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size), 12681ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveDstOpEnc_"#DST_REG), 12781ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#SRC_REG)>>; 12881ad6265SDimitry Andric} // foreach DST_REG 12981ad6265SDimitry Andricforeach TYPE = [MxType8, MxType16, MxType32] in 13081ad6265SDimitry Andricdef MOV # TYPE.Size # dd # TYPE.Postfix 13181ad6265SDimitry Andric : MxMove_RR<TYPE, "d", "d", 13281ad6265SDimitry Andric MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size), 13381ad6265SDimitry Andric MxMoveDstOpEnc_d, MxMoveSrcOpEnc_d>>; 134fe6060f1SDimitry Andric 13581ad6265SDimitry Andric// M <- R 13681ad6265SDimitry Andriclet mayStore = 1 in { 13781ad6265SDimitry Andricclass MxMove_MR<MxType TYPE, MxOpBundle DST, string SRC_REG, MxMoveEncoding ENC, 13881ad6265SDimitry Andric MxOpBundle SRC = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#SRC_REG)> 13981ad6265SDimitry Andric : MxMove<TYPE.Prefix, (outs), (ins DST.Op:$dst, SRC.Op:$src), 14081ad6265SDimitry Andric [(store TYPE.VT:$src, DST.Pat:$dst)], ENC>; 14181ad6265SDimitry Andric 14281ad6265SDimitry Andricclass MxMove_MI<MxType TYPE, MxOpBundle DST, MxMoveEncoding ENC, 14381ad6265SDimitry Andric MxImmOpBundle SRC = !cast<MxImmOpBundle>("MxOp"#TYPE.Size#"AddrMode_i")> 14481ad6265SDimitry Andric : MxMove<TYPE.Prefix, (outs), (ins DST.Op:$dst, SRC.Op:$src), 14581ad6265SDimitry Andric [(store SRC.ImmPat:$src, DST.Pat:$dst)], ENC>; 146fe6060f1SDimitry Andric} // let mayStore = 1 147fe6060f1SDimitry Andric 14881ad6265SDimitry Andricforeach REG = ["r", "a", "d"] in 14981ad6265SDimitry Andricforeach AM = MxMoveSupportedAMs in { 15081ad6265SDimitry Andric foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in 15181ad6265SDimitry Andric def MOV # TYPE.Size # AM # REG # TYPE.Postfix 15281ad6265SDimitry Andric : MxMove_MR<TYPE, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM), REG, 15381ad6265SDimitry Andric MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size), 15481ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM), 15581ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#REG)>>; 15681ad6265SDimitry Andric} // foreach AM 157fe6060f1SDimitry Andric 15881ad6265SDimitry Andricforeach AM = MxMoveSupportedAMs in { 15981ad6265SDimitry Andric foreach TYPE = [MxType8, MxType16, MxType32] in 16081ad6265SDimitry Andric def MOV # TYPE.Size # AM # i # TYPE.Postfix 16181ad6265SDimitry Andric : MxMove_MI<TYPE, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM), 16281ad6265SDimitry Andric MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size), 16381ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM), 16481ad6265SDimitry Andric MxEncAddrMode_i<"src", TYPE.Size>>>; 16581ad6265SDimitry Andric} // foreach AM 166fe6060f1SDimitry Andric 16781ad6265SDimitry Andric// R <- I 16881ad6265SDimitry Andricclass MxMove_RI<MxType TYPE, string DST_REG, MxMoveEncoding ENC, 16981ad6265SDimitry Andric MxImmOpBundle SRC = !cast<MxImmOpBundle>("MxOp"#TYPE.Size#"AddrMode_i"), 17081ad6265SDimitry Andric MxOpBundle DST = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_REG)> 17181ad6265SDimitry Andric : MxMove<TYPE.Prefix, (outs DST.Op:$dst), (ins SRC.Op:$src), 17281ad6265SDimitry Andric [(set TYPE.VT:$dst, SRC.ImmPat:$src)], ENC>; 17381ad6265SDimitry Andric 17481ad6265SDimitry Andricforeach REG = ["r", "a", "d"] in { 17581ad6265SDimitry Andric foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in 17681ad6265SDimitry Andric def MOV # TYPE.Size # REG # i # TYPE.Postfix 17781ad6265SDimitry Andric : MxMove_RI<TYPE, REG, 17881ad6265SDimitry Andric MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size), 17981ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveDstOpEnc_"#REG), 18081ad6265SDimitry Andric MxEncAddrMode_i<"src", TYPE.Size>>>; 18181ad6265SDimitry Andric} // foreach REG 18281ad6265SDimitry Andric 18381ad6265SDimitry Andric// R <- M 184fe6060f1SDimitry Andriclet mayLoad = 1 in 18581ad6265SDimitry Andricclass MxMove_RM<MxType TYPE, string DST_REG, MxOpBundle SRC, MxEncMemOp SRC_ENC, 18681ad6265SDimitry Andric MxMoveSize SIZE_ENC = !cast<MxMoveSize>("MxMoveSize"#TYPE.Size), 18781ad6265SDimitry Andric MxOpBundle DST = !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_REG), 18881ad6265SDimitry Andric MxEncMemOp DST_ENC = !cast<MxEncMemOp>("MxMoveDstOpEnc_"#DST_REG)> 18981ad6265SDimitry Andric : MxMove<TYPE.Prefix, (outs DST.Op:$dst), (ins SRC.Op:$src), 19081ad6265SDimitry Andric [(set TYPE.VT:$dst, (TYPE.Load SRC.Pat:$src))], 19181ad6265SDimitry Andric MxMoveEncoding<SIZE_ENC, DST_ENC, SRC_ENC>>; 192fe6060f1SDimitry Andric 19381ad6265SDimitry Andricforeach REG = ["r", "a", "d"] in 19481ad6265SDimitry Andricforeach AM = MxMoveSupportedAMs in { 19581ad6265SDimitry Andric foreach TYPE = !if(!eq(REG, "d"), [MxType8, MxType16, MxType32], [MxType16, MxType32]) in 19681ad6265SDimitry Andric def MOV # TYPE.Size # REG # AM # TYPE.Postfix 19781ad6265SDimitry Andric : MxMove_RM<TYPE, REG, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM), 19881ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>; 19981ad6265SDimitry Andric} // foreach AM 200fe6060f1SDimitry Andric 20181ad6265SDimitry Andric// Tail call version 20281ad6265SDimitry Andriclet Pattern = [(null_frag)] in { 20381ad6265SDimitry Andric foreach REG = ["r", "a"] in 20481ad6265SDimitry Andric foreach AM = MxMoveSupportedAMs in { 20581ad6265SDimitry Andric foreach TYPE = [MxType16, MxType32] in 20681ad6265SDimitry Andric def MOV # TYPE.Size # REG # AM # _TC 20781ad6265SDimitry Andric : MxMove_RM<TYPE, REG, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM), 20881ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)> { 20981ad6265SDimitry Andric let isCodeGenOnly = true; 210fe6060f1SDimitry Andric } 21181ad6265SDimitry Andric } // foreach AM 21281ad6265SDimitry Andric} // let Pattern 213fe6060f1SDimitry Andric 21481ad6265SDimitry Andriclet mayLoad = 1, mayStore = 1 in 21581ad6265SDimitry Andricclass MxMove_MM<MxType TYPE, MxOpBundle DST, MxOpBundle SRC, 21681ad6265SDimitry Andric MxEncMemOp DST_ENC, MxEncMemOp SRC_ENC> 21781ad6265SDimitry Andric : MxMove<TYPE.Prefix, (outs), (ins DST.Op:$dst, SRC.Op:$src), 21881ad6265SDimitry Andric [(store (TYPE.Load SRC.Pat:$src), DST.Pat:$dst)], 21981ad6265SDimitry Andric MxMoveEncoding<!cast<MxMoveSize>("MxMoveSize"#TYPE.Size), 22081ad6265SDimitry Andric DST_ENC, SRC_ENC>>; 221fe6060f1SDimitry Andric 22281ad6265SDimitry Andricforeach DST_AM = MxMoveSupportedAMs in 22381ad6265SDimitry Andricforeach SRC_AM = MxMoveSupportedAMs in { 22481ad6265SDimitry Andric foreach TYPE = [MxType8, MxType16, MxType32] in 22581ad6265SDimitry Andric def MOV # TYPE.Size # DST_AM # SRC_AM # TYPE.Postfix 22681ad6265SDimitry Andric : MxMove_MM<TYPE, !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#DST_AM), 22781ad6265SDimitry Andric !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#SRC_AM), 22881ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveDstOpEnc_"#DST_AM), 22981ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#SRC_AM)>; 23081ad6265SDimitry Andric} // foreach SRC_AM 231fe6060f1SDimitry Andric 232fe6060f1SDimitry Andric// Store ABS(basically pointer) as Immdiate to Mem 233fe6060f1SDimitry Andricdef : Pat<(store MxType32.BPat :$src, MxType32.PPat :$dst), 234fe6060f1SDimitry Andric (MOV32pi MxType32.POp :$dst, MxType32.IOp :$src)>; 235fe6060f1SDimitry Andric 236fe6060f1SDimitry Andricdef : Pat<(store MxType32.BPat :$src, MxType32.FPat :$dst), 237fe6060f1SDimitry Andric (MOV32fi MxType32.FOp :$dst, MxType32.IOp :$src)>; 238fe6060f1SDimitry Andric 239fe6060f1SDimitry Andricdef : Pat<(store MxType32.BPat :$src, MxType32.BPat :$dst), 240fe6060f1SDimitry Andric (MOV32bi MxType32.BOp :$dst, MxType32.IOp :$src)>; 241fe6060f1SDimitry Andric 242fe6060f1SDimitry Andricdef : Pat<(store MxType32.BPat :$src, MxType32.JPat :$dst), 243fe6060f1SDimitry Andric (MOV32ji MxType32.JOp :$dst, MxType32.IOp :$src)>; 244fe6060f1SDimitry Andric 245fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 246fe6060f1SDimitry Andric// MOVEM 247fe6060f1SDimitry Andric// 248fe6060f1SDimitry Andric// The mask is already pre-processed by the save/restore spill hook 249fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 250fe6060f1SDimitry Andric 251fe6060f1SDimitry Andric// Direction 25281ad6265SDimitry Andricdefvar MxMOVEM_MR = false; 25381ad6265SDimitry Andricdefvar MxMOVEM_RM = true; 254fe6060f1SDimitry Andric 255fe6060f1SDimitry Andric// Size 25681ad6265SDimitry Andricdefvar MxMOVEM_W = false; 25781ad6265SDimitry Andricdefvar MxMOVEM_L = true; 258fe6060f1SDimitry Andric 259fe6060f1SDimitry Andric/// ---------------+-------------+-------------+--------- 260fe6060f1SDimitry Andric/// F E D C B | A | 9 8 7 | 6 | 5 4 3 | 2 1 0 261fe6060f1SDimitry Andric/// ---------------+---+---------+---+---------+--------- 262fe6060f1SDimitry Andric/// 0 1 0 0 1 | D | 0 0 1 | S | MODE | REG 263fe6060f1SDimitry Andric/// ---------------+---+---------+---+---------+--------- 264fe6060f1SDimitry Andric/// REGISTER LIST MASK 265fe6060f1SDimitry Andric/// ----------------------------------------------------- 266fe6060f1SDimitry Andric/// D - direction(RM,MR) 267fe6060f1SDimitry Andric/// S - size(W,L) 26881ad6265SDimitry Andricclass MxMOVEMEncoding<MxEncMemOp opnd_enc, bit size, bit direction, 26981ad6265SDimitry Andric string mask_op_name> { 27081ad6265SDimitry Andric dag Value = (ascend 27181ad6265SDimitry Andric (descend 0b01001, direction, 0b001, size, opnd_enc.EA), 27281ad6265SDimitry Andric // Mask 27381ad6265SDimitry Andric (operand "$"#mask_op_name, 16), 27481ad6265SDimitry Andric opnd_enc.Supplement 27581ad6265SDimitry Andric ); 27681ad6265SDimitry Andric} 277fe6060f1SDimitry Andric 278fe6060f1SDimitry Andriclet mayStore = 1 in 27981ad6265SDimitry Andricclass MxMOVEM_MR<MxType TYPE, bit SIZE_ENC, 28081ad6265SDimitry Andric MxOperand MEMOp, MxEncMemOp MEM_ENC> 281fe6060f1SDimitry Andric : MxInst<(outs), (ins MEMOp:$dst, MxMoveMask:$mask), 28281ad6265SDimitry Andric "movem."#TYPE.Prefix#"\t$mask, $dst", []> { 28381ad6265SDimitry Andric let Inst = MxMOVEMEncoding<MEM_ENC, SIZE_ENC, MxMOVEM_MR, "mask">.Value; 28481ad6265SDimitry Andric} 28581ad6265SDimitry Andric 28681ad6265SDimitry Andricforeach AM = MxMoveSupportedAMs in { 28781ad6265SDimitry Andric foreach TYPE = [MxType16, MxType32] in 28881ad6265SDimitry Andric def MOVM # TYPE.Size # AM # m # TYPE.Postfix 28981ad6265SDimitry Andric : MxMOVEM_MR<TYPE, !if(!eq(TYPE, MxType16), MxMOVEM_W, MxMOVEM_L), 29081ad6265SDimitry Andric !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM).Op, 29181ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM)>; 29281ad6265SDimitry Andric} // foreach AM 293fe6060f1SDimitry Andric 294fe6060f1SDimitry Andriclet mayLoad = 1 in 29581ad6265SDimitry Andricclass MxMOVEM_RM<MxType TYPE, bit SIZE_ENC, 29681ad6265SDimitry Andric MxOperand MEMOp, MxEncMemOp MEM_ENC> 297fe6060f1SDimitry Andric : MxInst<(outs), (ins MxMoveMask:$mask, MEMOp:$src), 29881ad6265SDimitry Andric "movem."#TYPE.Prefix#"\t$src, $mask", []> { 29981ad6265SDimitry Andric let Inst = MxMOVEMEncoding<MEM_ENC, SIZE_ENC, MxMOVEM_RM, "mask">.Value; 30081ad6265SDimitry Andric} 301fe6060f1SDimitry Andric 30281ad6265SDimitry Andricforeach AM = MxMoveSupportedAMs in { 30381ad6265SDimitry Andric foreach TYPE = [MxType16, MxType32] in 30481ad6265SDimitry Andric def MOVM # TYPE.Size # m # AM # TYPE.Postfix 30581ad6265SDimitry Andric : MxMOVEM_RM<TYPE, !if(!eq(TYPE, MxType16), MxMOVEM_W, MxMOVEM_L), 30681ad6265SDimitry Andric !cast<MxOpBundle>("MxOp"#TYPE.Size#"AddrMode_"#AM).Op, 30781ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>; 30881ad6265SDimitry Andric} // foreach AM 309fe6060f1SDimitry Andric 310fe6060f1SDimitry Andric// Pseudo versions. These a required by virtual register spill/restore since 311fe6060f1SDimitry Andric// the mask requires real register to encode. These instruction will be expanded 312fe6060f1SDimitry Andric// into real MOVEM after RA finishes. 313fe6060f1SDimitry Andriclet mayStore = 1 in 314fe6060f1SDimitry Andricclass MxMOVEM_MR_Pseudo<MxType TYPE, MxOperand MEMOp> 315fe6060f1SDimitry Andric : MxPseudo<(outs), (ins MEMOp:$dst, TYPE.ROp:$reg)>; 316fe6060f1SDimitry Andriclet mayLoad = 1 in 317fe6060f1SDimitry Andricclass MxMOVEM_RM_Pseudo<MxType TYPE, MxOperand MEMOp> 318fe6060f1SDimitry Andric : MxPseudo<(outs TYPE.ROp:$dst), (ins MEMOp:$src)>; 319fe6060f1SDimitry Andric 320fe6060f1SDimitry Andric// Mem <- Reg 321fe6060f1SDimitry Andricdef MOVM8jm_P : MxMOVEM_MR_Pseudo<MxType8d, MxType8.JOp>; 322fe6060f1SDimitry Andricdef MOVM16jm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.JOp>; 323fe6060f1SDimitry Andricdef MOVM32jm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.JOp>; 324fe6060f1SDimitry Andric 325fe6060f1SDimitry Andricdef MOVM8pm_P : MxMOVEM_MR_Pseudo<MxType8d, MxType8.POp>; 326fe6060f1SDimitry Andricdef MOVM16pm_P : MxMOVEM_MR_Pseudo<MxType16r, MxType16.POp>; 327fe6060f1SDimitry Andricdef MOVM32pm_P : MxMOVEM_MR_Pseudo<MxType32r, MxType32.POp>; 328fe6060f1SDimitry Andric 329fe6060f1SDimitry Andric// Reg <- Mem 330fe6060f1SDimitry Andricdef MOVM8mj_P : MxMOVEM_RM_Pseudo<MxType8d, MxType8.JOp>; 331fe6060f1SDimitry Andricdef MOVM16mj_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.JOp>; 332fe6060f1SDimitry Andricdef MOVM32mj_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.JOp>; 333fe6060f1SDimitry Andric 334fe6060f1SDimitry Andricdef MOVM8mp_P : MxMOVEM_RM_Pseudo<MxType8d, MxType8.POp>; 335fe6060f1SDimitry Andricdef MOVM16mp_P : MxMOVEM_RM_Pseudo<MxType16r, MxType16.POp>; 336fe6060f1SDimitry Andricdef MOVM32mp_P : MxMOVEM_RM_Pseudo<MxType32r, MxType32.POp>; 337fe6060f1SDimitry Andric 338fe6060f1SDimitry Andric 339fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 340fe6060f1SDimitry Andric// MOVE to/from SR/CCR 341fe6060f1SDimitry Andric// 342fe6060f1SDimitry Andric// A special care must be taken working with to/from CCR since it is basically 343fe6060f1SDimitry Andric// word-size SR register truncated for user mode thus it only supports word-size 344fe6060f1SDimitry Andric// instructions. Plus the original M68000 does not support moves from CCR. So in 345fe6060f1SDimitry Andric// order to use CCR effectively one MUST use proper byte-size pseudo instructi- 346fe6060f1SDimitry Andric// ons that will be resolved sometime after RA pass. 347fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 348fe6060f1SDimitry Andric 349fe6060f1SDimitry Andric/// -------------------------------------------------- 350fe6060f1SDimitry Andric/// F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0 351fe6060f1SDimitry Andric/// -------------------------------------------------- 352fe6060f1SDimitry Andric/// | EFFECTIVE ADDRESS 353fe6060f1SDimitry Andric/// 0 1 0 0 0 1 0 0 1 1 | MODE | REG 354fe6060f1SDimitry Andric/// -------------------------------------------------- 355fe6060f1SDimitry Andriclet Defs = [CCR] in 35681ad6265SDimitry Andricclass MxMoveToCCR<MxOperand MEMOp, MxEncMemOp SRC_ENC> 35781ad6265SDimitry Andric : MxInst<(outs CCRC:$dst), (ins MEMOp:$src), "move.w\t$src, $dst", []> { 35881ad6265SDimitry Andric let Inst = (ascend 35981ad6265SDimitry Andric (descend 0b0100010011, SRC_ENC.EA), 36081ad6265SDimitry Andric SRC_ENC.Supplement 36181ad6265SDimitry Andric ); 36281ad6265SDimitry Andric} 363fe6060f1SDimitry Andric 36481ad6265SDimitry Andricclass MxMoveToCCRPseudo<MxOperand MEMOp> 36581ad6265SDimitry Andric : MxPseudo<(outs CCRC:$dst), (ins MEMOp:$src)>; 366fe6060f1SDimitry Andric 36781ad6265SDimitry Andriclet mayLoad = 1 in 36881ad6265SDimitry Andricforeach AM = MxMoveSupportedAMs in { 36981ad6265SDimitry Andric def MOV16c # AM : MxMoveToCCR<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op, 37081ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>; 37181ad6265SDimitry Andric def MOV8c # AM : MxMoveToCCRPseudo<!cast<MxOpBundle>("MxOp8AddrMode_"#AM).Op>; 37281ad6265SDimitry Andric} // foreach AM 373fe6060f1SDimitry Andric 37481ad6265SDimitry Andric// Only data register is allowed. 37581ad6265SDimitry Andricdef MOV16cd : MxMoveToCCR<MxOp16AddrMode_d.Op, MxMoveSrcOpEnc_d>; 37681ad6265SDimitry Andricdef MOV8cd : MxMoveToCCRPseudo<MxOp8AddrMode_d.Op>; 377fe6060f1SDimitry Andric 378fe6060f1SDimitry Andric/// Move from CCR 379fe6060f1SDimitry Andric/// -------------------------------------------------- 380fe6060f1SDimitry Andric/// F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0 381fe6060f1SDimitry Andric/// -------------------------------------------------- 382fe6060f1SDimitry Andric/// | EFFECTIVE ADDRESS 383fe6060f1SDimitry Andric/// 0 1 0 0 0 0 1 0 1 1 | MODE | REG 384fe6060f1SDimitry Andric/// -------------------------------------------------- 38581ad6265SDimitry Andriclet Uses = [CCR] in { 38681ad6265SDimitry Andricclass MxMoveFromCCR_R 38781ad6265SDimitry Andric : MxInst<(outs MxDRD16:$dst), (ins CCRC:$src), "move.w\t$src, $dst", []>, 388bdd1243dSDimitry Andric Requires<[ AtLeastM68010 ]> { 38981ad6265SDimitry Andric let Inst = (descend 0b0100001011, MxEncAddrMode_d<"dst">.EA); 39081ad6265SDimitry Andric} 391fe6060f1SDimitry Andric 39281ad6265SDimitry Andricclass MxMoveFromCCR_M<MxOperand MEMOp, MxEncMemOp DST_ENC> 39381ad6265SDimitry Andric : MxInst<(outs), (ins MEMOp:$dst, CCRC:$src), "move.w\t$src, $dst", []>, 394bdd1243dSDimitry Andric Requires<[ AtLeastM68010 ]> { 39581ad6265SDimitry Andric let Inst = (ascend 39681ad6265SDimitry Andric (descend 0b0100001011, DST_ENC.EA), 39781ad6265SDimitry Andric DST_ENC.Supplement 39881ad6265SDimitry Andric ); 39981ad6265SDimitry Andric} 400fe6060f1SDimitry Andric 40181ad6265SDimitry Andricclass MxMoveFromCCRPseudo<MxOperand MEMOp> 40281ad6265SDimitry Andric : MxPseudo<(outs), (ins MEMOp:$dst, CCRC:$src)>; 40381ad6265SDimitry Andric} // let Uses = [CCR] 404fe6060f1SDimitry Andric 40581ad6265SDimitry Andriclet mayStore = 1 in 40681ad6265SDimitry Andricforeach AM = MxMoveSupportedAMs in { 40781ad6265SDimitry Andric def MOV16 # AM # c 40881ad6265SDimitry Andric : MxMoveFromCCR_M<!cast<MxOpBundle>("MxOp16AddrMode_"#AM).Op, 40981ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveDstOpEnc_"#AM)>; 41081ad6265SDimitry Andric def MOV8 # AM # c 41181ad6265SDimitry Andric : MxMoveFromCCRPseudo<!cast<MxOpBundle>("MxOp8AddrMode_"#AM).Op>; 41281ad6265SDimitry Andric} // foreach AM 413fe6060f1SDimitry Andric 41481ad6265SDimitry Andric// Only data register is allowed. 41581ad6265SDimitry Andricdef MOV16dc : MxMoveFromCCR_R; 41681ad6265SDimitry Andricdef MOV8dc : MxMoveFromCCRPseudo<MxOp8AddrMode_d.Op>; 417fe6060f1SDimitry Andric 418fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 419fe6060f1SDimitry Andric// LEA 420fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 421fe6060f1SDimitry Andric 422fe6060f1SDimitry Andric/// ---------------------------------------------------- 423fe6060f1SDimitry Andric/// F E D C | B A 9 | 8 7 6 | 5 4 3 | 2 1 0 424fe6060f1SDimitry Andric/// ---------------------------------------------------- 425fe6060f1SDimitry Andric/// 0 1 0 0 | DST REG | 1 1 1 | MODE | REG 426fe6060f1SDimitry Andric/// ---------------------------------------------------- 42781ad6265SDimitry Andricclass MxLEA<MxOpBundle SRC, MxEncMemOp SRC_ENC> 42881ad6265SDimitry Andric : MxInst<(outs MxARD32:$dst), (ins SRC.Op:$src), 42981ad6265SDimitry Andric "lea\t$src, $dst", [(set i32:$dst, SRC.Pat:$src)]> { 43081ad6265SDimitry Andric let Inst = (ascend 43181ad6265SDimitry Andric (descend 0b0100, (operand "$dst", 3), 0b111, SRC_ENC.EA), 43281ad6265SDimitry Andric SRC_ENC.Supplement 43381ad6265SDimitry Andric ); 43481ad6265SDimitry Andric} 435fe6060f1SDimitry Andric 43681ad6265SDimitry Andricforeach AM = ["p", "f", "b", "q", "k"] in 43781ad6265SDimitry Andricdef LEA32 # AM : MxLEA<!cast<MxOpBundle>("MxOp32AddrMode_"#AM), 43881ad6265SDimitry Andric !cast<MxEncMemOp>("MxMoveSrcOpEnc_"#AM)>; 439fe6060f1SDimitry Andric 440fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 441bdd1243dSDimitry Andric// LINK/UNLK 442bdd1243dSDimitry Andric//===----------------------------------------------------------------------===// 443bdd1243dSDimitry Andric 444bdd1243dSDimitry Andriclet Uses = [SP], Defs = [SP] in { 445bdd1243dSDimitry Andriclet mayStore = 1 in { 446bdd1243dSDimitry Andric 447bdd1243dSDimitry Andricdef LINK16 : MxInst<(outs), (ins MxARD16:$src, Mxi16imm:$disp), "link.w\t$src, $disp", []> { 448bdd1243dSDimitry Andric let Inst = (ascend 449bdd1243dSDimitry Andric (descend 0b0100111001010, (operand "$src", 3)), 450bdd1243dSDimitry Andric (operand "$disp", 16) 451bdd1243dSDimitry Andric ); 452bdd1243dSDimitry Andric} 453bdd1243dSDimitry Andric 454bdd1243dSDimitry Andricdef LINK32 : MxInst<(outs), (ins MxARD16:$src, Mxi32imm:$disp), "link.l\t$src, $disp", []> { 455bdd1243dSDimitry Andric let Inst = (ascend 456bdd1243dSDimitry Andric (descend 0b0100100000001, (operand "$src", 3)), 457bdd1243dSDimitry Andric (slice "$disp", 31, 16), 458bdd1243dSDimitry Andric (slice "$disp", 15, 0) 459bdd1243dSDimitry Andric ); 460bdd1243dSDimitry Andric} 461bdd1243dSDimitry Andric 462bdd1243dSDimitry Andricdef UNLK : MxInst<(outs), (ins MxARD32:$src), "unlk\t$src", []> { 463bdd1243dSDimitry Andric let Inst = (descend 0b0100111001011, (operand "$src", 3)); 464bdd1243dSDimitry Andric} 465bdd1243dSDimitry Andric 466bdd1243dSDimitry Andric} // let mayStore = 1 467bdd1243dSDimitry Andric} // let Uses = [SP], Defs = [SP] 468bdd1243dSDimitry Andric 469bdd1243dSDimitry Andric//===----------------------------------------------------------------------===// 470fe6060f1SDimitry Andric// Pseudos 471fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 472fe6060f1SDimitry Andric 473fe6060f1SDimitry Andric/// Pushe/Pop to/from SP for simplicity 474fe6060f1SDimitry Andriclet Uses = [SP], Defs = [SP], hasSideEffects = 0 in { 475fe6060f1SDimitry Andric 476fe6060f1SDimitry Andric// SP <- SP - <size>; (SP) <- Dn 477fe6060f1SDimitry Andriclet mayStore = 1 in { 478fe6060f1SDimitry Andricdef PUSH8d : MxPseudo<(outs), (ins DR8:$reg)>; 479fe6060f1SDimitry Andricdef PUSH16d : MxPseudo<(outs), (ins DR16:$reg)>; 480fe6060f1SDimitry Andricdef PUSH32r : MxPseudo<(outs), (ins XR32:$reg)>; 481fe6060f1SDimitry Andric} // let mayStore = 1 482fe6060f1SDimitry Andric 483fe6060f1SDimitry Andric// Dn <- (SP); SP <- SP + <size> 484fe6060f1SDimitry Andriclet mayLoad = 1 in { 485fe6060f1SDimitry Andricdef POP8d : MxPseudo<(outs DR8:$reg), (ins)>; 486fe6060f1SDimitry Andricdef POP16d : MxPseudo<(outs DR16:$reg), (ins)>; 487fe6060f1SDimitry Andricdef POP32r : MxPseudo<(outs XR32:$reg), (ins)>; 488fe6060f1SDimitry Andric} // let mayLoad = 1 489fe6060f1SDimitry Andric 490fe6060f1SDimitry Andric} // let Uses/Defs = [SP], hasSideEffects = 0 491fe6060f1SDimitry Andric 492fe6060f1SDimitry Andric 493fe6060f1SDimitry Andriclet Defs = [CCR] in { 494fe6060f1SDimitry Andricclass MxPseudoMove_RR<MxType DST, MxType SRC, list<dag> PAT = []> 495fe6060f1SDimitry Andric : MxPseudo<(outs DST.ROp:$dst), (ins SRC.ROp:$src), PAT>; 496fe6060f1SDimitry Andric 497fe6060f1SDimitry Andricclass MxPseudoMove_RM<MxType DST, MxOperand SRCOpd, list<dag> PAT = []> 498fe6060f1SDimitry Andric : MxPseudo<(outs DST.ROp:$dst), (ins SRCOpd:$src), PAT>; 499fe6060f1SDimitry Andric} 500fe6060f1SDimitry Andric 501fe6060f1SDimitry Andric/// This group of Pseudos is analogues to the real x86 extending moves, but 502fe6060f1SDimitry Andric/// since M68k does not have those we need to emulate. These instructions 503fe6060f1SDimitry Andric/// will be expanded right after RA completed because we need to know precisely 504fe6060f1SDimitry Andric/// what registers are allocated for the operands and if they overlap we just 505fe6060f1SDimitry Andric/// extend the value if the registers are completely different we need to move 506fe6060f1SDimitry Andric/// first. 507fe6060f1SDimitry Andricforeach EXT = ["S", "Z"] in { 508fe6060f1SDimitry Andric let hasSideEffects = 0 in { 509fe6060f1SDimitry Andric 510fe6060f1SDimitry Andric def MOV#EXT#Xd16d8 : MxPseudoMove_RR<MxType16d, MxType8d>; 511fe6060f1SDimitry Andric def MOV#EXT#Xd32d8 : MxPseudoMove_RR<MxType32d, MxType8d>; 512fe6060f1SDimitry Andric def MOV#EXT#Xd32d16 : MxPseudoMove_RR<MxType32r, MxType16r>; 513fe6060f1SDimitry Andric 514fe6060f1SDimitry Andric let mayLoad = 1 in { 515fe6060f1SDimitry Andric 516fe6060f1SDimitry Andric def MOV#EXT#Xd16j8 : MxPseudoMove_RM<MxType16d, MxType8.JOp>; 517fe6060f1SDimitry Andric def MOV#EXT#Xd32j8 : MxPseudoMove_RM<MxType32d, MxType8.JOp>; 518fe6060f1SDimitry Andric def MOV#EXT#Xd32j16 : MxPseudoMove_RM<MxType32d, MxType16.JOp>; 519fe6060f1SDimitry Andric 520fe6060f1SDimitry Andric def MOV#EXT#Xd16p8 : MxPseudoMove_RM<MxType16d, MxType8.POp>; 521fe6060f1SDimitry Andric def MOV#EXT#Xd32p8 : MxPseudoMove_RM<MxType32d, MxType8.POp>; 522fe6060f1SDimitry Andric def MOV#EXT#Xd32p16 : MxPseudoMove_RM<MxType32d, MxType16.POp>; 523fe6060f1SDimitry Andric 524fe6060f1SDimitry Andric def MOV#EXT#Xd16f8 : MxPseudoMove_RM<MxType16d, MxType8.FOp>; 525fe6060f1SDimitry Andric def MOV#EXT#Xd32f8 : MxPseudoMove_RM<MxType32d, MxType8.FOp>; 526fe6060f1SDimitry Andric def MOV#EXT#Xd32f16 : MxPseudoMove_RM<MxType32d, MxType16.FOp>; 527fe6060f1SDimitry Andric 528*06c3fb27SDimitry Andric def MOV#EXT#Xd16q8 : MxPseudoMove_RM<MxType16d, MxType8.QOp>; 529*06c3fb27SDimitry Andric def MOV#EXT#Xd32q8 : MxPseudoMove_RM<MxType32d, MxType8.QOp>; 530*06c3fb27SDimitry Andric def MOV#EXT#Xd32q16 : MxPseudoMove_RM<MxType32d, MxType16.QOp>; 531*06c3fb27SDimitry Andric 532fe6060f1SDimitry Andric } 533fe6060f1SDimitry Andric } 534fe6060f1SDimitry Andric} 535fe6060f1SDimitry Andric 536fe6060f1SDimitry Andric/// This group of instructions is similar to the group above but DOES NOT do 537fe6060f1SDimitry Andric/// any value extension, they just load a smaller register into the lower part 538fe6060f1SDimitry Andric/// of another register if operands' real registers are different or does 539fe6060f1SDimitry Andric/// nothing if they are the same. 540fe6060f1SDimitry Andricdef MOVXd16d8 : MxPseudoMove_RR<MxType16d, MxType8d>; 541fe6060f1SDimitry Andricdef MOVXd32d8 : MxPseudoMove_RR<MxType32d, MxType8d>; 542fe6060f1SDimitry Andricdef MOVXd32d16 : MxPseudoMove_RR<MxType32r, MxType16r>; 543fe6060f1SDimitry Andric 544fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 545fe6060f1SDimitry Andric// Extend/Truncate Patterns 546fe6060f1SDimitry Andric//===----------------------------------------------------------------------===// 547fe6060f1SDimitry Andric 548fe6060f1SDimitry Andric// i16 <- sext i8 549fe6060f1SDimitry Andricdef: Pat<(i16 (sext i8:$src)), 550fe6060f1SDimitry Andric (EXTRACT_SUBREG (MOVSXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>; 551fe6060f1SDimitry Andricdef: Pat<(MxSExtLoadi16i8 MxCP_ARI:$src), 552fe6060f1SDimitry Andric (EXTRACT_SUBREG (MOVSXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>; 553fe6060f1SDimitry Andricdef: Pat<(MxSExtLoadi16i8 MxCP_ARID:$src), 554fe6060f1SDimitry Andric (EXTRACT_SUBREG (MOVSXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>; 555fe6060f1SDimitry Andricdef: Pat<(MxSExtLoadi16i8 MxCP_ARII:$src), 556fe6060f1SDimitry Andric (EXTRACT_SUBREG (MOVSXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>; 557fe6060f1SDimitry Andric 558fe6060f1SDimitry Andric// i32 <- sext i8 559fe6060f1SDimitry Andricdef: Pat<(i32 (sext i8:$src)), (MOVSXd32d8 MxDRD8:$src)>; 560fe6060f1SDimitry Andricdef: Pat<(MxSExtLoadi32i8 MxCP_ARI :$src), (MOVSXd32j8 MxARI8 :$src)>; 561fe6060f1SDimitry Andricdef: Pat<(MxSExtLoadi32i8 MxCP_ARID:$src), (MOVSXd32p8 MxARID8:$src)>; 562fe6060f1SDimitry Andricdef: Pat<(MxSExtLoadi32i8 MxCP_ARII:$src), (MOVSXd32f8 MxARII8:$src)>; 563fe6060f1SDimitry Andric 564fe6060f1SDimitry Andric// i32 <- sext i16 565fe6060f1SDimitry Andricdef: Pat<(i32 (sext i16:$src)), (MOVSXd32d16 MxDRD16:$src)>; 566fe6060f1SDimitry Andricdef: Pat<(MxSExtLoadi32i16 MxCP_ARI :$src), (MOVSXd32j16 MxARI16 :$src)>; 567fe6060f1SDimitry Andricdef: Pat<(MxSExtLoadi32i16 MxCP_ARID:$src), (MOVSXd32p16 MxARID16:$src)>; 568fe6060f1SDimitry Andricdef: Pat<(MxSExtLoadi32i16 MxCP_ARII:$src), (MOVSXd32f16 MxARII16:$src)>; 569fe6060f1SDimitry Andric 570fe6060f1SDimitry Andric// i16 <- zext i8 571fe6060f1SDimitry Andricdef: Pat<(i16 (zext i8:$src)), 572fe6060f1SDimitry Andric (EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>; 573fe6060f1SDimitry Andricdef: Pat<(MxZExtLoadi16i8 MxCP_ARI:$src), 574fe6060f1SDimitry Andric (EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>; 575fe6060f1SDimitry Andricdef: Pat<(MxZExtLoadi16i8 MxCP_ARID:$src), 576fe6060f1SDimitry Andric (EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>; 577fe6060f1SDimitry Andricdef: Pat<(MxZExtLoadi16i8 MxCP_ARII:$src), 578fe6060f1SDimitry Andric (EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>; 579*06c3fb27SDimitry Andricdef: Pat<(MxZExtLoadi16i8 MxCP_PCD :$src), (MOVZXd16q8 MxPCD8 :$src)>; 580fe6060f1SDimitry Andric 581fe6060f1SDimitry Andric// i32 <- zext i8 582fe6060f1SDimitry Andricdef: Pat<(i32 (zext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>; 583fe6060f1SDimitry Andricdef: Pat<(MxZExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>; 584fe6060f1SDimitry Andricdef: Pat<(MxZExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>; 585fe6060f1SDimitry Andricdef: Pat<(MxZExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>; 586*06c3fb27SDimitry Andricdef: Pat<(MxZExtLoadi32i8 MxCP_PCD :$src), (MOVZXd32q8 MxPCD8 :$src)>; 587fe6060f1SDimitry Andric 588fe6060f1SDimitry Andric// i32 <- zext i16 589fe6060f1SDimitry Andricdef: Pat<(i32 (zext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>; 590fe6060f1SDimitry Andricdef: Pat<(MxZExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>; 591fe6060f1SDimitry Andricdef: Pat<(MxZExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>; 592fe6060f1SDimitry Andricdef: Pat<(MxZExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>; 593*06c3fb27SDimitry Andricdef: Pat<(MxZExtLoadi32i16 MxCP_PCD :$src), (MOVZXd32q16 MxPCD16 :$src)>; 594fe6060f1SDimitry Andric 595fe6060f1SDimitry Andric// i16 <- anyext i8 596fe6060f1SDimitry Andricdef: Pat<(i16 (anyext i8:$src)), 597fe6060f1SDimitry Andric (EXTRACT_SUBREG (MOVZXd32d8 MxDRD8:$src), MxSubRegIndex16Lo)>; 598fe6060f1SDimitry Andricdef: Pat<(MxExtLoadi16i8 MxCP_ARI:$src), 599fe6060f1SDimitry Andric (EXTRACT_SUBREG (MOVZXd32j8 MxARI8:$src), MxSubRegIndex16Lo)>; 600fe6060f1SDimitry Andricdef: Pat<(MxExtLoadi16i8 MxCP_ARID:$src), 601fe6060f1SDimitry Andric (EXTRACT_SUBREG (MOVZXd32p8 MxARID8:$src), MxSubRegIndex16Lo)>; 602fe6060f1SDimitry Andricdef: Pat<(MxExtLoadi16i8 MxCP_ARII:$src), 603fe6060f1SDimitry Andric (EXTRACT_SUBREG (MOVZXd32f8 MxARII8:$src), MxSubRegIndex16Lo)>; 604fe6060f1SDimitry Andric 605fe6060f1SDimitry Andric// i32 <- anyext i8 606fe6060f1SDimitry Andricdef: Pat<(i32 (anyext i8:$src)), (MOVZXd32d8 MxDRD8:$src)>; 607fe6060f1SDimitry Andricdef: Pat<(MxExtLoadi32i8 MxCP_ARI :$src), (MOVZXd32j8 MxARI8 :$src)>; 608fe6060f1SDimitry Andricdef: Pat<(MxExtLoadi32i8 MxCP_ARID:$src), (MOVZXd32p8 MxARID8:$src)>; 609fe6060f1SDimitry Andricdef: Pat<(MxExtLoadi32i8 MxCP_ARII:$src), (MOVZXd32f8 MxARII8:$src)>; 610fe6060f1SDimitry Andric 611fe6060f1SDimitry Andric// i32 <- anyext i16 612fe6060f1SDimitry Andricdef: Pat<(i32 (anyext i16:$src)), (MOVZXd32d16 MxDRD16:$src)>; 613fe6060f1SDimitry Andricdef: Pat<(MxExtLoadi32i16 MxCP_ARI :$src), (MOVZXd32j16 MxARI16 :$src)>; 614fe6060f1SDimitry Andricdef: Pat<(MxExtLoadi32i16 MxCP_ARID:$src), (MOVZXd32p16 MxARID16:$src)>; 615fe6060f1SDimitry Andricdef: Pat<(MxExtLoadi32i16 MxCP_ARII:$src), (MOVZXd32f16 MxARII16:$src)>; 616fe6060f1SDimitry Andric 617fe6060f1SDimitry Andric// trunc patterns 618fe6060f1SDimitry Andricdef : Pat<(i16 (trunc i32:$src)), 619fe6060f1SDimitry Andric (EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex16Lo)>; 620fe6060f1SDimitry Andricdef : Pat<(i8 (trunc i32:$src)), 621fe6060f1SDimitry Andric (EXTRACT_SUBREG MxXRD32:$src, MxSubRegIndex8Lo)>; 622fe6060f1SDimitry Andricdef : Pat<(i8 (trunc i16:$src)), 623fe6060f1SDimitry Andric (EXTRACT_SUBREG MxXRD16:$src, MxSubRegIndex8Lo)>; 624*06c3fb27SDimitry Andric 625*06c3fb27SDimitry Andric//===----------------------------------------------------------------------===// 626*06c3fb27SDimitry Andric// FMOVE 627*06c3fb27SDimitry Andric//===----------------------------------------------------------------------===// 628*06c3fb27SDimitry Andric 629*06c3fb27SDimitry Andriclet Defs = [FPS] in 630*06c3fb27SDimitry Andricclass MxFMove<string size, dag outs, dag ins, list<dag> pattern, 631*06c3fb27SDimitry Andric string rounding = ""> 632*06c3fb27SDimitry Andric : MxInst<outs, ins, 633*06c3fb27SDimitry Andric "f"#rounding#"move."#size#"\t$src, $dst", pattern> { 634*06c3fb27SDimitry Andric // Only FMOVE uses FPC 635*06c3fb27SDimitry Andric let Uses = !if(!eq(rounding, ""), [FPC], []); 636*06c3fb27SDimitry Andric 637*06c3fb27SDimitry Andric // FSMOVE and FDMOVE are only available after M68040 638*06c3fb27SDimitry Andric let Predicates = [!if(!eq(rounding, ""), AtLeastM68881, AtLeastM68040)]; 639*06c3fb27SDimitry Andric} 640*06c3fb27SDimitry Andric 641*06c3fb27SDimitry Andric// FPDR <- FPDR 642*06c3fb27SDimitry Andricclass MxFMove_FF<string rounding, int size, 643*06c3fb27SDimitry Andric MxOpBundle Opnd = !cast<MxOpBundle>("MxOp"#size#"AddrMode_fpr")> 644*06c3fb27SDimitry Andric : MxFMove<"x", (outs Opnd.Op:$dst), (ins Opnd.Op:$src), 645*06c3fb27SDimitry Andric [(null_frag)], rounding> { 646*06c3fb27SDimitry Andric let Inst = (ascend 647*06c3fb27SDimitry Andric (descend 0b1111, 648*06c3fb27SDimitry Andric /*COPROCESSOR ID*/0b001, 649*06c3fb27SDimitry Andric 0b000, 650*06c3fb27SDimitry Andric /*MODE + REGISTER*/0b000000 651*06c3fb27SDimitry Andric ), 652*06c3fb27SDimitry Andric (descend 0b0, /* R/M */0b0, 0b0, 653*06c3fb27SDimitry Andric /*SOURCE SPECIFIER*/ 654*06c3fb27SDimitry Andric (operand "$src", 3), 655*06c3fb27SDimitry Andric /*DESTINATION*/ 656*06c3fb27SDimitry Andric (operand "$dst", 3), 657*06c3fb27SDimitry Andric /*OPMODE*/ 658*06c3fb27SDimitry Andric !cond(!eq(rounding, "s"): 0b1000000, 659*06c3fb27SDimitry Andric !eq(rounding, "d"): 0b1000100, 660*06c3fb27SDimitry Andric true: 0b0000000) 661*06c3fb27SDimitry Andric ) 662*06c3fb27SDimitry Andric ); 663*06c3fb27SDimitry Andric} 664*06c3fb27SDimitry Andric 665*06c3fb27SDimitry Andricforeach rounding = ["", "s", "d"] in { 666*06c3fb27SDimitry Andric def F # !toupper(rounding) # MOV80fp_fp : MxFMove_FF<rounding, 80>; 667*06c3fb27SDimitry Andric 668*06c3fb27SDimitry Andric // We don't have `fmove.s` or `fmove.d` because values will be converted to 669*06c3fb27SDimitry Andric // f80 upon storing into the register, but FMOV32/64fp_fp are still needed 670*06c3fb27SDimitry Andric // to make codegen easier. 671*06c3fb27SDimitry Andric let isCodeGenOnly = true in 672*06c3fb27SDimitry Andric foreach size = [32, 64] in 673*06c3fb27SDimitry Andric def F # !toupper(rounding) # MOV # size # fp_fp : MxFMove_FF<rounding, size>; 674*06c3fb27SDimitry Andric} 675