Index: lib/Target/Sparc/Disassembler/SparcDisassembler.cpp =================================================================== --- lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ lib/Target/Sparc/Disassembler/SparcDisassembler.cpp @@ -409,6 +409,57 @@ return MCDisassembler::Success; } +static unsigned DecodeRexF3(unsigned insn) { + + static const unsigned SparcRegsMapping[32] = { + 8, 9, 10, 11, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 16, 17, 18, 19, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7}; + + unsigned rop = (insn >> 30); + unsigned r4d = (insn >> 26) & 15; + unsigned rop3l = (insn >> 20) & 1; + unsigned r4s = (insn >> 16) & 0xF; + + int isfpop = rop3l; + int ximm = (insn >> 15) & 1; + int xop3 = (insn >> 9) & 0x3F; + int xfpop = (insn >> 9) & 0x7F; + int rdalt = (insn >> 8) & 1; + int rs1alt = (insn >> 7) & 1; + + unsigned op32 = 0; + + if (isfpop) { + unsigned opf = xfpop & 0x0f; + xop3 = 0x34; + if ((xfpop & 0x70) == 0x40) + xop3 |= 1; + if ((xfpop & 0x70) == 0x40) + opf |= 0x10; + if ((xfpop & 0x50) == 0x10) + opf |= 0x20; + if ((xfpop & 0x60) != 0) + opf |= 0x40; + if ((xfpop & 0x70) == 0x50 || (xfpop & 0x70) == 0x60) + opf |= 0x80; + op32 |= opf << 5; + op32 |= insn & 0x1f; + } + + op32 |= rop << 30; + op32 |= SparcRegsMapping[r4d + 16 * (rdalt ^ isfpop)] << 25; + op32 |= xop3 << 19; + op32 |= SparcRegsMapping[r4s + 16 * (rs1alt ^ isfpop)] << 14; + op32 |= ximm << 13; + if (!isfpop) + op32 |= insn & 0x7F; + + if (ximm != 0 && (insn & 0x40) != 0) + op32 |= 0x1F80; + + return op32; +} + DecodeStatus SparcDisassembler::getInstructionREX(MCInst &Instr, uint64_t &Size, ArrayRef Bytes, uint64_t Address, @@ -451,8 +502,12 @@ (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) | (Bytes[0] << 24); bool isCall = (Insn >> 30) == 1; + bool isRexEncoded = (Insn >> 31) && !(Insn & (1 << 25)); - if (isCall) { + if (isCall || isRexEncoded) { + if (isRexEncoded) { + Insn = DecodeRexF3(Insn); + } Result = decodeInstruction(DecoderTableSparc32, Instr, Insn, Address, this, STI); } else { Index: lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp =================================================================== --- lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +++ lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp @@ -99,6 +99,10 @@ unsigned getRexFPRegEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned RexF3_12PostEncoder(const MCInst &MI, unsigned EncodedValue, + const MCSubtargetInfo &STI) const; + unsigned RexF3_3PostEncoder(const MCInst &MI, unsigned EncodedValue, + const MCSubtargetInfo &STI) const; }; } // end anonymous namespace @@ -373,6 +377,102 @@ 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 4, 5, 6, 7, 0, 1, 2, 3, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; +static unsigned getField(unsigned insn, unsigned startBit, unsigned numBits) { + unsigned fieldMask = (((unsigned)1 << numBits) - 1) << startBit; + return (insn & fieldMask) >> startBit; +} + +unsigned +SparcMCCodeEmitter::RexF3_12PostEncoder(const MCInst &MI, unsigned EncodedValue, + const MCSubtargetInfo &STI) const { + if (!isREX(STI)) + return EncodedValue; + + if (MI.getOpcode() == SP::SAVEREX || MI.getOpcode() == SP::ADDREX) + return EncodedValue; + + unsigned Rd = RexIntRegsMapping[getField(EncodedValue, 25, 5)]; + unsigned Op3 = getField(EncodedValue, 19, 6); + unsigned Rs1 = RexIntRegsMapping[getField(EncodedValue, 14, 5)]; + unsigned Imm = getField(EncodedValue, 13, 1); + unsigned Rs2OrImm = + Imm ? getField(EncodedValue, 0, 7) : getField(EncodedValue, 0, 5); + + if (MI.getOpcode() == SP::CALLri || MI.getOpcode() == SP::CALLrr) + Rd = 23; + + if (MI.getOpcode() == SP::BINDri || MI.getOpcode() == SP::BINDrr) + Rd = 24; + + // {31-30} - + // {29-26} r4d + // {25} 0 + // {24-21} rop3 + // {20} 0 + // {19-16} r4s1 + // {15} ximm + // {14-9} xop3 + // {8} rdalt + // {7} rs1alt + // {6-0} rs2 / simm7 + EncodedValue &= 0xC0000000; + EncodedValue |= (Rd & 0xf) << 26; + EncodedValue |= 7 << 21; + EncodedValue |= (Rs1 & 0xf) << 16; + EncodedValue |= Imm << 15; + EncodedValue |= Op3 << 9; + EncodedValue |= (Rd & 0x10) << 4; + EncodedValue |= (Rs1 & 0x10) << 3; + EncodedValue |= Rs2OrImm; + + return EncodedValue; +} + +unsigned +SparcMCCodeEmitter::RexF3_3PostEncoder(const MCInst &MI, unsigned EncodedValue, + const MCSubtargetInfo &STI) const { + + if (!isREX(STI)) + return EncodedValue; + + unsigned Rd = RexFloatRegsMapping[getField(EncodedValue, 25, 5)]; + unsigned Op3 = getField(EncodedValue, 19, 6); + unsigned Rs1 = RexFloatRegsMapping[getField(EncodedValue, 14, 5)]; + unsigned Fpop = getField(EncodedValue, 5, 9); + unsigned Rs2 = getField(EncodedValue, 0, 5); + + unsigned Xfpop6 = getField(Op3, 0, 1) | getField(Fpop, 7, 1); + unsigned Xfpop5 = getField(Fpop, 6, 1) & ~getField(Fpop, 4, 1); + unsigned Xfpop4 = + ~getField(Op3, 0, 1) & (getField(Fpop, 5, 1) ^ getField(Fpop, 4, 1)); + + // {31-30} 10 + // {29-26} r4d + // {25} 0 + // {24-21} rop3 + // {20} 1 + // {19-16} r4s1 + // {15-9} xfpop + // {8} rdalt + // {7} rs1alt + // {6-5} 0 + // {4-0} rs2 + EncodedValue &= 0xC0000000; + EncodedValue |= (Rd & 0xf) << 26; + EncodedValue |= 7 << 21; + EncodedValue |= 1 << 20; + EncodedValue |= (Rs1 & 0xf) << 16; + EncodedValue |= Xfpop6 << 15; + EncodedValue |= Xfpop5 << 14; + EncodedValue |= Xfpop4 << 13; + EncodedValue |= (Fpop & 0xf) << 9; + EncodedValue |= (Rd & 0x10) << 4; + EncodedValue |= (Rs1 & 0x10) << 3; + EncodedValue |= Rs2; + + return EncodedValue; +} + unsigned SparcMCCodeEmitter::getRexIntRegEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, Index: lib/Target/Sparc/SparcInstrFormats.td =================================================================== --- lib/Target/Sparc/SparcInstrFormats.td +++ lib/Target/Sparc/SparcInstrFormats.td @@ -139,6 +139,7 @@ list pattern, InstrItinClass itin = IIC_iu_instr> : F3_1_asi { let asi = 0; + let PostEncoderMethod = "RexF3_12PostEncoder"; } class F3_2 opVal, bits<6> op3val, dag outs, dag ins, @@ -151,6 +152,7 @@ let Inst{13} = 1; // i field = 1 let Inst{12-0} = simm13; + let PostEncoderMethod = "RexF3_12PostEncoder"; } // floating-point @@ -164,6 +166,7 @@ let Inst{13-5} = opfval; // fp opcode let Inst{4-0} = rs2; + let PostEncoderMethod = "RexF3_3PostEncoder"; } // floating-point unary operations. @@ -178,6 +181,7 @@ let Inst{13-5} = opfval; // fp opcode let Inst{4-0} = rs2; + let PostEncoderMethod = "RexF3_3PostEncoder"; } // floating-point compares. @@ -191,6 +195,7 @@ let Inst{13-5} = opfval; // fp opcode let Inst{4-0} = rs2; + let PostEncoderMethod = "RexF3_3PostEncoder"; } // Shift by register rs2. Index: test/MC/Disassembler/Sparc/rex-instructions.txt =================================================================== --- test/MC/Disassembler/Sparc/rex-instructions.txt +++ test/MC/Disassembler/Sparc/rex-instructions.txt @@ -378,8 +378,16 @@ # Section 6.4.5 - Generic format 3 SPARC operation +# CHECK: add %sp, %i0, %o2 +0x88 0xe6 0x00 0x98 +# CHECK: add %sp, -54, %o2 +0x88 0xe6 0x80 0xca + # Section 6.4.6 - Floating-point operations +# CHECK: faddd %f0, %f2, %f4 +0xb0 0xf8 0x44 0x02 + # Section 6.5.1 - Set 32-bit constant # CHECK: rset32 50000, %l4 Index: test/MC/Sparc/rex-instructions.s =================================================================== --- test/MC/Sparc/rex-instructions.s +++ test/MC/Sparc/rex-instructions.s @@ -440,8 +440,17 @@ // Section 6.4.5 - Generic format 3 SPARC operation + !CHECK: add %sp, %i0, %o2 ! encoding: [0x88,0xe6,0x00,0x98] + add %sp, %i0, %o2 + + !CHECK: add %sp, -54, %o2 ! encoding: [0x88,0xe6,0x80,0xca] + add %sp, -54, %o2 + // Section 6.4.6 - Floating-point operations + !CHECK: faddd %f0, %f2, %f4 ! encoding: [0xb0,0xf8,0x44,0x02] + faddd %f0, %f2, %f4 + // Section 6.5.1 - Set 32-bit constant ! CHECK: rset32 50000, %l4 ! encoding: [0x93,0xe8,0x00,0x00,0xc3,0x50]