|  | //===-- SparcV9SchedInfo.cpp ----------------------------------------------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file was developed by the LLVM research group and is distributed under | 
|  | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // Describe the scheduling characteristics of the UltraSparc IIi. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "SparcV9Internals.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | /*--------------------------------------------------------------------------- | 
|  | Scheduling guidelines for SPARC IIi: | 
|  |  | 
|  | I-Cache alignment rules (pg 326) | 
|  | -- Align a branch target instruction so that it's entire group is within | 
|  | the same cache line (may be 1-4 instructions). | 
|  | ** Don't let a branch that is predicted taken be the last instruction | 
|  | on an I-cache line: delay slot will need an entire line to be fetched | 
|  | -- Make a FP instruction or a branch be the 4th instruction in a group. | 
|  | For branches, there are tradeoffs in reordering to make this happen | 
|  | (see pg. 327). | 
|  | ** Don't put a branch in a group that crosses a 32-byte boundary! | 
|  | An artificial branch is inserted after every 32 bytes, and having | 
|  | another branch will force the group to be broken into 2 groups. | 
|  |  | 
|  | iTLB rules: | 
|  | -- Don't let a loop span two memory pages, if possible | 
|  |  | 
|  | Branch prediction performance: | 
|  | -- Don't make the branch in a delay slot the target of a branch | 
|  | -- Try not to have 2 predicted branches within a group of 4 instructions | 
|  | (because each such group has a single branch target field). | 
|  | -- Try to align branches in slots 0, 2, 4 or 6 of a cache line (to avoid | 
|  | the wrong prediction bits being used in some cases). | 
|  |  | 
|  | D-Cache timing constraints: | 
|  | -- Signed int loads of less than 64 bits have 3 cycle latency, not 2 | 
|  | -- All other loads that hit in D-Cache have 2 cycle latency | 
|  | -- All loads are returned IN ORDER, so a D-Cache miss will delay a later hit | 
|  | -- Mis-aligned loads or stores cause a trap.  In particular, replace | 
|  | mis-aligned FP double precision l/s with 2 single-precision l/s. | 
|  | -- Simulations of integer codes show increase in avg. group size of | 
|  | 33% when code (including esp. non-faulting loads) is moved across | 
|  | one branch, and 50% across 2 branches. | 
|  |  | 
|  | E-Cache timing constraints: | 
|  | -- Scheduling for E-cache (D-Cache misses) is effective (due to load buffering) | 
|  |  | 
|  | Store buffer timing constraints: | 
|  | -- Stores can be executed in same cycle as instruction producing the value | 
|  | -- Stores are buffered and have lower priority for E-cache until | 
|  | highwater mark is reached in the store buffer (5 stores) | 
|  |  | 
|  | Pipeline constraints: | 
|  | -- Shifts can only use IEU0. | 
|  | -- CC setting instructions can only use IEU1. | 
|  | -- Several other instructions must only use IEU1: | 
|  | EDGE(?), ARRAY(?), CALL, JMPL, BPr, PST, and FCMP. | 
|  | -- Two instructions cannot store to the same register file in a single cycle | 
|  | (single write port per file). | 
|  |  | 
|  | Issue and grouping constraints: | 
|  | -- FP and branch instructions must use slot 4. | 
|  | -- Shift instructions cannot be grouped with other IEU0-specific instructions. | 
|  | -- CC setting instructions cannot be grouped with other IEU1-specific instrs. | 
|  | -- Several instructions must be issued in a single-instruction group: | 
|  | MOVcc or MOVr, MULs/x and DIVs/x, SAVE/RESTORE, many others | 
|  | -- A CALL or JMPL breaks a group, ie, is not combined with subsequent instrs. | 
|  | -- | 
|  | -- | 
|  |  | 
|  | Branch delay slot scheduling rules: | 
|  | -- A CTI couple (two back-to-back CTI instructions in the dynamic stream) | 
|  | has a 9-instruction penalty: the entire pipeline is flushed when the | 
|  | second instruction reaches stage 9 (W-Writeback). | 
|  | -- Avoid putting multicycle instructions, and instructions that may cause | 
|  | load misses, in the delay slot of an annulling branch. | 
|  | -- Avoid putting WR, SAVE..., RESTORE and RETURN instructions in the | 
|  | delay slot of an annulling branch. | 
|  |  | 
|  | *--------------------------------------------------------------------------- */ | 
|  |  | 
|  | //--------------------------------------------------------------------------- | 
|  | // List of CPUResources for UltraSPARC IIi. | 
|  | //--------------------------------------------------------------------------- | 
|  |  | 
|  | static const CPUResource  AllIssueSlots(   "All Instr Slots", 4); | 
|  | static const CPUResource  IntIssueSlots(   "Int Instr Slots", 3); | 
|  | static const CPUResource  First3IssueSlots("Instr Slots 0-3", 3); | 
|  | static const CPUResource  LSIssueSlots(    "Load-Store Instr Slot", 1); | 
|  | static const CPUResource  CTIIssueSlots(   "Ctrl Transfer Instr Slot", 1); | 
|  | static const CPUResource  FPAIssueSlots(   "FP Instr Slot 1", 1); | 
|  | static const CPUResource  FPMIssueSlots(   "FP Instr Slot 2", 1); | 
|  |  | 
|  | // IEUN instructions can use either Alu and should use IAluN. | 
|  | // IEU0 instructions must use Alu 1 and should use both IAluN and IAlu0. | 
|  | // IEU1 instructions must use Alu 2 and should use both IAluN and IAlu1. | 
|  | static const CPUResource  IAluN("Int ALU 1or2", 2); | 
|  | static const CPUResource  IAlu0("Int ALU 1",    1); | 
|  | static const CPUResource  IAlu1("Int ALU 2",    1); | 
|  |  | 
|  | static const CPUResource  LSAluC1("Load/Store Unit Addr Cycle", 1); | 
|  | static const CPUResource  LSAluC2("Load/Store Unit Issue Cycle", 1); | 
|  | static const CPUResource  LdReturn("Load Return Unit", 1); | 
|  |  | 
|  | static const CPUResource  FPMAluC1("FP Mul/Div Alu Cycle 1", 1); | 
|  | static const CPUResource  FPMAluC2("FP Mul/Div Alu Cycle 2", 1); | 
|  | static const CPUResource  FPMAluC3("FP Mul/Div Alu Cycle 3", 1); | 
|  |  | 
|  | static const CPUResource  FPAAluC1("FP Other Alu Cycle 1", 1); | 
|  | static const CPUResource  FPAAluC2("FP Other Alu Cycle 2", 1); | 
|  | static const CPUResource  FPAAluC3("FP Other Alu Cycle 3", 1); | 
|  |  | 
|  | static const CPUResource  IRegReadPorts("Int Reg ReadPorts", INT_MAX); // CHECK | 
|  | static const CPUResource  IRegWritePorts("Int Reg WritePorts", 2);     // CHECK | 
|  | static const CPUResource  FPRegReadPorts("FP Reg Read Ports", INT_MAX);// CHECK | 
|  | static const CPUResource  FPRegWritePorts("FP Reg Write Ports", 1);    // CHECK | 
|  |  | 
|  | static const CPUResource  CTIDelayCycle( "CTI  delay cycle", 1); | 
|  | static const CPUResource  FCMPDelayCycle("FCMP delay cycle", 1); | 
|  |  | 
|  |  | 
|  |  | 
|  | //--------------------------------------------------------------------------- | 
|  | // const InstrClassRUsage SparcV9RUsageDesc[] | 
|  | // | 
|  | // Purpose: | 
|  | //   Resource usage information for instruction in each scheduling class. | 
|  | //   The InstrRUsage Objects for individual classes are specified first. | 
|  | //   Note that fetch and decode are decoupled from the execution pipelines | 
|  | //   via an instr buffer, so they are not included in the cycles below. | 
|  | //--------------------------------------------------------------------------- | 
|  |  | 
|  | static const InstrClassRUsage NoneClassRUsage = { | 
|  | SPARC_NONE, | 
|  | /*totCycles*/ 7, | 
|  |  | 
|  | /* maxIssueNum */ 4, | 
|  | /* isSingleIssue */ false, | 
|  | /* breaksGroup */ false, | 
|  | /* numBubbles */ 0, | 
|  |  | 
|  | /*numSlots*/ 4, | 
|  | /* feasibleSlots[] */ { 0, 1, 2, 3 }, | 
|  |  | 
|  | /*numEntries*/ 0, | 
|  | /* V[] */ { | 
|  | /*Cycle G */ | 
|  | /*Ccle E */ | 
|  | /*Cycle C */ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle W */ | 
|  | } | 
|  | }; | 
|  |  | 
|  | static const InstrClassRUsage IEUNClassRUsage = { | 
|  | SPARC_IEUN, | 
|  | /*totCycles*/ 7, | 
|  |  | 
|  | /* maxIssueNum */ 3, | 
|  | /* isSingleIssue */ false, | 
|  | /* breaksGroup */ false, | 
|  | /* numBubbles */ 0, | 
|  |  | 
|  | /*numSlots*/ 3, | 
|  | /* feasibleSlots[] */ { 0, 1, 2 }, | 
|  |  | 
|  | /*numEntries*/ 4, | 
|  | /* V[] */ { | 
|  | /*Cycle G */ { AllIssueSlots.rid, 0, 1 }, | 
|  | { IntIssueSlots.rid, 0, 1 }, | 
|  | /*Cycle E */ { IAluN.rid, 1, 1 }, | 
|  | /*Cycle C */ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle W */ { IRegWritePorts.rid, 6, 1  } | 
|  | } | 
|  | }; | 
|  |  | 
|  | static const InstrClassRUsage IEU0ClassRUsage = { | 
|  | SPARC_IEU0, | 
|  | /*totCycles*/ 7, | 
|  |  | 
|  | /* maxIssueNum */ 1, | 
|  | /* isSingleIssue */ false, | 
|  | /* breaksGroup */ false, | 
|  | /* numBubbles */ 0, | 
|  |  | 
|  | /*numSlots*/ 3, | 
|  | /* feasibleSlots[] */ { 0, 1, 2 }, | 
|  |  | 
|  | /*numEntries*/ 5, | 
|  | /* V[] */ { | 
|  | /*Cycle G */ { AllIssueSlots.rid, 0, 1 }, | 
|  | { IntIssueSlots.rid, 0, 1 }, | 
|  | /*Cycle E */ { IAluN.rid, 1, 1 }, | 
|  | { IAlu0.rid, 1, 1 }, | 
|  | /*Cycle C */ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle W */ { IRegWritePorts.rid, 6, 1 } | 
|  | } | 
|  | }; | 
|  |  | 
|  | static const InstrClassRUsage IEU1ClassRUsage = { | 
|  | SPARC_IEU1, | 
|  | /*totCycles*/ 7, | 
|  |  | 
|  | /* maxIssueNum */ 1, | 
|  | /* isSingleIssue */ false, | 
|  | /* breaksGroup */ false, | 
|  | /* numBubbles */ 0, | 
|  |  | 
|  | /*numSlots*/ 3, | 
|  | /* feasibleSlots[] */ { 0, 1, 2 }, | 
|  |  | 
|  | /*numEntries*/ 5, | 
|  | /* V[] */ { | 
|  | /*Cycle G */ { AllIssueSlots.rid, 0, 1 }, | 
|  | { IntIssueSlots.rid, 0, 1 }, | 
|  | /*Cycle E */ { IAluN.rid, 1, 1 }, | 
|  | { IAlu1.rid, 1, 1 }, | 
|  | /*Cycle C */ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle W */ { IRegWritePorts.rid, 6, 1 } | 
|  | } | 
|  | }; | 
|  |  | 
|  | static const InstrClassRUsage FPMClassRUsage = { | 
|  | SPARC_FPM, | 
|  | /*totCycles*/ 7, | 
|  |  | 
|  | /* maxIssueNum */ 1, | 
|  | /* isSingleIssue */ false, | 
|  | /* breaksGroup */ false, | 
|  | /* numBubbles */ 0, | 
|  |  | 
|  | /*numSlots*/ 4, | 
|  | /* feasibleSlots[] */ { 0, 1, 2, 3 }, | 
|  |  | 
|  | /*numEntries*/ 7, | 
|  | /* V[] */ { | 
|  | /*Cycle G */ { AllIssueSlots.rid,   0, 1 }, | 
|  | { FPMIssueSlots.rid,   0, 1 }, | 
|  | /*Cycle E */ { FPRegReadPorts.rid,  1, 1 }, | 
|  | /*Cycle C */ { FPMAluC1.rid,        2, 1 }, | 
|  | /*Cycle N1*/ { FPMAluC2.rid,        3, 1 }, | 
|  | /*Cycle N1*/ { FPMAluC3.rid,        4, 1 }, | 
|  | /*Cycle N1*/ | 
|  | /*Cycle W */ { FPRegWritePorts.rid, 6, 1 } | 
|  | } | 
|  | }; | 
|  |  | 
|  | static const InstrClassRUsage FPAClassRUsage = { | 
|  | SPARC_FPA, | 
|  | /*totCycles*/ 7, | 
|  |  | 
|  | /* maxIssueNum */ 1, | 
|  | /* isSingleIssue */ false, | 
|  | /* breaksGroup */ false, | 
|  | /* numBubbles */ 0, | 
|  |  | 
|  | /*numSlots*/ 4, | 
|  | /* feasibleSlots[] */ { 0, 1, 2, 3 }, | 
|  |  | 
|  | /*numEntries*/ 7, | 
|  | /* V[] */ { | 
|  | /*Cycle G */ { AllIssueSlots.rid,   0, 1 }, | 
|  | { FPAIssueSlots.rid,   0, 1 }, | 
|  | /*Cycle E */ { FPRegReadPorts.rid,  1, 1 }, | 
|  | /*Cycle C */ { FPAAluC1.rid,        2, 1 }, | 
|  | /*Cycle N1*/ { FPAAluC2.rid,        3, 1 }, | 
|  | /*Cycle N1*/ { FPAAluC3.rid,        4, 1 }, | 
|  | /*Cycle N1*/ | 
|  | /*Cycle W */ { FPRegWritePorts.rid, 6, 1 } | 
|  | } | 
|  | }; | 
|  |  | 
|  | static const InstrClassRUsage LDClassRUsage = { | 
|  | SPARC_LD, | 
|  | /*totCycles*/ 7, | 
|  |  | 
|  | /* maxIssueNum */ 1, | 
|  | /* isSingleIssue */ false, | 
|  | /* breaksGroup */ false, | 
|  | /* numBubbles */ 0, | 
|  |  | 
|  | /*numSlots*/ 3, | 
|  | /* feasibleSlots[] */ { 0, 1, 2, }, | 
|  |  | 
|  | /*numEntries*/ 6, | 
|  | /* V[] */ { | 
|  | /*Cycle G */ { AllIssueSlots.rid,    0, 1 }, | 
|  | { First3IssueSlots.rid, 0, 1 }, | 
|  | { LSIssueSlots.rid,     0, 1 }, | 
|  | /*Cycle E */ { LSAluC1.rid,          1, 1 }, | 
|  | /*Cycle C */ { LSAluC2.rid,          2, 1 }, | 
|  | { LdReturn.rid,         2, 1 }, | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle W */ { IRegWritePorts.rid,   6, 1 } | 
|  | } | 
|  | }; | 
|  |  | 
|  | static const InstrClassRUsage STClassRUsage = { | 
|  | SPARC_ST, | 
|  | /*totCycles*/ 7, | 
|  |  | 
|  | /* maxIssueNum */ 1, | 
|  | /* isSingleIssue */ false, | 
|  | /* breaksGroup */ false, | 
|  | /* numBubbles */ 0, | 
|  |  | 
|  | /*numSlots*/ 3, | 
|  | /* feasibleSlots[] */ { 0, 1, 2 }, | 
|  |  | 
|  | /*numEntries*/ 4, | 
|  | /* V[] */ { | 
|  | /*Cycle G */ { AllIssueSlots.rid,    0, 1 }, | 
|  | { First3IssueSlots.rid, 0, 1 }, | 
|  | { LSIssueSlots.rid,     0, 1 }, | 
|  | /*Cycle E */ { LSAluC1.rid,          1, 1 }, | 
|  | /*Cycle C */ { LSAluC2.rid,          2, 1 } | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle W */ | 
|  | } | 
|  | }; | 
|  |  | 
|  | static const InstrClassRUsage CTIClassRUsage = { | 
|  | SPARC_CTI, | 
|  | /*totCycles*/ 7, | 
|  |  | 
|  | /* maxIssueNum */ 1, | 
|  | /* isSingleIssue */ false, | 
|  | /* breaksGroup */ false, | 
|  | /* numBubbles */ 0, | 
|  |  | 
|  | /*numSlots*/ 4, | 
|  | /* feasibleSlots[] */ { 0, 1, 2, 3 }, | 
|  |  | 
|  | /*numEntries*/ 4, | 
|  | /* V[] */ { | 
|  | /*Cycle G */ { AllIssueSlots.rid,    0, 1 }, | 
|  | { CTIIssueSlots.rid,    0, 1 }, | 
|  | /*Cycle E */ { IAlu0.rid,            1, 1 }, | 
|  | /*Cycles E-C */ { CTIDelayCycle.rid, 1, 2 } | 
|  | /*Cycle C */ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle W */ | 
|  | } | 
|  | }; | 
|  |  | 
|  | static const InstrClassRUsage SingleClassRUsage = { | 
|  | SPARC_SINGLE, | 
|  | /*totCycles*/ 7, | 
|  |  | 
|  | /* maxIssueNum */ 1, | 
|  | /* isSingleIssue */ true, | 
|  | /* breaksGroup */ false, | 
|  | /* numBubbles */ 0, | 
|  |  | 
|  | /*numSlots*/ 1, | 
|  | /* feasibleSlots[] */ { 0 }, | 
|  |  | 
|  | /*numEntries*/ 5, | 
|  | /* V[] */ { | 
|  | /*Cycle G */ { AllIssueSlots.rid,    0, 1 }, | 
|  | { AllIssueSlots.rid,    0, 1 }, | 
|  | { AllIssueSlots.rid,    0, 1 }, | 
|  | { AllIssueSlots.rid,    0, 1 }, | 
|  | /*Cycle E */ { IAlu0.rid,            1, 1 } | 
|  | /*Cycle C */ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle N1*/ | 
|  | /*Cycle W */ | 
|  | } | 
|  | }; | 
|  |  | 
|  |  | 
|  | static const InstrClassRUsage SparcV9RUsageDesc[] = { | 
|  | NoneClassRUsage, | 
|  | IEUNClassRUsage, | 
|  | IEU0ClassRUsage, | 
|  | IEU1ClassRUsage, | 
|  | FPMClassRUsage, | 
|  | FPAClassRUsage, | 
|  | CTIClassRUsage, | 
|  | LDClassRUsage, | 
|  | STClassRUsage, | 
|  | SingleClassRUsage | 
|  | }; | 
|  |  | 
|  |  | 
|  |  | 
|  | //--------------------------------------------------------------------------- | 
|  | // const InstrIssueDelta  SparcV9InstrIssueDeltas[] | 
|  | // | 
|  | // Purpose: | 
|  | //   Changes to issue restrictions information in InstrClassRUsage for | 
|  | //   instructions that differ from other instructions in their class. | 
|  | //--------------------------------------------------------------------------- | 
|  |  | 
|  | static const InstrIssueDelta  SparcV9InstrIssueDeltas[] = { | 
|  |  | 
|  | // opCode,  isSingleIssue,  breaksGroup,  numBubbles | 
|  |  | 
|  | // Special cases for single-issue only | 
|  | // Other single issue cases are below. | 
|  | //{ V9::LDDA,		true,	true,	0 }, | 
|  | //{ V9::STDA,		true,	true,	0 }, | 
|  | //{ V9::LDDF,		true,	true,	0 }, | 
|  | //{ V9::LDDFA,		true,	true,	0 }, | 
|  | { V9::ADDCr,		true,	true,	0 }, | 
|  | { V9::ADDCi,		true,	true,	0 }, | 
|  | { V9::ADDCccr,	true,	true,	0 }, | 
|  | { V9::ADDCcci,	true,	true,	0 }, | 
|  | { V9::SUBCr,		true,	true,	0 }, | 
|  | { V9::SUBCi,		true,	true,	0 }, | 
|  | { V9::SUBCccr,	true,	true,	0 }, | 
|  | { V9::SUBCcci,	true,	true,	0 }, | 
|  | //{ V9::LDSTUB,		true,	true,	0 }, | 
|  | //{ V9::SWAP,		true,	true,	0 }, | 
|  | //{ V9::SWAPA,		true,	true,	0 }, | 
|  | //{ V9::CAS,		true,	true,	0 }, | 
|  | //{ V9::CASA,		true,	true,	0 }, | 
|  | //{ V9::CASX,		true,	true,	0 }, | 
|  | //{ V9::CASXA,		true,	true,	0 }, | 
|  | //{ V9::LDFSR,		true,	true,	0 }, | 
|  | //{ V9::LDFSRA,		true,	true,	0 }, | 
|  | //{ V9::LDXFSR,		true,	true,	0 }, | 
|  | //{ V9::LDXFSRA,	true,	true,	0 }, | 
|  | //{ V9::STFSR,		true,	true,	0 }, | 
|  | //{ V9::STFSRA,		true,	true,	0 }, | 
|  | //{ V9::STXFSR,		true,	true,	0 }, | 
|  | //{ V9::STXFSRA,	true,	true,	0 }, | 
|  | //{ V9::SAVED,		true,	true,	0 }, | 
|  | //{ V9::RESTORED,	true,	true,	0 }, | 
|  | //{ V9::FLUSH,		true,	true,	9 }, | 
|  | //{ V9::FLUSHW,		true,	true,	9 }, | 
|  | //{ V9::ALIGNADDR,	true,	true,	0 }, | 
|  | //{ V9::DONE,		true,	true,	0 }, | 
|  | //{ V9::RETRY,		true,	true,	0 }, | 
|  | //{ V9::TCC,		true,	true,	0 }, | 
|  | //{ V9::SHUTDOWN,	true,	true,	0 }, | 
|  |  | 
|  | // Special cases for breaking group *before* | 
|  | // CURRENTLY NOT SUPPORTED! | 
|  | { V9::CALL,		false,	false,	0 }, | 
|  | { V9::JMPLCALLr,	false,	false,	0 }, | 
|  | { V9::JMPLCALLi,	false,	false,	0 }, | 
|  | { V9::JMPLRETr,	false,	false,	0 }, | 
|  | { V9::JMPLRETi,	false,	false,	0 }, | 
|  |  | 
|  | // Special cases for breaking the group *after* | 
|  | { V9::MULXr,		true,	true,	(4+34)/2 }, | 
|  | { V9::MULXi,		true,	true,	(4+34)/2 }, | 
|  | { V9::FDIVS,		false,	true,	0 }, | 
|  | { V9::FDIVD,		false,	true,	0 }, | 
|  | { V9::FDIVQ,		false,	true,	0 }, | 
|  | { V9::FSQRTS,		false,	true,	0 }, | 
|  | { V9::FSQRTD,		false,	true,	0 }, | 
|  | { V9::FSQRTQ,		false,	true,	0 }, | 
|  | //{ V9::FCMP{LE,GT,NE,EQ}, false, true, 0 }, | 
|  |  | 
|  | // Instructions that introduce bubbles | 
|  | //{ V9::MULScc,		true,	true,	2 }, | 
|  | //{ V9::SMULcc,		true,	true,	(4+18)/2 }, | 
|  | //{ V9::UMULcc,		true,	true,	(4+19)/2 }, | 
|  | { V9::SDIVXr,		true,	true,	68 }, | 
|  | { V9::SDIVXi,		true,	true,	68 }, | 
|  | { V9::UDIVXr,		true,	true,	68 }, | 
|  | { V9::UDIVXi,		true,	true,	68 }, | 
|  | //{ V9::SDIVcc,		true,	true,	36 }, | 
|  | //{ V9::UDIVcc,		true,	true,	37 }, | 
|  | { V9::WRCCRr,		true,	true,	4 }, | 
|  | { V9::WRCCRi,		true,	true,	4 }, | 
|  | //{ V9::WRPR,		true,	true,	4 }, | 
|  | //{ V9::RDCCR,		true,	true,	0 }, // no bubbles after, but see below | 
|  | //{ V9::RDPR,		true,	true,	0 }, | 
|  | }; | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  | //--------------------------------------------------------------------------- | 
|  | // const InstrRUsageDelta SparcV9InstrUsageDeltas[] | 
|  | // | 
|  | // Purpose: | 
|  | //   Changes to resource usage information in InstrClassRUsage for | 
|  | //   instructions that differ from other instructions in their class. | 
|  | //--------------------------------------------------------------------------- | 
|  |  | 
|  | static const InstrRUsageDelta SparcV9InstrUsageDeltas[] = { | 
|  |  | 
|  | // MachineOpCode, Resource, Start cycle, Num cycles | 
|  |  | 
|  | // | 
|  | // JMPL counts as a load/store instruction for issue! | 
|  | // | 
|  | { V9::JMPLCALLr, LSIssueSlots.rid,  0,  1 }, | 
|  | { V9::JMPLCALLi, LSIssueSlots.rid,  0,  1 }, | 
|  | { V9::JMPLRETr,  LSIssueSlots.rid,  0,  1 }, | 
|  | { V9::JMPLRETi,  LSIssueSlots.rid,  0,  1 }, | 
|  |  | 
|  | // | 
|  | // Many instructions cannot issue for the next 2 cycles after an FCMP | 
|  | // We model that with a fake resource FCMPDelayCycle. | 
|  | // | 
|  | { V9::FCMPS,    FCMPDelayCycle.rid, 1, 3 }, | 
|  | { V9::FCMPD,    FCMPDelayCycle.rid, 1, 3 }, | 
|  | { V9::FCMPQ,    FCMPDelayCycle.rid, 1, 3 }, | 
|  |  | 
|  | { V9::MULXr,     FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::MULXi,     FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::SDIVXr,    FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::SDIVXi,    FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::UDIVXr,    FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::UDIVXi,    FCMPDelayCycle.rid, 1, 1 }, | 
|  | //{ V9::SMULcc,   FCMPDelayCycle.rid, 1, 1 }, | 
|  | //{ V9::UMULcc,   FCMPDelayCycle.rid, 1, 1 }, | 
|  | //{ V9::SDIVcc,   FCMPDelayCycle.rid, 1, 1 }, | 
|  | //{ V9::UDIVcc,   FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::STDFr,    FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::STDFi,    FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::FMOVRSZ,  FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::FMOVRSLEZ,FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::FMOVRSLZ, FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::FMOVRSNZ, FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::FMOVRSGZ, FCMPDelayCycle.rid, 1, 1 }, | 
|  | { V9::FMOVRSGEZ,FCMPDelayCycle.rid, 1, 1 }, | 
|  |  | 
|  | // | 
|  | // Some instructions are stalled in the GROUP stage if a CTI is in | 
|  | // the E or C stage.  We model that with a fake resource CTIDelayCycle. | 
|  | // | 
|  | { V9::LDDFr,    CTIDelayCycle.rid,  1, 1 }, | 
|  | { V9::LDDFi,    CTIDelayCycle.rid,  1, 1 }, | 
|  | //{ V9::LDDA,     CTIDelayCycle.rid,  1, 1 }, | 
|  | //{ V9::LDDSTUB,  CTIDelayCycle.rid,  1, 1 }, | 
|  | //{ V9::LDDSTUBA, CTIDelayCycle.rid,  1, 1 }, | 
|  | //{ V9::SWAP,     CTIDelayCycle.rid,  1, 1 }, | 
|  | //{ V9::SWAPA,    CTIDelayCycle.rid,  1, 1 }, | 
|  | //{ V9::CAS,      CTIDelayCycle.rid,  1, 1 }, | 
|  | //{ V9::CASA,     CTIDelayCycle.rid,  1, 1 }, | 
|  | //{ V9::CASX,     CTIDelayCycle.rid,  1, 1 }, | 
|  | //{ V9::CASXA,    CTIDelayCycle.rid,  1, 1 }, | 
|  |  | 
|  | // | 
|  | // Signed int loads of less than dword size return data in cycle N1 (not C) | 
|  | // and put all loads in consecutive cycles into delayed load return mode. | 
|  | // | 
|  | { V9::LDSBr,    LdReturn.rid,  2, -1 }, | 
|  | { V9::LDSBr,    LdReturn.rid,  3,  1 }, | 
|  | { V9::LDSBi,    LdReturn.rid,  2, -1 }, | 
|  | { V9::LDSBi,    LdReturn.rid,  3,  1 }, | 
|  |  | 
|  | { V9::LDSHr,    LdReturn.rid,  2, -1 }, | 
|  | { V9::LDSHr,    LdReturn.rid,  3,  1 }, | 
|  | { V9::LDSHi,    LdReturn.rid,  2, -1 }, | 
|  | { V9::LDSHi,    LdReturn.rid,  3,  1 }, | 
|  |  | 
|  | { V9::LDSWr,    LdReturn.rid,  2, -1 }, | 
|  | { V9::LDSWr,    LdReturn.rid,  3,  1 }, | 
|  | { V9::LDSWi,    LdReturn.rid,  2, -1 }, | 
|  | { V9::LDSWi,    LdReturn.rid,  3,  1 }, | 
|  |  | 
|  | // | 
|  | // RDPR from certain registers and RD from any register are not dispatchable | 
|  | // until four clocks after they reach the head of the instr. buffer. | 
|  | // Together with their single-issue requirement, this means all four issue | 
|  | // slots are effectively blocked for those cycles, plus the issue cycle. | 
|  | // This does not increase the latency of the instruction itself. | 
|  | // | 
|  | { V9::RDCCR,   AllIssueSlots.rid,     0,  5 }, | 
|  | { V9::RDCCR,   AllIssueSlots.rid,     0,  5 }, | 
|  | { V9::RDCCR,   AllIssueSlots.rid,     0,  5 }, | 
|  | { V9::RDCCR,   AllIssueSlots.rid,     0,  5 }, | 
|  |  | 
|  | #undef EXPLICIT_BUBBLES_NEEDED | 
|  | #ifdef EXPLICIT_BUBBLES_NEEDED | 
|  | // | 
|  | // MULScc inserts one bubble. | 
|  | // This means it breaks the current group (captured in UltraSparcV9SchedInfo) | 
|  | // *and occupies all issue slots for the next cycle | 
|  | // | 
|  | //{ V9::MULScc,  AllIssueSlots.rid, 2, 2-1 }, | 
|  | //{ V9::MULScc,  AllIssueSlots.rid, 2, 2-1 }, | 
|  | //{ V9::MULScc,  AllIssueSlots.rid, 2, 2-1 }, | 
|  | //{ V9::MULScc,  AllIssueSlots.rid, 2, 2-1 }, | 
|  |  | 
|  | // | 
|  | // SMULcc inserts between 4 and 18 bubbles, depending on #leading 0s in rs1. | 
|  | // We just model this with a simple average. | 
|  | // | 
|  | //{ V9::SMULcc,  AllIssueSlots.rid, 2, ((4+18)/2)-1 }, | 
|  | //{ V9::SMULcc,  AllIssueSlots.rid, 2, ((4+18)/2)-1 }, | 
|  | //{ V9::SMULcc,  AllIssueSlots.rid, 2, ((4+18)/2)-1 }, | 
|  | //{ V9::SMULcc,  AllIssueSlots.rid, 2, ((4+18)/2)-1 }, | 
|  |  | 
|  | // SMULcc inserts between 4 and 19 bubbles, depending on #leading 0s in rs1. | 
|  | //{ V9::UMULcc,  AllIssueSlots.rid, 2, ((4+19)/2)-1 }, | 
|  | //{ V9::UMULcc,  AllIssueSlots.rid, 2, ((4+19)/2)-1 }, | 
|  | //{ V9::UMULcc,  AllIssueSlots.rid, 2, ((4+19)/2)-1 }, | 
|  | //{ V9::UMULcc,  AllIssueSlots.rid, 2, ((4+19)/2)-1 }, | 
|  |  | 
|  | // | 
|  | // MULX inserts between 4 and 34 bubbles, depending on #leading 0s in rs1. | 
|  | // | 
|  | { V9::MULX,    AllIssueSlots.rid, 2, ((4+34)/2)-1 }, | 
|  | { V9::MULX,    AllIssueSlots.rid, 2, ((4+34)/2)-1 }, | 
|  | { V9::MULX,    AllIssueSlots.rid, 2, ((4+34)/2)-1 }, | 
|  | { V9::MULX,    AllIssueSlots.rid, 2, ((4+34)/2)-1 }, | 
|  |  | 
|  | // | 
|  | // SDIVcc inserts 36 bubbles. | 
|  | // | 
|  | //{ V9::SDIVcc,  AllIssueSlots.rid, 2, 36-1 }, | 
|  | //{ V9::SDIVcc,  AllIssueSlots.rid, 2, 36-1 }, | 
|  | //{ V9::SDIVcc,  AllIssueSlots.rid, 2, 36-1 }, | 
|  | //{ V9::SDIVcc,  AllIssueSlots.rid, 2, 36-1 }, | 
|  |  | 
|  | // UDIVcc inserts 37 bubbles. | 
|  | //{ V9::UDIVcc,  AllIssueSlots.rid, 2, 37-1 }, | 
|  | //{ V9::UDIVcc,  AllIssueSlots.rid, 2, 37-1 }, | 
|  | //{ V9::UDIVcc,  AllIssueSlots.rid, 2, 37-1 }, | 
|  | //{ V9::UDIVcc,  AllIssueSlots.rid, 2, 37-1 }, | 
|  |  | 
|  | // | 
|  | // SDIVX inserts 68 bubbles. | 
|  | // | 
|  | { V9::SDIVX,   AllIssueSlots.rid, 2, 68-1 }, | 
|  | { V9::SDIVX,   AllIssueSlots.rid, 2, 68-1 }, | 
|  | { V9::SDIVX,   AllIssueSlots.rid, 2, 68-1 }, | 
|  | { V9::SDIVX,   AllIssueSlots.rid, 2, 68-1 }, | 
|  |  | 
|  | // | 
|  | // UDIVX inserts 68 bubbles. | 
|  | // | 
|  | { V9::UDIVX,   AllIssueSlots.rid, 2, 68-1 }, | 
|  | { V9::UDIVX,   AllIssueSlots.rid, 2, 68-1 }, | 
|  | { V9::UDIVX,   AllIssueSlots.rid, 2, 68-1 }, | 
|  | { V9::UDIVX,   AllIssueSlots.rid, 2, 68-1 }, | 
|  |  | 
|  | // | 
|  | // WR inserts 4 bubbles. | 
|  | // | 
|  | //{ V9::WR,     AllIssueSlots.rid, 2, 68-1 }, | 
|  | //{ V9::WR,     AllIssueSlots.rid, 2, 68-1 }, | 
|  | //{ V9::WR,     AllIssueSlots.rid, 2, 68-1 }, | 
|  | //{ V9::WR,     AllIssueSlots.rid, 2, 68-1 }, | 
|  |  | 
|  | // | 
|  | // WRPR inserts 4 bubbles. | 
|  | // | 
|  | //{ V9::WRPR,   AllIssueSlots.rid, 2, 68-1 }, | 
|  | //{ V9::WRPR,   AllIssueSlots.rid, 2, 68-1 }, | 
|  | //{ V9::WRPR,   AllIssueSlots.rid, 2, 68-1 }, | 
|  | //{ V9::WRPR,   AllIssueSlots.rid, 2, 68-1 }, | 
|  |  | 
|  | // | 
|  | // DONE inserts 9 bubbles. | 
|  | // | 
|  | //{ V9::DONE,   AllIssueSlots.rid, 2, 9-1 }, | 
|  | //{ V9::DONE,   AllIssueSlots.rid, 2, 9-1 }, | 
|  | //{ V9::DONE,   AllIssueSlots.rid, 2, 9-1 }, | 
|  | //{ V9::DONE,   AllIssueSlots.rid, 2, 9-1 }, | 
|  |  | 
|  | // | 
|  | // RETRY inserts 9 bubbles. | 
|  | // | 
|  | //{ V9::RETRY,   AllIssueSlots.rid, 2, 9-1 }, | 
|  | //{ V9::RETRY,   AllIssueSlots.rid, 2, 9-1 }, | 
|  | //{ V9::RETRY,   AllIssueSlots.rid, 2, 9-1 }, | 
|  | //{ V9::RETRY,   AllIssueSlots.rid, 2, 9-1 }, | 
|  |  | 
|  | #endif  /*EXPLICIT_BUBBLES_NEEDED */ | 
|  | }; | 
|  |  | 
|  | // Additional delays to be captured in code: | 
|  | // 1. RDPR from several state registers (page 349) | 
|  | // 2. RD   from *any* register (page 349) | 
|  | // 3. Writes to TICK, PSTATE, TL registers and FLUSH{W} instr (page 349) | 
|  | // 4. Integer store can be in same group as instr producing value to store. | 
|  | // 5. BICC and BPICC can be in the same group as instr producing CC (pg 350) | 
|  | // 6. FMOVr cannot be in the same or next group as an IEU instr (pg 351). | 
|  | // 7. The second instr. of a CTI group inserts 9 bubbles (pg 351) | 
|  | // 8. WR{PR}, SVAE, SAVED, RESTORE, RESTORED, RETURN, RETRY, and DONE that | 
|  | //    follow an annulling branch cannot be issued in the same group or in | 
|  | //    the 3 groups following the branch. | 
|  | // 9. A predicted annulled load does not stall dependent instructions. | 
|  | //    Other annulled delay slot instructions *do* stall dependents, so | 
|  | //    nothing special needs to be done for them during scheduling. | 
|  | //10. Do not put a load use that may be annulled in the same group as the | 
|  | //    branch.  The group will stall until the load returns. | 
|  | //11. Single-prec. FP loads lock 2 registers, for dependency checking. | 
|  | // | 
|  | // | 
|  | // Additional delays we cannot or will not capture: | 
|  | // 1. If DCTI is last word of cache line, it is delayed until next line can be | 
|  | //    fetched.  Also, other DCTI alignment-related delays (pg 352) | 
|  | // 2. Load-after-store is delayed by 7 extra cycles if load hits in D-Cache. | 
|  | //    Also, several other store-load and load-store conflicts (pg 358) | 
|  | // 3. MEMBAR, LD{X}FSR, LDD{A} and a bunch of other load stalls (pg 358) | 
|  | // 4. There can be at most 8 outstanding buffered store instructions | 
|  | //     (including some others like MEMBAR, LDSTUB, CAS{AX}, and FLUSH) | 
|  |  | 
|  |  | 
|  |  | 
|  | //--------------------------------------------------------------------------- | 
|  | // class SparcV9SchedInfo | 
|  | // | 
|  | // Purpose: | 
|  | //   Scheduling information for the UltraSPARC. | 
|  | //   Primarily just initializes machine-dependent parameters in | 
|  | //   class TargetSchedInfo. | 
|  | //--------------------------------------------------------------------------- | 
|  |  | 
|  | /*ctor*/ | 
|  | SparcV9SchedInfo::SparcV9SchedInfo(const TargetMachine& tgt) | 
|  | : TargetSchedInfo(tgt, | 
|  | (unsigned int) SPARC_NUM_SCHED_CLASSES, | 
|  | SparcV9RUsageDesc, | 
|  | SparcV9InstrUsageDeltas, | 
|  | SparcV9InstrIssueDeltas, | 
|  | sizeof(SparcV9InstrUsageDeltas)/sizeof(InstrRUsageDelta), | 
|  | sizeof(SparcV9InstrIssueDeltas)/sizeof(InstrIssueDelta)) | 
|  | { | 
|  | maxNumIssueTotal = 4; | 
|  | longestIssueConflict = 0;		// computed from issuesGaps[] | 
|  |  | 
|  | // must be called after above parameters are initialized. | 
|  | initializeResources(); | 
|  | } | 
|  |  | 
|  | void | 
|  | SparcV9SchedInfo::initializeResources() | 
|  | { | 
|  | // Compute TargetSchedInfo::instrRUsages and TargetSchedInfo::issueGaps | 
|  | TargetSchedInfo::initializeResources(); | 
|  |  | 
|  | // Machine-dependent fixups go here.  None for now. | 
|  | } |