Index: llvm/trunk/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ llvm/trunk/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -124,6 +124,15 @@ Sparc::Q8, Sparc::Q9, Sparc::Q10, Sparc::Q11, Sparc::Q12, Sparc::Q13, Sparc::Q14, Sparc::Q15 }; + static unsigned ASRRegs[32] = { + SP::Y, SP::ASR1, SP::ASR2, SP::ASR3, + SP::ASR4, SP::ASR5, SP::ASR6, SP::ASR7, + SP::ASR8, SP::ASR9, SP::ASR10, SP::ASR11, + SP::ASR12, SP::ASR13, SP::ASR14, SP::ASR15, + SP::ASR16, SP::ASR17, SP::ASR18, SP::ASR19, + SP::ASR20, SP::ASR21, SP::ASR22, SP::ASR23, + SP::ASR24, SP::ASR25, SP::ASR26, SP::ASR27, + SP::ASR28, SP::ASR29, SP::ASR30, SP::ASR31}; /// SparcOperand - Instances of this class represent a parsed Sparc machine /// instruction. @@ -136,7 +145,7 @@ rk_DoubleReg, rk_QuadReg, rk_CCReg, - rk_Y + rk_ASRReg }; private: enum KindTy { @@ -661,9 +670,6 @@ default: Op = SparcOperand::CreateReg(RegNo, RegKind, S, E); break; - case Sparc::Y: - Op = SparcOperand::CreateToken("%y", S); - break; case Sparc::ICC: if (name == "xcc") @@ -753,7 +759,15 @@ if (name.equals("y")) { RegNo = Sparc::Y; - RegKind = SparcOperand::rk_Y; + RegKind = SparcOperand::rk_ASRReg; + return true; + } + + if (name.substr(0, 3).equals_lower("asr") + && !name.substr(3).getAsInteger(10, intVal) + && intVal > 0 && intVal < 32) { + RegNo = ASRRegs[intVal]; + RegKind = SparcOperand::rk_ASRReg; return true; } Index: llvm/trunk/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp =================================================================== --- llvm/trunk/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp +++ llvm/trunk/lib/Target/Sparc/Disassembler/SparcDisassembler.cpp @@ -107,6 +107,16 @@ static const unsigned FCCRegDecoderTable[] = { SP::FCC0, SP::FCC1, SP::FCC2, SP::FCC3 }; +static const unsigned ASRRegDecoderTable[] = { + SP::Y, SP::ASR1, SP::ASR2, SP::ASR3, + SP::ASR4, SP::ASR5, SP::ASR6, SP::ASR7, + SP::ASR8, SP::ASR9, SP::ASR10, SP::ASR11, + SP::ASR12, SP::ASR13, SP::ASR14, SP::ASR15, + SP::ASR16, SP::ASR17, SP::ASR18, SP::ASR19, + SP::ASR20, SP::ASR21, SP::ASR22, SP::ASR23, + SP::ASR24, SP::ASR25, SP::ASR26, SP::ASR27, + SP::ASR28, SP::ASR29, SP::ASR30, SP::ASR31}; + static DecodeStatus DecodeIntRegsRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, @@ -177,6 +187,15 @@ return MCDisassembler::Success; } +static DecodeStatus DecodeASRRegsRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 31) + return MCDisassembler::Fail; + Inst.addOperand(MCOperand::createReg(ASRRegDecoderTable[RegNo])); + return MCDisassembler::Success; +} + static DecodeStatus DecodeLoadInt(MCInst &Inst, unsigned insn, uint64_t Address, const void *Decoder); Index: llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp @@ -168,8 +168,10 @@ } else { TopPart = CurDAG->getRegister(SP::G0, MVT::i32); } - TopPart = SDValue(CurDAG->getMachineNode(SP::WRYrr, dl, MVT::Glue, TopPart, - CurDAG->getRegister(SP::G0, MVT::i32)), 0); + TopPart = SDValue(CurDAG->getMachineNode(SP::WRASRrr, dl, MVT::i32, + TopPart, + CurDAG->getRegister(SP::G0, MVT::i32)), 0); + TopPart = CurDAG->getCopyToReg(TopPart, dl, SP::Y, TopPart, SDValue()).getValue(1); // FIXME: Handle div by immediate. unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr; @@ -185,7 +187,9 @@ SDNode *Mul = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Glue, MulLHS, MulRHS); // The high part is in the Y register. - return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDValue(Mul, 1)); + return CurDAG->SelectNodeTo(N, SP::RDASR, MVT::i32, + CurDAG->getRegister(SP::Y, MVT::i32), + SDValue(Mul, 1)); } } Index: llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td +++ llvm/trunk/lib/Target/Sparc/SparcInstrInfo.td @@ -705,20 +705,19 @@ } // Section B.28 - Read State Register Instructions -let Uses = [Y], rs1 = 0, rs2 = 0 in - def RDY : F3_1<2, 0b101000, - (outs IntRegs:$dst), (ins), - "rd %y, $dst", []>; +let rs2 = 0 in + def RDASR : F3_1<2, 0b101000, + (outs IntRegs:$rd), (ins ASRRegs:$rs1), + "rd $rs1, $rd", []>; // Section B.29 - Write State Register Instructions -let Defs = [Y], rd = 0 in { - def WRYrr : F3_1<2, 0b110000, - (outs), (ins IntRegs:$rs1, IntRegs:$rs2), - "wr $rs1, $rs2, %y", []>; - def WRYri : F3_2<2, 0b110000, - (outs), (ins IntRegs:$rs1, simm13Op:$simm13), - "wr $rs1, $simm13, %y", []>; -} +def WRASRrr : F3_1<2, 0b110000, + (outs ASRRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2), + "wr $rs1, $rs2, $rd", []>; +def WRASRri : F3_2<2, 0b110000, + (outs ASRRegs:$rd), (ins IntRegs:$rs1, simm13Op:$simm13), + "wr $rs1, $simm13, $rd", []>; + // Convert Integer to Floating-point Instructions, p. 141 def FITOS : F3_3u<2, 0b110100, 0b011000100, (outs FPRegs:$rd), (ins FPRegs:$rs2), Index: llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td =================================================================== --- llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td +++ llvm/trunk/lib/Target/Sparc/SparcRegisterInfo.td @@ -56,6 +56,38 @@ // Y register def Y : SparcCtrlReg<0, "Y">, DwarfRegNum<[64]>; +// Ancillary state registers (implementation defined) +def ASR1 : SparcCtrlReg<1, "ASR1">; +def ASR2 : SparcCtrlReg<2, "ASR2">; +def ASR3 : SparcCtrlReg<3, "ASR3">; +def ASR4 : SparcCtrlReg<4, "ASR4">; +def ASR5 : SparcCtrlReg<5, "ASR5">; +def ASR6 : SparcCtrlReg<6, "ASR6">; +def ASR7 : SparcCtrlReg<7, "ASR7">; +def ASR8 : SparcCtrlReg<8, "ASR8">; +def ASR9 : SparcCtrlReg<9, "ASR9">; +def ASR10 : SparcCtrlReg<10, "ASR10">; +def ASR11 : SparcCtrlReg<11, "ASR11">; +def ASR12 : SparcCtrlReg<12, "ASR12">; +def ASR13 : SparcCtrlReg<13, "ASR13">; +def ASR14 : SparcCtrlReg<14, "ASR14">; +def ASR15 : SparcCtrlReg<15, "ASR15">; +def ASR16 : SparcCtrlReg<16, "ASR16">; +def ASR17 : SparcCtrlReg<17, "ASR17">; +def ASR18 : SparcCtrlReg<18, "ASR18">; +def ASR19 : SparcCtrlReg<19, "ASR19">; +def ASR20 : SparcCtrlReg<20, "ASR20">; +def ASR21 : SparcCtrlReg<21, "ASR21">; +def ASR22 : SparcCtrlReg<22, "ASR22">; +def ASR23 : SparcCtrlReg<23, "ASR23">; +def ASR24 : SparcCtrlReg<24, "ASR24">; +def ASR25 : SparcCtrlReg<25, "ASR25">; +def ASR26 : SparcCtrlReg<26, "ASR26">; +def ASR27 : SparcCtrlReg<27, "ASR27">; +def ASR28 : SparcCtrlReg<28, "ASR28">; +def ASR29 : SparcCtrlReg<29, "ASR29">; +def ASR30 : SparcCtrlReg<30, "ASR30">; +def ASR31 : SparcCtrlReg<31, "ASR31">; // Integer registers def G0 : Ri< 0, "G0">, DwarfRegNum<[0]>; @@ -209,3 +241,7 @@ // Floating point control register classes. def FCCRegs : RegisterClass<"SP", [i1], 1, (sequence "FCC%u", 0, 3)>; + +// Ancillary state registers +def ASRRegs : RegisterClass<"SP", [i32], 32, + (add Y, (sequence "ASR%u", 1, 31))>; Index: llvm/trunk/test/CodeGen/SPARC/basictest.ll =================================================================== --- llvm/trunk/test/CodeGen/SPARC/basictest.ll +++ llvm/trunk/test/CodeGen/SPARC/basictest.ll @@ -36,3 +36,51 @@ ret i32 0 } +; CHECK-LABEL: signed_divide: +; CHECK: sra %o0, 31, %o2 +; CHECK: wr %o2, %g0, %y +; CHECK: sdiv %o0, %o1, %o0 +define i32 @signed_divide(i32 %a, i32 %b) { + %r = sdiv i32 %a, %b + ret i32 %r +} + +; CHECK-LABEL: unsigned_divide: +; CHECK: wr %g0, %g0, %y +; CHECK: udiv %o0, %o1, %o0 +define i32 @unsigned_divide(i32 %a, i32 %b) { + %r = udiv i32 %a, %b + ret i32 %r +} + +; CHECK-LABEL: multiply_32x32: +; CHECK: smul %o0, %o1, %o0 +define i32 @multiply_32x32(i32 %a, i32 %b) { + %r = mul i32 %a, %b + ret i32 %r +} + +; CHECK-LABEL: signed_multiply_32x32_64: +; CHECK: smul %o0, %o1, %o1 +; CHECK: rd %y, %o0 +define i64 @signed_multiply_32x32_64(i32 %a, i32 %b) { + %xa = sext i32 %a to i64 + %xb = sext i32 %b to i64 + %r = mul i64 %xa, %xb + ret i64 %r +} + +; CHECK-LABEL: unsigned_multiply_32x32_64: +; CHECK: umul %o0, %o1, %o2 +; CHECK: rd %y, %o2 +;FIXME: the smul in the output is totally redundant and should not there. +; CHECK: smul %o0, %o1, %o1 +; CHECK: retl +; CHECK: mov %o2, %o0 +define i64 @unsigned_multiply_32x32_64(i32 %a, i32 %b) { + %xa = zext i32 %a to i64 + %xb = zext i32 %b to i64 + %r = mul i64 %xa, %xb + ret i64 %r +} + Index: llvm/trunk/test/MC/Disassembler/Sparc/sparc.txt =================================================================== --- llvm/trunk/test/MC/Disassembler/Sparc/sparc.txt +++ llvm/trunk/test/MC/Disassembler/Sparc/sparc.txt @@ -200,3 +200,18 @@ # CHECK: rett %i7+8 0x81 0xcf 0xe0 0x08 + +# CHECK: rd %y, %i0 +0xb1 0x40 0x00 0x00 + +# CHECK: rd %asr1, %i0 +0xb1 0x40 0x40 0x00 + +# CHECK: wr %i0, 5, %y +0x81 0x86 0x20 0x05 + +# CHECK: wr %i0, %i1, %asr15 +0x9f 0x86 0x00 0x19 + +# CHECK: stbar +0x81 0x43 0xc0 0x00 Index: llvm/trunk/test/MC/Sparc/sparc-special-registers.s =================================================================== --- llvm/trunk/test/MC/Sparc/sparc-special-registers.s +++ llvm/trunk/test/MC/Sparc/sparc-special-registers.s @@ -0,0 +1,17 @@ +! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s +! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s + + ! CHECK: rd %y, %i0 ! encoding: [0xb1,0x40,0x00,0x00] + rd %y, %i0 + + ! CHECK: rd %asr1, %i0 ! encoding: [0xb1,0x40,0x40,0x00] + rd %asr1, %i0 + + ! CHECK: wr %i0, 5, %y ! encoding: [0x81,0x86,0x20,0x05] + wr %i0, 5, %y + + ! CHECK: wr %i0, %i1, %asr15 ! encoding: [0x9f,0x86,0x00,0x19] + wr %i0, %i1, %asr15 + + ! CHECK: rd %asr15, %g0 ! encoding: [0x81,0x43,0xc0,0x00] + rd %asr15, %g0