diff --git a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp index f6c58165497..d0621c1c795 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp @@ -39,6 +39,12 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { case Sparc::fixup_sparc_br19: return (Value >> 2) & 0x7ffff; + case Sparc::fixup_sparc_br16_2: + return (Value >> 2) & 0xc000; + + case Sparc::fixup_sparc_br16_14: + return (Value >> 2) & 0x3fff; + case Sparc::fixup_sparc_pc22: case Sparc::fixup_sparc_got22: case Sparc::fixup_sparc_tls_gd_hi22: @@ -106,6 +112,8 @@ namespace { { "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br16_2", 10, 2, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_sparc_br16_14", 18, 14, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_sparc_hi22", 10, 22, 0 }, { "fixup_sparc_lo10", 22, 10, 0 }, { "fixup_sparc_h44", 10, 22, 0 }, diff --git a/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h b/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h index 005a0242dc9..d42bcee6b3c 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h +++ b/lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h @@ -26,6 +26,10 @@ namespace llvm { /// branches on icc/xcc fixup_sparc_br19, + /// fixup_sparc_bpr - 16-bit fixup for bpr + fixup_sparc_br16_2, + fixup_sparc_br16_14, + /// fixup_sparc_hi22 - 22-bit fixup corresponding to %hi(foo) /// for sethi fixup_sparc_hi22, diff --git a/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp index 96665ef2454..310fbd913c7 100644 --- a/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +++ b/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp @@ -64,6 +64,10 @@ public: unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + }; } // end anonymous namespace @@ -192,6 +196,22 @@ getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo, (MCFixupKind)Sparc::fixup_sparc_br19)); return 0; } +unsigned SparcMCCodeEmitter:: +getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + if (MO.isReg() || MO.isImm()) + return getMachineOpValue(MI, MO, Fixups, STI); + + Fixups.push_back(MCFixup::Create(0, MO.getExpr(), + (MCFixupKind)Sparc::fixup_sparc_br16_2)); + Fixups.push_back(MCFixup::Create(0, MO.getExpr(), + (MCFixupKind)Sparc::fixup_sparc_br16_14)); + + return 0; +} + #include "SparcGenMCCodeEmitter.inc" diff --git a/lib/Target/Sparc/SparcCodeEmitter.cpp b/lib/Target/Sparc/SparcCodeEmitter.cpp index 6b5e4bf0f5b..97bacf2d319 100644 --- a/lib/Target/Sparc/SparcCodeEmitter.cpp +++ b/lib/Target/Sparc/SparcCodeEmitter.cpp @@ -78,6 +78,8 @@ private: unsigned) const; unsigned getBranchPredTargetOpValue(const MachineInstr &MI, unsigned) const; + unsigned getBranchOnRegTargetOpValue(const MachineInstr &MI, + unsigned) const; void emitWord(unsigned Word); @@ -206,6 +208,12 @@ unsigned SparcCodeEmitter::getBranchPredTargetOpValue(const MachineInstr &MI, return getMachineOpValue(MI, MO); } +unsigned SparcCodeEmitter::getBranchOnRegTargetOpValue(const MachineInstr &MI, + unsigned opIdx) const { + const MachineOperand MO = MI.getOperand(opIdx); + return getMachineOpValue(MI, MO); +} + unsigned SparcCodeEmitter::getRelocation(const MachineInstr &MI, const MachineOperand &MO) const { diff --git a/lib/Target/Sparc/SparcInstr64Bit.td b/lib/Target/Sparc/SparcInstr64Bit.td index 9232860ba61..9ac0e806171 100644 --- a/lib/Target/Sparc/SparcInstr64Bit.td +++ b/lib/Target/Sparc/SparcInstr64Bit.td @@ -344,6 +344,84 @@ def FMOVQ_XCC : F4_3<0b110101, 0b000011, (outs QFPRegs:$rd), } // opf_cc } // Uses, Constraints +// Branch On integer register with Prediction (BPr). +let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in +multiclass BranchOnReg cond, string OpcStr> { + def napt : F2_4; + def apt : F2_4; + def napn : F2_4; + def apn : F2_4; +} + +multiclass bpr_alias { + def : InstAlias; + def : InstAlias; +} + +defm BPZ : BranchOnReg<0b001, "brz">; +defm BPLEZ : BranchOnReg<0b010, "brlez">; +defm BPLZ : BranchOnReg<0b011, "brlz">; +defm BPNZ : BranchOnReg<0b101, "brnz">; +defm BPGZ : BranchOnReg<0b110, "brgz">; +defm BPGEZ : BranchOnReg<0b111, "brgez">; + +defm : bpr_alias<"brz", BPZnapt, BPZapt >; +defm : bpr_alias<"brlez", BPLEZnapt, BPLEZapt>; +defm : bpr_alias<"brlz", BPLZnapt, BPLZapt >; +defm : bpr_alias<"brnz", BPNZnapt, BPNZapt >; +defm : bpr_alias<"brgz", BPGZnapt, BPGZapt >; +defm : bpr_alias<"brgez", BPGEZnapt, BPGEZapt>; + +// Move integer register on register condition (MOVr). +multiclass MOVR< bits<3> rcond, string OpcStr> { + def rr : F4_4r<0b101111, 0b00000, rcond, (outs I64Regs:$rd), + (ins I64Regs:$rs1, IntRegs:$rs2), + !strconcat(OpcStr, " $rs1, $rs2, $rd"), []>; + + def ri : F4_4i<0b101111, rcond, (outs I64Regs:$rd), + (ins I64Regs:$rs1, i64imm:$simm10), + !strconcat(OpcStr, " $rs1, $simm10, $rd"), []>; +} + +defm MOVRRZ : MOVR<0b001, "movrz">; +defm MOVRLEZ : MOVR<0b010, "movrlez">; +defm MOVRLZ : MOVR<0b011, "movrlz">; +defm MOVRNZ : MOVR<0b101, "movrnz">; +defm MOVRGZ : MOVR<0b110, "movrgz">; +defm MOVRGEZ : MOVR<0b111, "movrgez">; + +// Move FP register on integer register condition (FMOVr). +multiclass FMOVR rcond, string OpcStr> { + + def S : F4_4r<0b110101, 0b00101, rcond, + (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2), + !strconcat(!strconcat("fmovrs", OpcStr)," $rs1, $rs2, $rd"), + []>; + def D : F4_4r<0b110101, 0b00110, rcond, + (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2), + !strconcat(!strconcat("fmovrd", OpcStr)," $rs1, $rs2, $rd"), + []>; + def Q : F4_4r<0b110101, 0b00111, rcond, + (outs FPRegs:$rd), (ins I64Regs:$rs1, FPRegs:$rs2), + !strconcat(!strconcat("fmovrq", OpcStr)," $rs1, $rs2, $rd"), + []>, Requires<[HasHardQuad]>; +} + +let Predicates = [HasV9] in { + defm FMOVRZ : FMOVR<0b001, "z">; + defm FMOVRLEZ : FMOVR<0b010, "lez">; + defm FMOVRLZ : FMOVR<0b011, "lz">; + defm FMOVRNZ : FMOVR<0b101, "nz">; + defm FMOVRGZ : FMOVR<0b110, "gz">; + defm FMOVRGEZ : FMOVR<0b111, "gez">; +} + //===----------------------------------------------------------------------===// // 64-bit Floating Point Conversions. //===----------------------------------------------------------------------===// diff --git a/lib/Target/Sparc/SparcInstrAliases.td b/lib/Target/Sparc/SparcInstrAliases.td index dc35544daa3..0ab93706df6 100644 --- a/lib/Target/Sparc/SparcInstrAliases.td +++ b/lib/Target/Sparc/SparcInstrAliases.td @@ -224,7 +224,6 @@ defm : fp_cond_alias<"le", 0b1101>; defm : fp_cond_alias<"ule", 0b1110>; defm : fp_cond_alias<"o", 0b1111>; - // Instruction aliases for JMPL. // jmp addr -> jmpl addr, %g0 diff --git a/lib/Target/Sparc/SparcInstrFormats.td b/lib/Target/Sparc/SparcInstrFormats.td index 6b0b0ce16a8..1ce25904f30 100644 --- a/lib/Target/Sparc/SparcInstrFormats.td +++ b/lib/Target/Sparc/SparcInstrFormats.td @@ -77,6 +77,25 @@ class F2_3 op2Val, bit annul, bit pred, let Inst{18-0} = imm19; } +class F2_4 cond, bit annul, bit pred, + dag outs, dag ins, string asmstr, list pattern> + : InstSP { + bits<16> imm16; + bits<5> rs1; + + let op = 0; // op = 0 + + let Inst{29} = annul; + let Inst{28} = 0; + let Inst{27-25} = cond; + let Inst{24-22} = 0b011; + let Inst{21-20} = imm16{15-14}; + let Inst{19} = pred; + let Inst{18-14} = rs1; + let Inst{13-0} = imm16{13-0}; +} + + //===----------------------------------------------------------------------===// // Format #3 instruction classes in the Sparc //===----------------------------------------------------------------------===// @@ -254,3 +273,27 @@ class F4_3 op3, bits<6> opf_low, dag outs, dag ins, let Inst{10-5} = opf_low; let Inst{4-0} = rs2; } + +class F4_4r op3, bits<5> opf_low, bits<3> rcond, dag outs, dag ins, + string asmstr, list pattern> + : F4 { + bits <5> rs1; + bits <5> rs2; + let Inst{18-14} = rs1; + let Inst{13} = 0; // IsImm + let Inst{12-10} = rcond; + let Inst{9-5} = opf_low; + let Inst{4-0} = rs2; +} + + +class F4_4i op3, bits<3> rcond, dag outs, dag ins, + string asmstr, list pattern> + : F4 { + bits<5> rs1; + bits<10> simm10; + let Inst{18-14} = rs1; + let Inst{13} = 1; // IsImm + let Inst{12-10} = rcond; + let Inst{9-0} = simm10; +} diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index b4d8ba55fd1..c7babc888e3 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -109,6 +109,10 @@ def bprtarget : Operand { let EncoderMethod = "getBranchPredTargetOpValue"; } +def bprtarget16 : Operand { + let EncoderMethod = "getBranchOnRegTargetOpValue"; +} + def calltarget : Operand { let EncoderMethod = "getCallTargetOpValue"; let DecoderMethod = "DecodeCall"; diff --git a/test/MC/Sparc/sparc64-ctrl-instructions.s b/test/MC/Sparc/sparc64-ctrl-instructions.s index 7d6d98e20fa..d3f633daf3f 100644 --- a/test/MC/Sparc/sparc64-ctrl-instructions.s +++ b/test/MC/Sparc/sparc64-ctrl-instructions.s @@ -1136,3 +1136,81 @@ ! CHECK: fbne,a,pn %fcc3, .BB0 ! encoding: [0x23,0b01110AAA,A,A] ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br19 fbne,a,pn %fcc3, .BB0 + + + ! CHECK: brz %g1, .BB0 ! encoding: [0x02,0b11AA1000,0b01BBBBBB,B] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2 + ! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14 + ! CHECK: brlez %g1, .BB0 ! encoding: [0x04,0b11AA1000,0b01BBBBBB,B] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2 + ! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14 + ! CHECK: brlz %g1, .BB0 ! encoding: [0x06,0b11AA1000,0b01BBBBBB,B] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2 + ! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14 + ! CHECK: brnz %g1, .BB0 ! encoding: [0x0a,0b11AA1000,0b01BBBBBB,B] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2 + ! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14 + ! CHECK: brgz %g1, .BB0 ! encoding: [0x0c,0b11AA1000,0b01BBBBBB,B] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2 + ! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14 + ! CHECK: brgez %g1, .BB0 ! encoding: [0x0e,0b11AA1000,0b01BBBBBB,B] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2 + ! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14 + + brz %g1, .BB0 + brlez %g1, .BB0 + brlz %g1, .BB0 + brnz %g1, .BB0 + brgz %g1, .BB0 + brgez %g1, .BB0 + + ! CHECK: brz %g1, .BB0 ! encoding: [0x02,0b11AA1000,0b01BBBBBB,B] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2 + ! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14 + brz,pt %g1, .BB0 + + ! CHECK: brz,a %g1, .BB0 ! encoding: [0x22,0b11AA1000,0b01BBBBBB,B] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2 + ! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14 + brz,a %g1, .BB0 + + ! CHECK: brz,a %g1, .BB0 ! encoding: [0x22,0b11AA1000,0b01BBBBBB,B] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2 + ! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14 + brz,a,pt %g1, .BB0 + + ! CHECK: brz,pn %g1, .BB0 ! encoding: [0x02,0b11AA0000,0b01BBBBBB,B] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2 + ! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14 + brz,pn %g1, .BB0 + + ! CHECK: brz,a,pn %g1, .BB0 ! encoding: [0x22,0b11AA0000,0b01BBBBBB,B] + ! CHECK-NEXT: ! fixup A - offset: 0, value: .BB0, kind: fixup_sparc_br16_2 + ! CHECK-NEXT: ! fixup B - offset: 0, value: .BB0, kind: fixup_sparc_br16_14 + brz,a,pn %g1, .BB0 + + ! CHECK: movrz %g1, %g2, %g3 ! encoding: [0x87,0x78,0x44,0x02] + ! CHECK: movrlez %g1, %g2, %g3 ! encoding: [0x87,0x78,0x48,0x02] + ! CHECK: movrlz %g1, %g2, %g3 ! encoding: [0x87,0x78,0x4c,0x02] + ! CHECK: movrnz %g1, %g2, %g3 ! encoding: [0x87,0x78,0x54,0x02] + ! CHECK: movrgz %g1, %g2, %g3 ! encoding: [0x87,0x78,0x58,0x02] + ! CHECK: movrgez %g1, %g2, %g3 ! encoding: [0x87,0x78,0x5c,0x02] + movrz %g1, %g2, %g3 + movrlez %g1, %g2, %g3 + movrlz %g1, %g2, %g3 + movrnz %g1, %g2, %g3 + movrgz %g1, %g2, %g3 + movrgez %g1, %g2, %g3 + + ! CHECK: fmovrsz %g1, %f2, %f3 ! encoding: [0x87,0xa8,0x44,0xa2] + ! CHECK: fmovrslez %g1, %f2, %f3 ! encoding: [0x87,0xa8,0x48,0xa2] + ! CHECK: fmovrslz %g1, %f2, %f3 ! encoding: [0x87,0xa8,0x4c,0xa2] + ! CHECK: fmovrsnz %g1, %f2, %f3 ! encoding: [0x87,0xa8,0x54,0xa2] + ! CHECK: fmovrsgz %g1, %f2, %f3 ! encoding: [0x87,0xa8,0x58,0xa2] + ! CHECK: fmovrsgez %g1, %f2, %f3 ! encoding: [0x87,0xa8,0x5c,0xa2] + fmovrsz %g1, %f2, %f3 + fmovrslez %g1, %f2, %f3 + fmovrslz %g1, %f2, %f3 + fmovrsnz %g1, %f2, %f3 + fmovrsgz %g1, %f2, %f3 + fmovrsgez %g1, %f2, %f3