From 670d0abe49777cdd306c1e301ac906ecc39b4b09 Mon Sep 17 00:00:00 2001 From: "Vikram S. Adve" Date: Sat, 28 Jul 2001 04:26:42 +0000 Subject: [PATCH] Added several SPARC instructions including conditional move and SETHI. Added MachineInstrInfo class and subclass UltraSparcInstrInfo. Added several fields to MachineInstrDescriptor (and renamed it from MachineInstrInfo). Latency fields are to support scheduling. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/Sparc.h | 455 ++++++++++++++++++++++++----------- 1 file changed, 308 insertions(+), 147 deletions(-) diff --git a/include/llvm/CodeGen/Sparc.h b/include/llvm/CodeGen/Sparc.h index 3eab4048cfe..40f4551c8f3 100644 --- a/include/llvm/CodeGen/Sparc.h +++ b/include/llvm/CodeGen/Sparc.h @@ -21,24 +21,9 @@ const OpCodeMask Annul = 0x20000000; // annul delay instr? const OpCodeMask PredictTaken = 0x00080000; // predict branch taken? -//--------------------------------------------------------------------------- -// class UltraSparcMachine -// -// Purpose: -// Machine description. -// -//--------------------------------------------------------------------------- - -class UltraSparc: public TargetMachine { -public: - /*ctor*/ UltraSparc (); - /*dtor*/ virtual ~UltraSparc () {} -}; - - //--------------------------------------------------------------------------- // enum SparcMachineOpCode. -// const MachineInstrInfo SparcMachineInstrInfo[]. +// const MachineInstrDescriptor SparcMachineInstrDesc[] // // Purpose: // Description of UltraSparc machine instructions. @@ -54,6 +39,9 @@ enum SparcMachineOpCode { SETSW, SETUW, + // Set high-order bits of register and clear low-order bits + SETHI, + // Add or add with carry. // Immed bit specifies if second operand is immediate(1) or register(0) ADD, @@ -192,6 +180,53 @@ enum SparcMachineOpCode { FBULE, FBO, + // Conditional move on integer comparison with zero. + MOVRZ, + MOVRLEZ, + MOVRLZ, + MOVRNZ, + MOVRGZ, + MOVRGEZ, + + // Conditional move on integer condition code. + MOVA, + MOVN, + MOVNE, + MOVE, + MOVG, + MOVLE, + MOVGE, + MOVL, + MOVGU, + MOVLEU, + MOVCC, + MOVCS, + MOVPOS, + MOVNEG, + MOVVC, + MOVVS, + + // Conditional move on floating point condition code. + // Note that the enum name is not the same as the assembly mnemonic below + // because that would duplicate some entries with those above. + // Therefore, we use MOVF here instead of MOV. + MOVFA, + MOVFN, + MOVFU, + MOVFG, + MOVFUG, + MOVFL, + MOVFUL, + MOVFLG, + MOVFNE, + MOVFE, + MOVFUE, + MOVFGE, + MOVFUGE, + MOVFLE, + MOVFULE, + MOVFO, + // Load integer instructions LDSB, LDSH, @@ -226,178 +261,304 @@ enum SparcMachineOpCode { INVALID_OPCODE }; -const MachineInstrInfo SparcMachineInstrInfo[] = { +const MachineInstrDescriptor SparcMachineInstrDesc[] = { - { "NOP", 0, -1, 0, false }, + // Fields of each structure: + // opCodeString, + // numOperands, + // resultPosition (0-based; -1 if no result), + // maxImmedConst, + // immedIsSignExtended, + // numDelaySlots (in cycles) + // latency (in cycles) + // class flags - // Synthetic SPARC assembly opcodes for setting a register to a constant - { "SETSW", 2, 1, 0, true }, // max immediate constant is ignored - { "SETUW", 2, 1, 0, false }, // max immediate constant is ignored + { "NOP", 0, -1, 0, false, 0, 1, M_NOP_FLAG }, + + // Synthetic SPARC assembly opcodes for setting a register to a constant. + // Max immediate constant should be ignored for both these instructions. + { "SETSW", 2, 1, 0, true, 0, 1, M_INT_FLAG | M_ARITH_FLAG }, + { "SETUW", 2, 1, 0, false, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG | M_ARITH_FLAG }, + + // Set high-order bits of register and clear low-order bits + { "SETHI", 2, 1, (1 << 22) - 1, false, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG | M_ARITH_FLAG }, // Add or add with carry. - { "ADD", 3, 2, (1 << 12) - 1, true }, - { "ADDcc", 3, 2, (1 << 12) - 1, true }, - { "ADDC", 3, 2, (1 << 12) - 1, true }, - { "ADDCcc", 3, 2, (1 << 12) - 1, true }, + { "ADD", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_ARITH_FLAG }, + { "ADDcc", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_ARITH_FLAG }, + { "ADDC", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_ARITH_FLAG }, + { "ADDCcc", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_ARITH_FLAG }, // Sub tract or subtract with carry. - { "SUB", 3, 2, (1 << 12) - 1, true }, - { "SUBcc", 3, 2, (1 << 12) - 1, true }, - { "SUBC", 3, 2, (1 << 12) - 1, true }, - { "SUBCcc", 3, 2, (1 << 12) - 1, true }, + { "SUB", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_ARITH_FLAG }, + { "SUBcc", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_ARITH_FLAG }, + { "SUBC", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_ARITH_FLAG }, + { "SUBCcc", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_ARITH_FLAG }, // Integer multiply, signed divide, unsigned divide. // Note that the deprecated 32-bit multiply and multiply-step are not used. - { "MULX", 3, 2, (1 << 12) - 1, true }, - { "SDIVX", 3, 2, (1 << 12) - 1, true }, - { "UDIVX", 3, 2, (1 << 12) - 1, true }, + { "MULX", 3, 2, (1 << 12) - 1, true, 0, 3, M_INT_FLAG | M_ARITH_FLAG }, + { "SDIVX", 3, 2, (1 << 12) - 1, true, 0, 6, M_INT_FLAG | M_ARITH_FLAG }, + { "UDIVX", 3, 2, (1 << 12) - 1, true, 0, 6, M_INT_FLAG | M_ARITH_FLAG }, - // Floating point add, subtract, compare - { "FADDS", 3, 2, 0, false }, - { "FADDD", 3, 2, 0, false }, - { "FADDQ", 3, 2, 0, false }, - { "FSUBS", 3, 2, 0, false }, - { "FSUBD", 3, 2, 0, false }, - { "FSUBQ", 3, 2, 0, false }, - { "FCMPS", 3, 2, 0, false }, - { "FCMPD", 3, 2, 0, false }, - { "FCMPQ", 3, 2, 0, false }, + // Floating point add, subtract, compare. + // Note that destination of FCMP* instructions is operand 0, not operand 2. + { "FADDS", 3, 2, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FADDD", 3, 2, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FADDQ", 3, 2, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FSUBS", 3, 2, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FSUBD", 3, 2, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FSUBQ", 3, 2, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FCMPS", 3, 0, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FCMPD", 3, 0, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FCMPQ", 3, 0, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, // NOTE: FCMPE{S,D,Q}: FP Compare With Exception are currently unused! // Floating point multiply or divide. - { "FMULS", 3, 2, 0, false }, - { "FMULD", 3, 2, 0, false }, - { "FMULQ", 3, 2, 0, false }, - { "FSMULD", 3, 2, 0, false }, - { "FDMULQ", 3, 2, 0, false }, - { "FDIVS", 3, 2, 0, false }, - { "FDIVD", 3, 2, 0, false }, - { "FDIVQ", 3, 2, 0, false }, + { "FMULS", 3, 2, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FMULD", 3, 2, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FMULQ", 3, 2, 0, false, 0, 0, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FSMULD", 3, 2, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FDMULQ", 3, 2, 0, false, 0, 0, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FDIVS", 3, 2, 0, false, 0, 22, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FDIVD", 3, 2, 0, false, 0, 22, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FDIVQ", 3, 2, 0, false, 0, 0, M_FLOAT_FLAG | M_ARITH_FLAG }, // Logical operations - { "AND", 3, 2, (1 << 12) - 1, true }, - { "ANDcc", 3, 2, (1 << 12) - 1, true }, - { "ANDN", 3, 2, (1 << 12) - 1, true }, - { "ANDNcc", 3, 2, (1 << 12) - 1, true }, - { "OR", 3, 2, (1 << 12) - 1, true }, - { "ORcc", 3, 2, (1 << 12) - 1, true }, - { "ORN", 3, 2, (1 << 12) - 1, true }, - { "ORNcc", 3, 2, (1 << 12) - 1, true }, - { "XOR", 3, 2, (1 << 12) - 1, true }, - { "XORcc", 3, 2, (1 << 12) - 1, true }, - { "XNOR", 3, 2, (1 << 12) - 1, true }, - { "XNORcc", 3, 2, (1 << 12) - 1, true }, + { "AND", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "ANDcc", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "ANDN", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "ANDNcc", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "OR", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "ORcc", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "ORN", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "ORNcc", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "XOR", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "XORcc", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "XNOR", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "XNORcc", 3, 2, (1 << 12) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, // Shift operations - { "SLL", 3, 2, (1 << 5) - 1, true }, - { "SRL", 3, 2, (1 << 5) - 1, true }, - { "SRA", 3, 2, (1 << 5) - 1, true }, - { "SLLX", 3, 2, (1 << 6) - 1, true }, - { "SRLX", 3, 2, (1 << 6) - 1, true }, - { "SRAX", 3, 2, (1 << 6) - 1, true }, + { "SLL", 3, 2, (1 << 5) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "SRL", 3, 2, (1 << 5) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "SRA", 3, 2, (1 << 5) - 1, true, 0, 1, M_INT_FLAG | M_ARITH_FLAG }, + { "SLLX", 3, 2, (1 << 6) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "SRLX", 3, 2, (1 << 6) - 1, true, 0, 1, M_INT_FLAG | M_LOGICAL_FLAG}, + { "SRAX", 3, 2, (1 << 6) - 1, true, 0, 1, M_INT_FLAG | M_ARITH_FLAG }, // Convert from floating point to floating point formats - { "FSTOD", 2, 1, 0, false }, - { "FSTOQ", 2, 1, 0, false }, - { "FDTOS", 2, 1, 0, false }, - { "FDTOQ", 2, 1, 0, false }, - { "FQTOS", 2, 1, 0, false }, - { "FQTOD", 2, 1, 0, false }, + { "FSTOD", 2, 1, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FSTOQ", 2, 1, 0, false, 0, 0, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FDTOS", 2, 1, 0, false, 0, 3, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FDTOQ", 2, 1, 0, false, 0, 0, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FQTOS", 2, 1, 0, false, 0, 0, M_FLOAT_FLAG | M_ARITH_FLAG }, + { "FQTOD", 2, 1, 0, false, 0, 0, M_FLOAT_FLAG | M_ARITH_FLAG }, - // Convert from floating point to integer formats - { "FSTOX", 2, 1, 0, false }, - { "FDTOX", 2, 1, 0, false }, - { "FQTOX", 2, 1, 0, false }, - { "FSTOI", 2, 1, 0, false }, - { "FDTOI", 2, 1, 0, false }, - { "FQTOI", 2, 1, 0, false }, + // Convert from floating point to integer formats. + // Note that this accesses both integer and floating point registers. + { "FSTOX", 2, 1, 0, false, 0, 3, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG }, + { "FDTOX", 2, 1, 0, false, 0, 0, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG }, + { "FQTOX", 2, 1, 0, false, 0, 2, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG }, + { "FSTOI", 2, 1, 0, false, 0, 3, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG }, + { "FDTOI", 2, 1, 0, false, 0, 3, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG }, + { "FQTOI", 2, 1, 0, false, 0, 0, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG }, // Convert from integer to floating point formats - { "FXTOS", 2, 1, 0, false }, - { "FXTOD", 2, 1, 0, false }, - { "FXTOQ", 2, 1, 0, false }, - { "FITOS", 2, 1, 0, false }, - { "FITOD", 2, 1, 0, false }, - { "FITOQ", 2, 1, 0, false }, + // Note that this accesses both integer and floating point registers. + { "FXTOS", 2, 1, 0, false, 0, 3, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG }, + { "FXTOD", 2, 1, 0, false, 0, 3, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG }, + { "FXTOQ", 2, 1, 0, false, 0, 0, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG }, + { "FITOS", 2, 1, 0, false, 0, 3, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG }, + { "FITOD", 2, 1, 0, false, 0, 3, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG }, + { "FITOQ", 2, 1, 0, false, 0, 0, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG }, // Branch on integer comparison with zero. - { "BRZ", 2, -1, (1 << 15) - 1, true }, - { "BRLEZ", 2, -1, (1 << 15) - 1, true }, - { "BRLZ", 2, -1, (1 << 15) - 1, true }, - { "BRNZ", 2, -1, (1 << 15) - 1, true }, - { "BRGZ", 2, -1, (1 << 15) - 1, true }, - { "BRGEZ", 2, -1, (1 << 15) - 1, true }, + // Latency includes the delay slot. + { "BRZ", 2, -1, (1 << 15) - 1, true, 1, 2, M_INT_FLAG | M_BRANCH_FLAG }, + { "BRLEZ", 2, -1, (1 << 15) - 1, true, 1, 2, M_INT_FLAG | M_BRANCH_FLAG }, + { "BRLZ", 2, -1, (1 << 15) - 1, true, 1, 2, M_INT_FLAG | M_BRANCH_FLAG }, + { "BRNZ", 2, -1, (1 << 15) - 1, true, 1, 2, M_INT_FLAG | M_BRANCH_FLAG }, + { "BRGZ", 2, -1, (1 << 15) - 1, true, 1, 2, M_INT_FLAG | M_BRANCH_FLAG }, + { "BRGEZ", 2, -1, (1 << 15) - 1, true, 1, 2, M_INT_FLAG | M_BRANCH_FLAG }, // Branch on condition code. - { "BA", 1, -1, (1 << 21) - 1, true }, - { "BN", 1, -1, (1 << 21) - 1, true }, - { "BNE", 1, -1, (1 << 21) - 1, true }, - { "BE", 1, -1, (1 << 21) - 1, true }, - { "BG", 1, -1, (1 << 21) - 1, true }, - { "BLE", 1, -1, (1 << 21) - 1, true }, - { "BGE", 1, -1, (1 << 21) - 1, true }, - { "BL", 1, -1, (1 << 21) - 1, true }, - { "BGU", 1, -1, (1 << 21) - 1, true }, - { "BLEU", 1, -1, (1 << 21) - 1, true }, - { "BCC", 1, -1, (1 << 21) - 1, true }, - { "BCS", 1, -1, (1 << 21) - 1, true }, - { "BPOS", 1, -1, (1 << 21) - 1, true }, - { "BNEG", 1, -1, (1 << 21) - 1, true }, - { "BVC", 1, -1, (1 << 21) - 1, true }, - { "BVS", 1, -1, (1 << 21) - 1, true }, + // The first argument specifies the ICC register: %icc or %xcc + // Latency includes the delay slot. + { "BA", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BN", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BNE", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BE", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BG", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BLE", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BGE", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BL", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BGU", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BLEU", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BCC", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BCS", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BPOS", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BNEG", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BVC", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "BVS", 2, -1, (1 << 21) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, // Branch on floating point condition code. // Annul bit specifies if intruction in delay slot is annulled(1) or not(0). // PredictTaken bit hints if branch should be predicted taken(1) or not(0). // The first argument is the FCCn register (0 <= n <= 3). - { "FBA", 2, -1, (1 << 18) - 1, true }, - { "FBN", 2, -1, (1 << 18) - 1, true }, - { "FBU", 2, -1, (1 << 18) - 1, true }, - { "FBG", 2, -1, (1 << 18) - 1, true }, - { "FBUG", 2, -1, (1 << 18) - 1, true }, - { "FBL", 2, -1, (1 << 18) - 1, true }, - { "FBUL", 2, -1, (1 << 18) - 1, true }, - { "FBLG", 2, -1, (1 << 18) - 1, true }, - { "FBNE", 2, -1, (1 << 18) - 1, true }, - { "FBE", 2, -1, (1 << 18) - 1, true }, - { "FBUE", 2, -1, (1 << 18) - 1, true }, - { "FBGE", 2, -1, (1 << 18) - 1, true }, - { "FBUGE", 2, -1, (1 << 18) - 1, true }, - { "FBLE", 2, -1, (1 << 18) - 1, true }, - { "FBULE", 2, -1, (1 << 18) - 1, true }, - { "FBO", 2, -1, (1 << 18) - 1, true }, + // Latency includes the delay slot. + { "FBA", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBN", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBU", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBG", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBUG", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBL", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBUL", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBLG", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBNE", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBE", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBUE", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBGE", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBUGE", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBLE", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBULE", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + { "FBO", 2, -1, (1 << 18) - 1, true, 1, 2, M_CC_FLAG | M_BRANCH_FLAG }, + + // Conditional move on integer comparison with zero. + { "MOVRZ", 3, 2, (1 << 12) - 1, true, 0, 1, M_CONDL_FLAG | M_INT_FLAG }, + { "MOVRLEZ", 3, 2, (1 << 12) - 1, true, 0, 1, M_CONDL_FLAG | M_INT_FLAG }, + { "MOVRLZ", 3, 2, (1 << 12) - 1, true, 0, 1, M_CONDL_FLAG | M_INT_FLAG }, + { "MOVRNZ", 3, 2, (1 << 12) - 1, true, 0, 1, M_CONDL_FLAG | M_INT_FLAG }, + { "MOVRGZ", 3, 2, (1 << 12) - 1, true, 0, 1, M_CONDL_FLAG | M_INT_FLAG }, + { "MOVRGEZ", 3, 2, (1 << 12) - 1, true, 0, 1, M_CONDL_FLAG | M_INT_FLAG }, + + // Conditional move on integer condition code. + // The first argument specifies the ICC register: %icc or %xcc + { "MOVA", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVN", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVNE", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVE", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVG", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVLE", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVGE", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVL", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVGU", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVLEU", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVCC", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVCS", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVPOS", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVNEG", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVVC", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVVS", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + + // Conditional move (of integer register) on floating point condition code. + // The first argument is the FCCn register (0 <= n <= 3). + // Note that the enum name above is not the same as the assembly mnemonic + // because some of the assembly mnemonics are the same as the move on + // integer CC (e.g., MOVG), and we cannot have the same enum entry twice. + { "MOVA", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVN", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVU", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVG", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVUG", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVL", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVUL", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVLG", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVNE", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVE", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVUE", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVGE", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVUGE", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVLE", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVULE", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, + { "MOVO", 3, 2, (1 << 12) - 1, true, 0, 1, M_CC_FLAG | M_INT_FLAG }, // Load integer instructions - { "LDSB", 3, 2, (1 << 12) - 1, true }, - { "LDSH", 3, 2, (1 << 12) - 1, true }, - { "LDSW", 3, 2, (1 << 12) - 1, true }, - { "LDUB", 3, 2, (1 << 12) - 1, true }, - { "LDUH", 3, 2, (1 << 12) - 1, true }, - { "LDUW", 3, 2, (1 << 12) - 1, true }, - { "LDX", 3, 2, (1 << 12) - 1, true }, + // Latency includes 1 cycle for address generation (Sparc IIi) + // Signed loads of less than 64 bits need an extra cycle for sign-extension. + // + // Not reflected here: After a 3-cycle loads, all subsequent consecutive + // loads also require 3 cycles to avoid contention for the load return + // stage. Latency returns to 2 cycles after the first cycle with no load. + { "LDSB", 3, 2, (1 << 12) - 1, true, 0, 3, M_INT_FLAG | M_LOAD_FLAG }, + { "LDSH", 3, 2, (1 << 12) - 1, true, 0, 3, M_INT_FLAG | M_LOAD_FLAG }, + { "LDSW", 3, 2, (1 << 12) - 1, true, 0, 3, M_INT_FLAG | M_LOAD_FLAG }, + { "LDUB", 3, 2, (1 << 12) - 1, true, 0, 2, M_INT_FLAG | M_LOAD_FLAG }, + { "LDUH", 3, 2, (1 << 12) - 1, true, 0, 2, M_INT_FLAG | M_LOAD_FLAG }, + { "LDUW", 3, 2, (1 << 12) - 1, true, 0, 2, M_INT_FLAG | M_LOAD_FLAG }, + { "LDX", 3, 2, (1 << 12) - 1, true, 0, 2, M_INT_FLAG | M_LOAD_FLAG }, // Load floating-point instructions - { "LD", 3, 2, (1 << 12) - 1, true }, - { "LDD", 3, 2, (1 << 12) - 1, true }, - { "LDQ", 3, 2, (1 << 12) - 1, true }, + // Latency includes 1 cycle for address generation (Sparc IIi) + { "LD", 3, 2, (1 << 12) - 1, true, 0, 2, M_FLOAT_FLAG | M_LOAD_FLAG }, + { "LDD", 3, 2, (1 << 12) - 1, true, 0, 2, M_FLOAT_FLAG | M_LOAD_FLAG }, + { "LDQ", 3, 2, (1 << 12) - 1, true, 0, 2, M_FLOAT_FLAG | M_LOAD_FLAG }, // Store integer instructions - { "STB", 3, -1, (1 << 12) - 1, true }, - { "STH", 3, -1, (1 << 12) - 1, true }, - { "STW", 3, -1, (1 << 12) - 1, true }, - { "STX", 3, -1, (1 << 12) - 1, true }, + // Latency includes 1 cycle for address generation (Sparc IIi) + { "STB", 3, -1, (1 << 12) - 1, true, 0, 2, M_INT_FLAG | M_STORE_FLAG }, + { "STH", 3, -1, (1 << 12) - 1, true, 0, 2, M_INT_FLAG | M_STORE_FLAG }, + { "STW", 3, -1, (1 << 12) - 1, true, 0, 2, M_INT_FLAG | M_STORE_FLAG }, + { "STX", 3, -1, (1 << 12) - 1, true, 0, 3, M_INT_FLAG | M_STORE_FLAG }, - // Store floating-point instructions - { "ST", 3, -1, (1 << 12) - 1, true }, - { "STD", 3, -1, (1 << 12) - 1, true }, + // Store floating-point instructions (Sparc IIi) + { "ST", 3, -1, (1 << 12) - 1, true, 0, 2, M_FLOAT_FLAG | M_STORE_FLAG}, + { "STD", 3, -1, (1 << 12) - 1, true, 0, 2, M_FLOAT_FLAG | M_STORE_FLAG}, - // Call, Return and "Jump and link" - { "CALL", 1, -1, (1 << 29) - 1, true }, - { "JMPL", 3, -1, (1 << 12) - 1, true }, - { "RETURN", 2, -1, 0, false }, + // Call, Return and "Jump and link". + // Latency includes the delay slot. + { "CALL", 1, -1, (1 << 29) - 1, true, 1, 2, M_BRANCH_FLAG | M_CALL_FLAG}, + { "JMPL", 3, -1, (1 << 12) - 1, true, 1, 2, M_BRANCH_FLAG | M_CALL_FLAG}, + { "RETURN", 2, -1, 0, false, 1, 2, M_BRANCH_FLAG | M_RET_FLAG }, // End-of-array marker - { "INVALID_SPARC_OPCODE", 0, -1, 0, false } + { "INVALID_SPARC_OPCODE", 0, -1, 0, false, 0, 0, 0x0 } +}; + + + +//--------------------------------------------------------------------------- +// class UltraSparcInstrInfo +// +// Purpose: +// Information about individual instructions. +// Most information is stored in the SparcMachineInstrDesc array above. +// Other information is computed on demand, and most such functions +// default to member functions in base class MachineInstrInfo. +//--------------------------------------------------------------------------- + +class UltraSparcInstrInfo : public MachineInstrInfo { +public: + /*ctor*/ UltraSparcInstrInfo() + : MachineInstrInfo(SparcMachineInstrDesc, INVALID_OPCODE) + {} + + virtual bool hasResultInterlock (MachineOpCode opCode) + { + // All UltraSPARC instructions have interlocks (note that delay slots + // are not considered here). + // However, instructions that use the result of an FCMP produce a + // 9-cycle stall if they are issued less than 3 cycles after the FCMP. + // Force the compiler to insert a software interlock (i.e., gap of + // 2 other groups, including NOPs if necessary). + return (opCode == FCMPS || opCode == FCMPD || opCode == FCMPQ); + } +}; + + +//--------------------------------------------------------------------------- +// class UltraSparcMachine +// +// Purpose: +// Primary interface to machine description for the UltraSPARC. +// Primarily just initializes machine-dependent parameters in +// class TargetMachine, and creates machine-dependent subclasses +// for classes such as MachineInstrInfo. +//--------------------------------------------------------------------------- + +class UltraSparc: public TargetMachine { +public: + /*ctor*/ UltraSparc (); + /*dtor*/ virtual ~UltraSparc (); }; -- 2.34.1