Home | History | Annotate | Download | only in Mips
      1 //==- MipsScheduleP5600.td - P5600 Scheduling Definitions --*- tablegen -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 def MipsP5600Model : SchedMachineModel {
     11   int IssueWidth = 2; // 2x dispatched per cycle
     12   int MicroOpBufferSize = 48; // min(48, 48, 64)
     13   int LoadLatency = 4;
     14   int MispredictPenalty = 8; // TODO: Estimated
     15 
     16   let CompleteModel = 0;
     17   let FullInstRWOverlapCheck = 1;
     18 
     19   list<Predicate> UnsupportedFeatures = [HasMips32r6, HasMips64r6,
     20                                          HasMips3, HasMips64r2, HasCnMips,
     21                                          InMicroMips, InMips16Mode,
     22                                          HasDSP, HasDSPR2, HasMT, HasCRC];
     23 }
     24 
     25 let SchedModel = MipsP5600Model in {
     26 
     27 // ALQ Pipelines
     28 // =============
     29 
     30 def P5600ALQ : ProcResource<1> { let BufferSize = 16; }
     31 def P5600IssueALU : ProcResource<1> { let Super = P5600ALQ; }
     32 
     33 // ALU Pipeline
     34 // ------------
     35 
     36 def P5600WriteALU : SchedWriteRes<[P5600IssueALU]>;
     37 
     38 // and, lui, nor, or, slti, sltiu, sub, subu, xor
     39 def : InstRW<[P5600WriteALU], (instrs AND, LUi, NOR, OR, SLTi, SLTiu, SUB,
     40                                SUBu, XOR)>;
     41 
     42 // AGQ Pipelines
     43 // =============
     44 
     45 def P5600AGQ : ProcResource<3> { let BufferSize = 16; }
     46 def P5600IssueAL2 : ProcResource<1> { let Super = P5600AGQ; }
     47 def P5600IssueCTISTD : ProcResource<1> { let Super = P5600AGQ; }
     48 def P5600IssueLDST : ProcResource<1> { let Super = P5600AGQ; }
     49 
     50 def P5600AL2Div : ProcResource<1>;
     51 // Pseudo-resource used to block CTISTD when handling multi-pipeline splits.
     52 def P5600CTISTD : ProcResource<1>;
     53 
     54 // CTISTD Pipeline
     55 // ---------------
     56 
     57 def P5600WriteJump : SchedWriteRes<[P5600IssueCTISTD, P5600CTISTD]>;
     58 def P5600WriteJumpAndLink : SchedWriteRes<[P5600IssueCTISTD, P5600CTISTD]> {
     59   let Latency = 2;
     60 }
     61 
     62 // b, beq, beql, bg[et]z, bl[et]z, bne, bnel, j, syscall, jal, bltzal,
     63 // jalr, jr.hb, jr
     64 def : InstRW<[P5600WriteJump], (instrs B, BAL, BAL_BR, BEQ, BEQL, BGEZ, BGEZAL,
     65                                 BGEZALL, BGEZL, BGTZ, BGTZL, BLEZ, BLEZL, BLTZ,
     66                                 BLTZAL, BLTZALL, BLTZL, BNE, BNEL, BREAK,
     67                                 DERET, ERET, ERETNC, J, JR, JR_HB,
     68                                 PseudoIndirectBranch,
     69                                 PseudoIndirectHazardBranch, PseudoReturn,
     70                                 SDBBP, SSNOP, SYSCALL, TAILCALL, TAILCALLREG,
     71                                 TAILCALLREGHB, TEQ, TEQI, TGE, TGEI, TGEIU,
     72                                 TGEU, TLT, TLTI, TLTU, TNE, TNEI, TRAP,
     73                                 TTLTIU, WAIT, PAUSE)>;
     74 
     75 def : InstRW<[P5600WriteJumpAndLink], (instrs JAL, JALR, JALRHBPseudo,
     76                                        JALRPseudo, JALR_HB)>;
     77 
     78 def : InstRW<[P5600WriteJumpAndLink], (instrs JALX)> {
     79   let Unsupported = 1;
     80 }
     81 
     82 def P5600COP0 : SchedWriteRes<[P5600IssueCTISTD, P5600CTISTD]>;
     83 
     84 def : InstRW<[P5600COP0], (instrs TLBINV, TLBINVF, TLBP, TLBR, TLBWI, TLBWR,
     85                            MFC0, MTC0)>;
     86 
     87 def P5600COP2 : SchedWriteRes<[P5600IssueCTISTD, P5600CTISTD]>;
     88 
     89 def : InstRW<[P5600COP2], (instrs MFC2, MTC2)> {
     90   let Unsupported = 1;
     91 }
     92 
     93 // LDST Pipeline
     94 // -------------
     95 
     96 def P5600WriteLoad : SchedWriteRes<[P5600IssueLDST]> {
     97   let Latency = 4;
     98 }
     99 
    100 def P5600WriteLoadShifted : SchedWriteRes<[P5600IssueLDST, P5600CTISTD]> {
    101   let Latency = 4;
    102 }
    103 
    104 def P5600WriteCache : SchedWriteRes<[P5600IssueLDST]>;
    105 
    106 def P5600WriteStore : SchedWriteRes<[P5600IssueLDST, P5600CTISTD]> {
    107   // FIXME: This is a bit pessimistic. P5600CTISTD is only used during cycle 2
    108   //        not during 0, 1, and 2.
    109   let ResourceCycles = [ 1, 3 ];
    110 }
    111 
    112 def P5600WriteGPRFromBypass : SchedWriteRes<[P5600IssueLDST]> {
    113   let Latency = 2;
    114 }
    115 
    116 def P5600WriteStoreFromOtherUnits : SchedWriteRes<[P5600IssueLDST]>;
    117 def P5600WriteLoadToOtherUnits : SchedWriteRes<[P5600IssueLDST]> {
    118   let Latency = 0;
    119 }
    120 
    121 // l[bhw], l[bh]u, ll
    122 def : InstRW<[P5600WriteLoad], (instrs LB, LBu, LH, LHu, LW, LL, LWC2, LWC3,
    123                                 LDC2, LDC3, LBE, LBuE, LHE, LHuE, LWE, LLE,
    124                                 LWPC)>;
    125 
    126 // lw[lr]
    127 def : InstRW<[P5600WriteLoadShifted], (instrs LWL, LWR, LWLE, LWRE)>;
    128 
    129 // s[bhw], sw[lr]
    130 def : InstRW<[P5600WriteStore], (instrs SB, SH, SW, SWC2, SWC3, SDC2, SDC3, SC,
    131                                  SBE, SHE, SWE, SCE, SWL, SWR, SWLE, SWRE)>;
    132 
    133 // pref, cache, sync, synci
    134 def : InstRW<[P5600WriteCache], (instrs PREF, PREFE, CACHE, CACHEE, SYNC,
    135                                  SYNCI)>;
    136 
    137 // LDST is also used in moves from general purpose registers to floating point
    138 // and MSA.
    139 def P5600WriteMoveGPRToOtherUnits : SchedWriteRes<[P5600IssueLDST]> {
    140   let Latency = 0;
    141 }
    142 
    143 // AL2 Pipeline
    144 // ------------
    145 
    146 def P5600WriteAL2 : SchedWriteRes<[P5600IssueAL2]>;
    147 def P5600WriteAL2BitExt : SchedWriteRes<[P5600IssueAL2]> { let Latency = 2; }
    148 def P5600WriteAL2ShadowMov : SchedWriteRes<[P5600IssueAL2]> { let Latency = 2; }
    149 def P5600WriteAL2CondMov : SchedWriteRes<[P5600IssueAL2, P5600CTISTD]> {
    150   let Latency = 2;
    151 }
    152 def P5600WriteAL2Div : SchedWriteRes<[P5600IssueAL2, P5600AL2Div]> {
    153   // Estimated worst case
    154   let Latency = 34;
    155   let ResourceCycles = [1, 34];
    156 }
    157 def P5600WriteAL2DivU : SchedWriteRes<[P5600IssueAL2, P5600AL2Div]> {
    158   // Estimated worst case
    159   let Latency = 34;
    160   let ResourceCycles = [1, 34];
    161 }
    162 def P5600WriteAL2Mul : SchedWriteRes<[P5600IssueAL2]> { let Latency = 3; }
    163 def P5600WriteAL2Mult: SchedWriteRes<[P5600IssueAL2]> { let Latency = 5; }
    164 def P5600WriteAL2MAdd: SchedWriteRes<[P5600IssueAL2, P5600CTISTD]> {
    165   let Latency = 5;
    166 }
    167 
    168 // clo, clz, di, ei, mfhi, mflo
    169 def : InstRW<[P5600WriteAL2], (instrs CLO, CLZ, DI, EI, MFHI, MFLO,
    170                                PseudoMFHI, PseudoMFLO)>;
    171 
    172 // ehb, rdhwr, rdpgpr, wrpgpr, wsbh
    173 def : InstRW<[P5600WriteAL2ShadowMov], (instrs EHB, RDHWR, WSBH)>;
    174 
    175 // mov[nz]
    176 def : InstRW<[P5600WriteAL2CondMov], (instrs MOVN_I_I, MOVZ_I_I)>;
    177 
    178 // divu?
    179 def : InstRW<[P5600WriteAL2Div], (instrs DIV, PseudoSDIV, SDIV)>;
    180 def : InstRW<[P5600WriteAL2DivU], (instrs DIVU, PseudoUDIV, UDIV)>;
    181 
    182 // mul
    183 def : InstRW<[P5600WriteAL2Mul], (instrs MUL)>;
    184 // multu?, multu?
    185 def : InstRW<[P5600WriteAL2Mult], (instrs MULT, MULTu, PseudoMULT,
    186                                    PseudoMULTu)>;
    187 // maddu?, msubu?, mthi, mtlo
    188 def : InstRW<[P5600WriteAL2MAdd], (instrs MADD, MADDU, MSUB, MSUBU,
    189                                    MTHI, MTLO, PseudoMADD, PseudoMADDU,
    190                                    PseudoMSUB, PseudoMSUBU, PseudoMTLOHI)>;
    191 
    192 // ext, ins
    193 def : InstRW<[P5600WriteAL2BitExt], (instrs EXT, INS)>;
    194 
    195 // Either ALU or AL2 Pipelines
    196 // ---------------------------
    197 //
    198 // Some instructions can choose between ALU and AL2, but once dispatched to
    199 // ALQ or AGQ respectively they are committed to that path.
    200 // The decision is based on the outcome of the most recent selection when the
    201 // choice was last available. For now, we assume ALU is always chosen.
    202 
    203 def P5600WriteEitherALU : SchedWriteVariant<
    204   // FIXME: Implement selection predicate
    205   [SchedVar<SchedPredicate<[{1}]>, [P5600WriteALU]>,
    206    SchedVar<SchedPredicate<[{0}]>, [P5600WriteAL2]>
    207   ]>;
    208 
    209 // add, addi, addiu, addu, andi, ori, rotr, se[bh], sllv?, sr[al]v?, slt, sltu,
    210 // xori
    211 def : InstRW<[P5600WriteEitherALU], (instrs ADD, ADDi, ADDiu, ANDi, ORi, ROTR,
    212                                      SEB, SEH, SLT, SLTu, SLL, SRA, SRL, XORi,
    213                                      ADDu, SLLV, SRAV, SRLV, LSA, COPY)>;
    214 
    215 // FPU Pipelines
    216 // =============
    217 
    218 def P5600FPQ : ProcResource<3> { let BufferSize = 16; }
    219 def P5600IssueFPUS : ProcResource<1> { let Super = P5600FPQ; }
    220 def P5600IssueFPUL : ProcResource<1> { let Super = P5600FPQ; }
    221 def P5600IssueFPULoad : ProcResource<1> { let Super = P5600FPQ; }
    222 
    223 def P5600FPUDivSqrt : ProcResource<2>;
    224 
    225 def P5600WriteFPUS : SchedWriteRes<[P5600IssueFPUS]>;
    226 def P5600WriteFPUL : SchedWriteRes<[P5600IssueFPUL]> { let Latency = 4; }
    227 def P5600WriteFPUL_MADDSUB : SchedWriteRes<[P5600IssueFPUL]> { let Latency = 6; }
    228 def P5600WriteFPUDivI : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> {
    229   // Best/Common/Worst case = 7 / 23 / 27
    230   let Latency = 23; // Using common case
    231   let ResourceCycles = [ 1, 23 ];
    232 }
    233 def P5600WriteFPUDivS : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> {
    234   // Best/Common/Worst case = 7 / 23 / 27
    235   let Latency = 23; // Using common case
    236   let ResourceCycles = [ 1, 23 ];
    237 }
    238 def P5600WriteFPUDivD : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> {
    239   // Best/Common/Worst case = 7 / 31 / 35
    240   let Latency = 31; // Using common case
    241   let ResourceCycles = [ 1, 31 ];
    242 }
    243 def P5600WriteFPURcpS : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> {
    244   // Best/Common/Worst case = 7 / 19 / 23
    245   let Latency = 19; // Using common case
    246   let ResourceCycles = [ 1, 19 ];
    247 }
    248 def P5600WriteFPURcpD : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> {
    249   // Best/Common/Worst case = 7 / 27 / 31
    250   let Latency = 27; // Using common case
    251   let ResourceCycles = [ 1, 27 ];
    252 }
    253 def P5600WriteFPURsqrtS : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> {
    254   // Best/Common/Worst case = 7 / 27 / 27
    255   let Latency = 27; // Using common case
    256   let ResourceCycles = [ 1, 27 ];
    257 }
    258 def P5600WriteFPURsqrtD : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> {
    259   // Best/Common/Worst case = 7 / 27 / 31
    260   let Latency = 27; // Using common case
    261   let ResourceCycles = [ 1, 27 ];
    262 }
    263 def P5600WriteFPUSqrtS : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> {
    264   // Best/Common/Worst case = 7 / 27 / 31
    265   let Latency = 27; // Using common case
    266   let ResourceCycles = [ 1, 27 ];
    267 }
    268 def P5600WriteFPUSqrtD : SchedWriteRes<[P5600IssueFPUL, P5600FPUDivSqrt]> {
    269   // Best/Common/Worst case = 7 / 35 / 39
    270   let Latency = 35; // Using common case
    271   let ResourceCycles = [ 1, 35 ];
    272 }
    273 def P5600WriteMSAShortLogic : SchedWriteRes<[P5600IssueFPUS]>;
    274 def P5600WriteMSAShortInt : SchedWriteRes<[P5600IssueFPUS]> { let Latency = 2; }
    275 def P5600WriteMoveOtherUnitsToFPU : SchedWriteRes<[P5600IssueFPUS]>;
    276 def P5600WriteMSAOther3 : SchedWriteRes<[P5600IssueFPUS]> { let Latency = 3; }
    277 def P5600WriteMSALongInt : SchedWriteRes<[P5600IssueFPUS]> { let Latency = 5; }
    278 
    279 // vshf.[bhwd], binsl.[bhwd], binsr.[bhwd], insert.[bhwd], sld?.[bhwd],
    280 // bset.[bhwd], bclr.[bhwd], bneg.[bhwd], bsel_v, bseli_b
    281 def : InstRW<[P5600WriteMSAShortInt], (instregex "^VSHF_[BHWD]$")>;
    282 def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BINSL|BINSLI)_[BHWD]$")>;
    283 def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BINSR|BINSRI)_[BHWD]$")>;
    284 def : InstRW<[P5600WriteMSAShortInt], (instregex "^INSERT_[BHWD]$")>;
    285 def : InstRW<[P5600WriteMSAShortInt], (instregex "^(SLD|SLDI)_[BHWD]$")>;
    286 def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BSET|BSETI)_[BHWD]$")>;
    287 def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BCLR|BCLRI)_[BHWD]$")>;
    288 def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BNEG|BNEGI)_[BHWD]$")>;
    289 def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BSEL_V|BSELI_B)$")>;
    290 def : InstRW<[P5600WriteMSAShortInt], (instregex "^BMN*Z.*$")>;
    291 
    292 // pcnt.[bhwd], sat_s.[bhwd], sat_u.bhwd]
    293 def : InstRW<[P5600WriteMSAOther3], (instregex "^PCNT_[BHWD]$")>;
    294 def : InstRW<[P5600WriteMSAOther3], (instregex "^SAT_(S|U)_[BHWD]$")>;
    295 
    296 // bnz.[bhwdv], cfcmsa, ctcmsa
    297 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(BNZ|BZ)_[BHWDV]$")>;
    298 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^C(F|T)CMSA$")>;
    299 
    300 // FPUS is also used in moves from floating point and MSA registers to general
    301 // purpose registers.
    302 def P5600WriteMoveFPUSToOtherUnits : SchedWriteRes<[P5600IssueFPUS]> {
    303   let Latency = 0;
    304 }
    305 
    306 // FPUL is also used in moves from floating point and MSA registers to general
    307 // purpose registers.
    308 def P5600WriteMoveFPULToOtherUnits : SchedWriteRes<[P5600IssueFPUL]>;
    309 
    310 // Short Pipe
    311 // ----------
    312 //
    313 // abs.[ds], abs.ps, bc1[tf]l?, mov[tf].[ds], mov[tf], mov.[ds], [cm][ft]c1,
    314 // m[ft]hc1, neg.[ds], neg.ps, nor.v, nori.b, or.v, ori.b, xor.v, xori.b,
    315 // sdxc1, sdc1, st.[bhwd], swc1, swxc1
    316 def : InstRW<[P5600WriteFPUS], (instrs FABS_S, FABS_D32, FABS_D64, MOVF_D32,
    317                                 MOVF_D64, MOVF_S, MOVT_D32, MOVT_D64,
    318                                 MOVT_S, FMOV_D32, FMOV_D64, FMOV_S, FNEG_S,
    319                                 FNEG_D32, FNEG_D64)>;
    320 
    321 // adds_a.[bhwd], adds_[asu].[bhwd], addvi?.[bhwd], asub_[us].[bhwd],
    322 // aver?_[us].[bhwd], shf.[bhw], fill[bhwd], splat?.[bhwd]
    323 def : InstRW<[P5600WriteMSAShortInt], (instregex "^ADD_A_[BHWD]$")>;
    324 def : InstRW<[P5600WriteMSAShortInt], (instregex "^ADDS_[ASU]_[BHWD]$")>;
    325 // TODO: ADDVI_[BHW] might be 1 cycle latency rather than 2. Need to confirm it.
    326 def : InstRW<[P5600WriteMSAShortInt], (instregex "^ADDVI?_[BHWD]$")>;
    327 def : InstRW<[P5600WriteMSAShortInt], (instregex "^ASUB_[US].[BHWD]$")>;
    328 def : InstRW<[P5600WriteMSAShortInt], (instregex "^AVER?_[US].[BHWD]$")>;
    329 def : InstRW<[P5600WriteMSAShortInt], (instregex "^SHF_[BHW]$")>;
    330 def : InstRW<[P5600WriteMSAShortInt], (instregex "^FILL_[BHWD]$")>;
    331 def : InstRW<[P5600WriteMSAShortInt], (instregex "^(SPLAT|SPLATI)_[BHWD]$")>;
    332 
    333 // and.v, andi.b, move.v, ldi.[bhwd]
    334 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^MOVE_V$")>;
    335 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^LDI_[BHWD]$")>;
    336 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)_V$")>;
    337 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)I_B$")>;
    338 
    339 // fexp2_w, fexp2_d
    340 def : InstRW<[P5600WriteFPUS], (instregex "^FEXP2_(W|D)$")>;
    341 
    342 // compare, converts, round to int, floating point truncate.
    343 def : InstRW<[P5600WriteFPUS], (instregex "^(CLT|CLTI)_(S|U)_[BHWD]$")>;
    344 def : InstRW<[P5600WriteFPUS], (instregex "^(CLE|CLEI)_(S|U)_[BHWD]$")>;
    345 def : InstRW<[P5600WriteFPUS], (instregex "^(CEQ|CEQI)_[BHWD]$")>;
    346 def : InstRW<[P5600WriteFPUS], (instregex "^CMP_UN_(S|D)$")>;
    347 def : InstRW<[P5600WriteFPUS], (instregex "^CMP_UEQ_(S|D)$")>;
    348 def : InstRW<[P5600WriteFPUS], (instregex "^CMP_EQ_(S|D)$")>;
    349 def : InstRW<[P5600WriteFPUS], (instregex "^CMP_LT_(S|D)$")>;
    350 def : InstRW<[P5600WriteFPUS], (instregex "^CMP_ULT_(S|D)$")>;
    351 def : InstRW<[P5600WriteFPUS], (instregex "^CMP_LE_(S|D)$")>;
    352 def : InstRW<[P5600WriteFPUS], (instregex "^CMP_ULE_(S|D)$")>;
    353 def : InstRW<[P5600WriteFPUS], (instregex "^FS(AF|EQ|LT|LE|NE|OR)_(W|D)$")>;
    354 def : InstRW<[P5600WriteFPUS], (instregex "^FSUEQ_(W|D)$")>;
    355 def : InstRW<[P5600WriteFPUS], (instregex "^FSULE_(W|D)$")>;
    356 def : InstRW<[P5600WriteFPUS], (instregex "^FSULT_(W|D)$")>;
    357 def : InstRW<[P5600WriteFPUS], (instregex "^FSUNE_(W|D)$")>;
    358 def : InstRW<[P5600WriteFPUS], (instregex "^FSUN_(W|D)$")>;
    359 def : InstRW<[P5600WriteFPUS], (instregex "^FCAF_(W|D)$")>;
    360 def : InstRW<[P5600WriteFPUS], (instregex "^FCEQ_(W|D)$")>;
    361 def : InstRW<[P5600WriteFPUS], (instregex "^FCLE_(W|D)$")>;
    362 def : InstRW<[P5600WriteFPUS], (instregex "^FCLT_(W|D)$")>;
    363 def : InstRW<[P5600WriteFPUS], (instregex "^FCNE_(W|D)$")>;
    364 def : InstRW<[P5600WriteFPUS], (instregex "^FCOR_(W|D)$")>;
    365 def : InstRW<[P5600WriteFPUS], (instregex "^FCUEQ_(W|D)$")>;
    366 def : InstRW<[P5600WriteFPUS], (instregex "^FCULE_(W|D)$")>;
    367 def : InstRW<[P5600WriteFPUS], (instregex "^FCULT_(W|D)$")>;
    368 def : InstRW<[P5600WriteFPUS], (instregex "^FCUNE_(W|D)$")>;
    369 def : InstRW<[P5600WriteFPUS], (instregex "^FCUN_(W|D)$")>;
    370 def : InstRW<[P5600WriteFPUS], (instregex "^FABS_(W|D)$")>;
    371 def : InstRW<[P5600WriteFPUS], (instregex "^FFINT_(U|S)_(W|D)$")>;
    372 def : InstRW<[P5600WriteFPUS], (instregex "^FFQL_(W|D)$")>;
    373 def : InstRW<[P5600WriteFPUS], (instregex "^FFQR_(W|D)$")>;
    374 def : InstRW<[P5600WriteFPUS], (instregex "^FTINT_(U|S)_(W|D)$")>;
    375 def : InstRW<[P5600WriteFPUS], (instregex "^FRINT_(W|D)$")>;
    376 def : InstRW<[P5600WriteFPUS], (instregex "^FTQ_(H|W)$")>;
    377 def : InstRW<[P5600WriteFPUS], (instregex "^FTRUNC_(U|S)_(W|D)$")>;
    378 
    379 // fexdo.[hw], fexupl.[wd], fexupr.[wd]
    380 def : InstRW<[P5600WriteFPUS], (instregex "^FEXDO_(H|W)$")>;
    381 def : InstRW<[P5600WriteFPUS], (instregex "^FEXUPL_(W|D)$")>;
    382 def : InstRW<[P5600WriteFPUS], (instregex "^FEXUPR_(W|D)$")>;
    383 
    384 // fclass.[wd], fmax.[wd], fmax_a.[wd], fmin.[wd], fmin_a.[wd], flog2.[wd]
    385 def : InstRW<[P5600WriteFPUS], (instregex "^FCLASS_(W|D)$")>;
    386 def : InstRW<[P5600WriteFPUS], (instregex "^FMAX_A_(W|D)$")>;
    387 def : InstRW<[P5600WriteFPUS], (instregex "^FMAX_(W|D)$")>;
    388 def : InstRW<[P5600WriteFPUS], (instregex "^FMIN_A_(W|D)$")>;
    389 def : InstRW<[P5600WriteFPUS], (instregex "^FMIN_(W|D)$")>;
    390 def : InstRW<[P5600WriteFPUS], (instregex "^FLOG2_(W|D)$")>;
    391 
    392 // interleave right/left, interleave even/odd, insert
    393 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(ILVR|ILVL)_[BHWD]$")>;
    394 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(ILVEV|ILVOD)_[BHWD]$")>;
    395 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^INSVE_[BHWD]$")>;
    396 
    397 // subs_?.[bhwd], subsus_?.[bhwd], subsuu_?.[bhwd], subvi.[bhwd], subv.[bhwd],
    398 def : InstRW<[P5600WriteMSAShortInt], (instregex "^SUBS_(S|U)_[BHWD]$")>;
    399 def : InstRW<[P5600WriteMSAShortInt], (instregex "^SUBSUS_(S|U)_[BHWD]$")>;
    400 def : InstRW<[P5600WriteMSAShortInt], (instregex "^SUBSUU_(S|U)_[BHWD]$")>;
    401 def : InstRW<[P5600WriteMSAShortInt], (instregex "^SUBVI_[BHWD]$")>;
    402 def : InstRW<[P5600WriteMSAShortInt], (instregex "^SUBV_[BHWD]$")>;
    403 
    404 // mod_[su].[bhwd], div_[su].[bhwd]
    405 def : InstRW<[P5600WriteFPUDivI], (instregex "^MOD_(S|U)_[BHWD]$")>;
    406 def : InstRW<[P5600WriteFPUDivI], (instregex "^DIV_(S|U)_[BHWD]$")>;
    407 
    408 // hadd_[su].[bhwd], hsub_[su].[bhwd], max_[sua].[bhwd], min_[sua].[bhwd],
    409 // maxi_[su].[bhwd], mini_[su].[bhwd], sra?.[bhwd], srar?.[bhwd], srlr.[bhwd],
    410 // sll?.[bhwd], pckev.[bhwd], pckod.[bhwd], nloc.[bhwd], nlzc.[bhwd],
    411 // insve.[bhwd]
    412 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^HADD_(S|U)_[BHWD]$")>;
    413 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^HSUB_(S|U)_[BHWD]$")>;
    414 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(MAX|MIN)_S_[BHWD]$")>;
    415 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(MAX|MIN)_U_[BHWD]$")>;
    416 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(MAX|MIN)_A_[BHWD]$")>;
    417 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(MAXI|MINI)_(S|U)_[BHWD]$")>;
    418 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(SRA|SRAI)_[BHWD]$")>;
    419 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(SRL|SRLI)_[BHWD]$")>;
    420 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(SRAR|SRARI)_[BHWD]$")>;
    421 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(SRLR|SRLRI)_[BHWD]$")>;
    422 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(SLL|SLLI)_[BHWD]$")>;
    423 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(PCKEV|PCKOD)_[BHWD]$")>;
    424 def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(NLOC|NLZC)_[BHWD]$")>;
    425 
    426 // Long Pipe
    427 // ----------
    428 //
    429 // add.[ds], add.ps, cvt.d.[sw], cvt.s.[dw], cvt.w.[sd], cvt.[sw].ps,
    430 // cvt.ps.[sw], c.<cc>.[ds], c.<cc>.ps, mul.[ds], mul.ps, sub.[ds], sub.ps,
    431 // trunc.w.[ds], trunc.w.ps
    432 def : InstRW<[P5600WriteFPUL],
    433              (instrs FADD_D32, FADD_D64, FADD_S, FMUL_D32, FMUL_D64, FMUL_S,
    434               FSUB_D32, FSUB_D64, FSUB_S)>;
    435 def : InstRW<[P5600WriteFPUL], (instregex "^TRUNC_(L|W)_(S|D32|D64)$")>;
    436 def : InstRW<[P5600WriteFPUL],
    437              (instregex "^CVT_(S|D32|D64|L|W)_(S|D32|D64|L|W)$")>;
    438 def : InstRW<[P5600WriteFPUL], (instregex "^C_[A-Z]+_(S|D32|D64)$")>;
    439 def : InstRW<[P5600WriteFPUL], (instregex "^FCMP_(S32|D32|D64)$")>;
    440 def : InstRW<[P5600WriteFPUL], (instregex "^PseudoCVT_(S|D32|D64)_(L|W)$")>;
    441 
    442 // div.[ds], div.ps
    443 def : InstRW<[P5600WriteFPUDivS], (instrs FDIV_S)>;
    444 def : InstRW<[P5600WriteFPUDivD], (instrs FDIV_D32, FDIV_D64)>;
    445 
    446 // sqrt.[ds], sqrt.ps
    447 def : InstRW<[P5600WriteFPUSqrtS], (instrs FSQRT_S)>;
    448 def : InstRW<[P5600WriteFPUSqrtD], (instrs FSQRT_D32, FSQRT_D64)>;
    449 
    450 // frcp.[wd], frsqrt.[wd]
    451 def : InstRW<[P5600WriteFPURsqrtD], (instregex "^FRCP_(W|D)$")>;
    452 def : InstRW<[P5600WriteFPURsqrtD], (instregex "^FRSQRT_(W|D)$")>;
    453 
    454 def : InstRW<[P5600WriteFPURsqrtD], (instrs RECIP_D32, RECIP_D64, RSQRT_D32,
    455                                      RSQRT_D64)>;
    456 def : InstRW<[P5600WriteFPURsqrtS], (instrs RECIP_S, RSQRT_S)>;
    457 
    458 // fmadd.[wd], fmsubb.[wd], fdiv.[wd], fsqrt.[wd], fmul.[wd], fadd.[wd],
    459 // fsub.[wd]
    460 def : InstRW<[P5600WriteFPUL_MADDSUB], (instregex "^FMADD_(W|D)$")>;
    461 def : InstRW<[P5600WriteFPUL_MADDSUB], (instregex "^FMSUB_(W|D)$")>;
    462 def : InstRW<[P5600WriteFPUDivS], (instregex "^FDIV_W$")>;
    463 def : InstRW<[P5600WriteFPUDivD], (instregex "^FDIV_D$")>;
    464 def : InstRW<[P5600WriteFPUSqrtS], (instregex "^FSQRT_W$")>;
    465 def : InstRW<[P5600WriteFPUSqrtD], (instregex "^FSQRT_D$")>;
    466 def : InstRW<[P5600WriteFPUL], (instregex "^FMUL_(W|D)$")>;
    467 def : InstRW<[P5600WriteFPUL], (instregex "^FADD_(W|D)$")>;
    468 def : InstRW<[P5600WriteFPUL], (instregex "^FSUB_(W|D)$")>;
    469 
    470 // dpadd_?.[bhwd], dpsub_?.[bhwd], dotp_?.[bhwd], msubv.[bhwd], maddv.[bhwd]
    471 // mulv.[bhwd].
    472 def : InstRW<[P5600WriteMSALongInt], (instregex "^DPADD_(S|U)_[HWD]$")>;
    473 def : InstRW<[P5600WriteMSALongInt], (instregex "^DPSUB_(S|U)_[HWD]$")>;
    474 def : InstRW<[P5600WriteMSALongInt], (instregex "^DOTP_(S|U)_[HWD]$")>;
    475 def : InstRW<[P5600WriteMSALongInt], (instregex "^MSUBV_[BHWD]$")>;
    476 def : InstRW<[P5600WriteMSALongInt], (instregex "^MADDV_[BHWD]$")>;
    477 def : InstRW<[P5600WriteMSALongInt], (instregex "^MULV_[BHWD]$")>;
    478 
    479 def : InstRW<[P5600WriteMSALongInt], (instregex "^MADDR_Q_[HW]$")>;
    480 def : InstRW<[P5600WriteMSALongInt], (instregex "^MADD_Q_[HW]$")>;
    481 def : InstRW<[P5600WriteMSALongInt], (instregex "^MSUBR_Q_[HW]$")>;
    482 def : InstRW<[P5600WriteMSALongInt], (instregex "^MSUB_Q_[HW]$")>;
    483 def : InstRW<[P5600WriteMSALongInt], (instregex "^MULR_Q_[HW]$")>;
    484 def : InstRW<[P5600WriteMSALongInt], (instregex "^MUL_Q_[HW]$")>;
    485 
    486 // madd.[ds], msub.[ds], nmadd.[ds], nmsub.[ds],
    487 // Operand 0 is read on cycle 5. All other operands are read on operand 0.
    488 def : InstRW<[SchedReadAdvance<5>, P5600WriteFPUL_MADDSUB],
    489              (instrs MADD_D32, MADD_D64, MADD_S, MSUB_D32, MSUB_D64, MSUB_S,
    490               NMADD_D32, NMADD_D64, NMADD_S, NMSUB_D32, NMSUB_D64, NMSUB_S)>;
    491 
    492 // madd.ps, msub.ps, nmadd.ps, nmsub.ps
    493 // Operand 0 and 1 are read on cycle 5. All others are read on operand 0.
    494 // (none of these instructions exist in the backend yet)
    495 
    496 // Load Pipe
    497 // ---------
    498 //
    499 // This is typically used in conjunction with the load pipeline under the AGQ
    500 // All the instructions are in the 'Tricky Instructions' section.
    501 
    502 def P5600WriteLoadOtherUnitsToFPU : SchedWriteRes<[P5600IssueFPULoad]> {
    503   let Latency = 4;
    504 }
    505 
    506 // Tricky Instructions
    507 // ===================
    508 //
    509 // These instructions are split across multiple uops (in different pipelines)
    510 // that must cooperate to complete the operation
    511 
    512 // FIXME: This isn't quite right since the implementation of WriteSequence
    513 //        current aggregates the resources and ignores the exact cycle they are
    514 //        used.
    515 def P5600WriteMoveGPRToFPU : WriteSequence<[P5600WriteMoveGPRToOtherUnits,
    516                                             P5600WriteMoveOtherUnitsToFPU]>;
    517 
    518 // FIXME: This isn't quite right since the implementation of WriteSequence
    519 //        current aggregates the resources and ignores the exact cycle they are
    520 //        used.
    521 def P5600WriteMoveFPUToGPR : WriteSequence<[P5600WriteMoveFPUSToOtherUnits,
    522                                             P5600WriteGPRFromBypass]>;
    523 
    524 // FIXME: This isn't quite right since the implementation of WriteSequence
    525 //        current aggregates the resources and ignores the exact cycle they are
    526 //        used.
    527 def P5600WriteStoreFPUS : WriteSequence<[P5600WriteMoveFPUSToOtherUnits,
    528                                          P5600WriteStoreFromOtherUnits]>;
    529 
    530 // FIXME: This isn't quite right since the implementation of WriteSequence
    531 //        current aggregates the resources and ignores the exact cycle they are
    532 //        used.
    533 def P5600WriteStoreFPUL : WriteSequence<[P5600WriteMoveFPULToOtherUnits,
    534                                          P5600WriteStoreFromOtherUnits]>;
    535 
    536 // FIXME: This isn't quite right since the implementation of WriteSequence
    537 //        current aggregates the resources and ignores the exact cycle they are
    538 //        used.
    539 def P5600WriteLoadFPU : WriteSequence<[P5600WriteLoadToOtherUnits,
    540                                        P5600WriteLoadOtherUnitsToFPU]>;
    541 
    542 // ctc1, mtc1, mthc1
    543 def : InstRW<[P5600WriteMoveGPRToFPU], (instrs CTC1, MTC1, MTC1_D64, MTHC1_D32,
    544                                         MTHC1_D64, BuildPairF64,
    545                                         BuildPairF64_64)>;
    546 
    547 // copy.[su]_[bhwd]
    548 def : InstRW<[P5600WriteMoveFPUToGPR], (instregex "^COPY_U_[BHW]$")>;
    549 def : InstRW<[P5600WriteMoveFPUToGPR], (instregex "^COPY_S_[BHWD]$")>;
    550 
    551 // bc1[ft], cfc1, mfc1, mfhc1, movf, movt
    552 def : InstRW<[P5600WriteMoveFPUToGPR], (instrs BC1F, BC1FL, BC1T, BC1TL, CFC1,
    553                                         MFC1, MFC1_D64, MFHC1_D32, MFHC1_D64,
    554                                         MOVF_I, MOVT_I, ExtractElementF64,
    555                                         ExtractElementF64_64)>;
    556 
    557 // swc1, swxc1, st.[bhwd]
    558 def : InstRW<[P5600WriteStoreFPUS], (instrs SDC1, SDXC1, SUXC1, SWC1, SWXC1)>;
    559 def : InstRW<[P5600WriteStoreFPUS], (instregex "^ST_[BHWD]$")>;
    560 
    561 // movn.[ds], movz.[ds]
    562 def : InstRW<[P5600WriteStoreFPUL], (instrs MOVN_I_D32, MOVN_I_D64, MOVN_I_S,
    563                                      MOVZ_I_D32, MOVZ_I_D64, MOVZ_I_S)>;
    564 
    565 // l[dw]x?c1, ld.[bhwd]
    566 def : InstRW<[P5600WriteLoadFPU], (instrs LDC1, LDXC1, LWC1, LWXC1, LUXC1)>;
    567 def : InstRW<[P5600WriteLoadFPU], (instregex "LD_[BHWD]")>;
    568 
    569 // Unsupported Instructions
    570 // ========================
    571 //
    572 // The following instruction classes are never valid on P5600.
    573 //   II_DADDIU, II_DADDU, II_DMFC1, II_DMTC1, II_DMULT, II_DMULTU, II_DROTR,
    574 //   II_DROTR32, II_DROTRV, II_DDIV, II_DSLL, II_DSLL32, II_DSLLV, II_DSRA,
    575 //   II_DSRA32, II_DSRAV, II_DSRL, II_DSRL32, II_DSRLV, II_DSUBU, II_DDIVU,
    576 //   II_JALRC, II_LD, II_LD[LR], II_RESTORE, II_SAVE, II_SD, II_SDC1, II_SD[LR]
    577 //
    578 // The following instructions are never valid on P5600.
    579 //   addq.ph, repl.ph, repl.qb, subq.ph, subu_s.qb
    580 //
    581 // Guesswork
    582 // =========
    583 //
    584 // This section is largely temporary guesswork.
    585 
    586 // ceil.[lw].[ds], floor.[lw].[ds]
    587 // Reason behind guess: trunc.[lw].ds and the various cvt's are in FPUL
    588 def : InstRW<[P5600WriteFPUL], (instregex "^CEIL_(L|W)_(S|D32|D64)$")>;
    589 def : InstRW<[P5600WriteFPUL], (instregex "^FLOOR_(L|W)_(S|D32|D64)$")>;
    590 def : InstRW<[P5600WriteFPUL], (instregex "^ROUND_(L|W)_(S|D32|D64)$")>;
    591 
    592 // rotrv
    593 // Reason behind guess: rotr is in the same category and the two register forms
    594 //                      generally follow the immediate forms in this category
    595 def : InstRW<[P5600WriteEitherALU], (instrs ROTRV)>;
    596 }
    597