]> granicus.if.org Git - llvm/commitdiff
[SystemZ] Add remaining branch instructions
authorUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 28 Nov 2016 13:40:08 +0000 (13:40 +0000)
committerUlrich Weigand <ulrich.weigand@de.ibm.com>
Mon, 28 Nov 2016 13:40:08 +0000 (13:40 +0000)
This patch adds assembler support for the remaining branch instructions:
the non-relative branch on count variants, and all variants of branch
on index.

The only one of those that can be readily exploited for code generation
is BRCTH (branch on count using a high 32-bit register as count).  Do
use it, however, it is necessary to also introduce a hew CHIMux pseudo
to allow comparisons of a 32-bit value agains a short immediate to go
into a high register as well (implemented via CHI/CIH).

This causes a bit of codegen changes overall, but those have proven to
be neutral (or even beneficial) in performance measurements.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@288029 91177308-0d34-0410-b5e6-96231b3b80d8

15 files changed:
lib/Target/SystemZ/SystemZElimCompare.cpp
lib/Target/SystemZ/SystemZInstrFormats.td
lib/Target/SystemZ/SystemZInstrInfo.cpp
lib/Target/SystemZ/SystemZInstrInfo.td
lib/Target/SystemZ/SystemZLongBranch.cpp
lib/Target/SystemZ/SystemZScheduleZ13.td
lib/Target/SystemZ/SystemZScheduleZ196.td
lib/Target/SystemZ/SystemZScheduleZEC12.td
test/CodeGen/SystemZ/loop-02.ll [new file with mode: 0644]
test/MC/Disassembler/SystemZ/insns-pcrel.txt
test/MC/Disassembler/SystemZ/insns.txt
test/MC/SystemZ/insn-bad-z196.s
test/MC/SystemZ/insn-bad.s
test/MC/SystemZ/insn-good-z196.s
test/MC/SystemZ/insn-good.s

index 6b07c5404006ec2ba51221519241eb979c05cc63..b292b55477908ec9b0940596ceb986911283a3f3 100644 (file)
@@ -171,7 +171,7 @@ static unsigned getCompareSourceReg(MachineInstr &Compare) {
 
 // Compare compares the result of MI against zero.  If MI is an addition
 // of -1 and if CCUsers is a single branch on nonzero, eliminate the addition
-// and convert the branch to a BRCT(G).  Return true on success.
+// and convert the branch to a BRCT(G) or BRCTH.  Return true on success.
 bool SystemZElimCompare::convertToBRCT(
     MachineInstr &MI, MachineInstr &Compare,
     SmallVectorImpl<MachineInstr *> &CCUsers) {
@@ -182,6 +182,8 @@ bool SystemZElimCompare::convertToBRCT(
     BRCT = SystemZ::BRCT;
   else if (Opcode == SystemZ::AGHI)
     BRCT = SystemZ::BRCTG;
+  else if (Opcode == SystemZ::AIH)
+    BRCT = SystemZ::BRCTH;
   else
     return false;
   if (MI.getOperand(2).getImm() != -1)
@@ -205,16 +207,20 @@ bool SystemZElimCompare::convertToBRCT(
     if (getRegReferences(*MBBI, SrcReg))
       return false;
 
-  // The transformation is OK.  Rebuild Branch as a BRCT(G).
+  // The transformation is OK.  Rebuild Branch as a BRCT(G) or BRCTH.
   MachineOperand Target(Branch->getOperand(2));
   while (Branch->getNumOperands())
     Branch->RemoveOperand(0);
   Branch->setDesc(TII->get(BRCT));
-  MachineInstrBuilder(*Branch->getParent()->getParent(), Branch)
-      .addOperand(MI.getOperand(0))
-      .addOperand(MI.getOperand(1))
-      .addOperand(Target)
-      .addReg(SystemZ::CC, RegState::ImplicitDefine | RegState::Dead);
+  MachineInstrBuilder MIB(*Branch->getParent()->getParent(), Branch);
+  MIB.addOperand(MI.getOperand(0))
+     .addOperand(MI.getOperand(1))
+     .addOperand(Target);
+  // Add a CC def to BRCT(G), since we may have to split them again if the
+  // branch displacement overflows.  BRCTH has a 32-bit displacement, so
+  // this is not necessary there.
+  if (BRCT != SystemZ::BRCTH)
+    MIB.addReg(SystemZ::CC, RegState::ImplicitDefine | RegState::Dead);
   MI.eraseFromParent();
   return true;
 }
index 7a3aa40fc9d59705e8ec6baaf8a2794be3cf82ea..a5c1c2680d5b8ffe6f2a3d4cfe633cce3bcfb51d 100644 (file)
@@ -291,6 +291,23 @@ class InstRIEd<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
   let Inst{7-0}   = op{7-0};
 }
 
+class InstRIEe<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+  : InstSystemZ<6, outs, ins, asmstr, pattern> {
+  field bits<48> Inst;
+  field bits<48> SoftFail = 0;
+
+  bits<4> R1;
+  bits<4> R3;
+  bits<16> RI2;
+
+  let Inst{47-40} = op{15-8};
+  let Inst{39-36} = R1;
+  let Inst{35-32} = R3;
+  let Inst{31-16} = RI2;
+  let Inst{15-8}  = 0;
+  let Inst{7-0}   = op{7-0};
+}
+
 class InstRIEf<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
   : InstSystemZ<6, outs, ins, asmstr, pattern> {
   field bits<48> Inst;
@@ -1506,15 +1523,14 @@ class ICV<string name>
 //     compares the two input operands and branches or traps on the result.
 //
 //   BranchUnary:
-//     One register output operand, one register input operand and
-//     one branch displacement.  The instructions stores a modified
-//     form of the source register in the destination register and
-//     branches on the result.
+//     One register output operand, one register input operand and one branch
+//     target.  The instructions stores a modified form of the source register
+//     in the destination register and branches on the result.
 //
 //   BranchBinary:
 //     One register output operand, two register input operands and one branch
-//     displacement. The instructions stores a modified form of one of the
-//     source registers in the destination register and branches on the result.
+//     target. The instructions stores a modified form of one of the source
+//     registers in the destination register and branches on the result.
 //
 //   LoadMultiple:
 //     One address input operand and two explicit output operands.
@@ -1911,6 +1927,41 @@ class BranchUnaryRI<string mnemonic, bits<12> opcode, RegisterOperand cls>
   let DisableEncoding = "$R1src";
 }
 
+class BranchUnaryRIL<string mnemonic, bits<12> opcode, RegisterOperand cls>
+  : InstRILb<opcode, (outs cls:$R1), (ins cls:$R1src, brtarget32:$RI2),
+             mnemonic##"\t$R1, $RI2", []> {
+  let Constraints = "$R1 = $R1src";
+  let DisableEncoding = "$R1src";
+}
+
+class BranchUnaryRR<string mnemonic, bits<8> opcode, RegisterOperand cls>
+  : InstRR<opcode, (outs cls:$R1), (ins cls:$R1src, GR64:$R2),
+           mnemonic##"\t$R1, $R2", []> {
+  let Constraints = "$R1 = $R1src";
+  let DisableEncoding = "$R1src";
+}
+
+class BranchUnaryRRE<string mnemonic, bits<16> opcode, RegisterOperand cls>
+  : InstRRE<opcode, (outs cls:$R1), (ins cls:$R1src, GR64:$R2),
+            mnemonic##"\t$R1, $R2", []> {
+  let Constraints = "$R1 = $R1src";
+  let DisableEncoding = "$R1src";
+}
+
+class BranchUnaryRX<string mnemonic, bits<8> opcode, RegisterOperand cls>
+  : InstRXa<opcode, (outs cls:$R1), (ins cls:$R1src, bdxaddr12only:$XBD2),
+            mnemonic##"\t$R1, $XBD2", []> {
+  let Constraints = "$R1 = $R1src";
+  let DisableEncoding = "$R1src";
+}
+
+class BranchUnaryRXY<string mnemonic, bits<16> opcode, RegisterOperand cls>
+  : InstRXYa<opcode, (outs cls:$R1), (ins cls:$R1src, bdxaddr20only:$XBD2),
+             mnemonic##"\t$R1, $XBD2", []> {
+  let Constraints = "$R1 = $R1src";
+  let DisableEncoding = "$R1src";
+}
+
 class BranchBinaryRSI<string mnemonic, bits<8> opcode, RegisterOperand cls>
   : InstRSI<opcode, (outs cls:$R1), (ins cls:$R1src, cls:$R3, brtarget16:$RI2),
             mnemonic##"\t$R1, $R3, $RI2", []> {
@@ -1918,6 +1969,30 @@ class BranchBinaryRSI<string mnemonic, bits<8> opcode, RegisterOperand cls>
   let DisableEncoding = "$R1src";
 }
 
+class BranchBinaryRIEe<string mnemonic, bits<16> opcode, RegisterOperand cls>
+  : InstRIEe<opcode, (outs cls:$R1),
+             (ins cls:$R1src, cls:$R3, brtarget16:$RI2),
+             mnemonic##"\t$R1, $R3, $RI2", []> {
+  let Constraints = "$R1 = $R1src";
+  let DisableEncoding = "$R1src";
+}
+
+class BranchBinaryRS<string mnemonic, bits<8> opcode, RegisterOperand cls>
+  : InstRSa<opcode, (outs cls:$R1),
+            (ins cls:$R1src, cls:$R3, bdaddr12only:$BD2),
+            mnemonic##"\t$R1, $R3, $BD2", []> {
+  let Constraints = "$R1 = $R1src";
+  let DisableEncoding = "$R1src";
+}
+
+class BranchBinaryRSY<string mnemonic, bits<16> opcode, RegisterOperand cls>
+  : InstRSYa<opcode,
+             (outs cls:$R1), (ins cls:$R1src, cls:$R3, bdaddr20only:$BD2),
+             mnemonic##"\t$R1, $R3, $BD2", []> {
+  let Constraints = "$R1 = $R1src";
+  let DisableEncoding = "$R1src";
+}
+
 class LoadMultipleRS<string mnemonic, bits<8> opcode, RegisterOperand cls,
                      AddressingMode mode = bdaddr12only>
   : InstRSa<opcode, (outs cls:$R1, cls:$R3), (ins mode:$BD2),
@@ -3639,7 +3714,9 @@ multiclass BinaryRIAndKPseudo<string key, SDPatternOperator operator,
 // Like CompareRI, but expanded after RA depending on the choice of register.
 class CompareRIPseudo<SDPatternOperator operator, RegisterOperand cls,
                       Immediate imm>
-  : Pseudo<(outs), (ins cls:$R1, imm:$I2), [(operator cls:$R1, imm:$I2)]>;
+  : Pseudo<(outs), (ins cls:$R1, imm:$I2), [(operator cls:$R1, imm:$I2)]> {
+  let isCompare = 1;
+}
 
 // Like CompareRXY, but expanded after RA depending on the choice of register.
 class CompareRXYPseudo<SDPatternOperator operator, RegisterOperand cls,
index 8f1b5575902ea094471010c7d74b48c2330909a0..7b835b04fd3f47216cf0dd899f890700f59fba47 100644 (file)
@@ -1321,6 +1321,10 @@ bool SystemZInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
     expandRIPseudo(MI, SystemZ::AFI, SystemZ::AIH, false);
     return true;
 
+  case SystemZ::CHIMux:
+    expandRIPseudo(MI, SystemZ::CHI, SystemZ::CIH, false);
+    return true;
+
   case SystemZ::CFIMux:
     expandRIPseudo(MI, SystemZ::CFI, SystemZ::CIH, false);
     return true;
@@ -1386,6 +1390,7 @@ SystemZInstrInfo::getBranchInfo(const MachineInstr &MI) const {
                              MI.getOperand(1).getImm(), &MI.getOperand(2));
 
   case SystemZ::BRCT:
+  case SystemZ::BRCTH:
     return SystemZII::Branch(SystemZII::BranchCT, SystemZ::CCMASK_ICMP,
                              SystemZ::CCMASK_CMP_NE, &MI.getOperand(2));
 
index 28c8557c78dc28fba6127b3efb394cf6c0521640..87a70da68566af8eabd7277d853236166ceb2536 100644 (file)
@@ -155,15 +155,33 @@ let isBranch = 1, isTerminator = 1 in {
 }
 
 // Decrement a register and branch if it is nonzero.  These don't clobber CC,
-// but we might need to split long branches into sequences that do.
-let isBranch = 1, isTerminator = 1, Defs = [CC] in {
-  def BRCT  : BranchUnaryRI<"brct",  0xA76, GR32>;
-  def BRCTG : BranchUnaryRI<"brctg", 0xA77, GR64>;
+// but we might need to split long relative branches into sequences that do.
+let isBranch = 1, isTerminator = 1 in {
+  let Defs = [CC] in {
+    def BRCT  : BranchUnaryRI<"brct",  0xA76, GR32>;
+    def BRCTG : BranchUnaryRI<"brctg", 0xA77, GR64>;
+  }
+  // This doesn't need to clobber CC since we never need to split it.
+  def BRCTH : BranchUnaryRIL<"brcth", 0xCC6, GRH32>,
+              Requires<[FeatureHighWord]>;
+
+  def BCT   : BranchUnaryRX<"bct",  0x46,GR32>;
+  def BCTR  : BranchUnaryRR<"bctr", 0x06, GR32>;
+  def BCTG  : BranchUnaryRXY<"bctg",  0xE346, GR64>;
+  def BCTGR : BranchUnaryRRE<"bctgr", 0xB946, GR64>;
 }
 
-let isBranch = 1, isTerminator = 1, Defs = [CC] in {
-  def BRXH  : BranchBinaryRSI<"brxh",  0x84, GR32>;
-  def BRXLE : BranchBinaryRSI<"brxle", 0x85, GR32>;
+let isBranch = 1, isTerminator = 1 in {
+  let Defs = [CC] in {
+    def BRXH  : BranchBinaryRSI<"brxh",  0x84, GR32>;
+    def BRXLE : BranchBinaryRSI<"brxle", 0x85, GR32>;
+    def BRXHG : BranchBinaryRIEe<"brxhg", 0xEC44, GR64>;
+    def BRXLG : BranchBinaryRIEe<"brxlg", 0xEC45, GR64>;
+  }
+  def BXH   : BranchBinaryRS<"bxh",  0x86, GR32>;
+  def BXLE  : BranchBinaryRS<"bxle", 0x87, GR32>;
+  def BXHG  : BranchBinaryRSY<"bxhg",  0xEB44, GR64>;
+  def BXLEG : BranchBinaryRSY<"bxleg", 0xEB45, GR64>;
 }
 
 //===----------------------------------------------------------------------===//
@@ -1235,7 +1253,10 @@ let Defs = [CC], CCValues = 0xE in {
   def CGFR : CompareRRE<"cgfr", 0xB930, null_frag, GR64, GR32>;
   def CGR  : CompareRRE<"cgr",  0xB920, z_scmp,    GR64, GR64>;
 
-  // Comparison with a signed 16-bit immediate.
+  // Comparison with a signed 16-bit immediate.  CHIMux expands to CHI or CIH,
+  // depending on the choice of register.
+  def CHIMux : CompareRIPseudo<z_scmp, GRX32, imm32sx16>,
+               Requires<[FeatureHighWord]>;
   def CHI  : CompareRI<"chi",  0xA7E, z_scmp, GR32, imm32sx16>;
   def CGHI : CompareRI<"cghi", 0xA7F, z_scmp, GR64, imm64sx16>;
 
index 0be0396034c409eb5450c60c33331bf171ec4efa..14ff6afbd4aebdca29aa28a30d25911a13980900 100644 (file)
@@ -226,6 +226,10 @@ TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr &MI) {
       // Relaxes to A(G)HI and BRCL, which is 6 bytes longer.
       Terminator.ExtraRelaxSize = 6;
       break;
+    case SystemZ::BRCTH:
+      // Never needs to be relaxed.
+      Terminator.ExtraRelaxSize = 0;
+      break;
     case SystemZ::CRJ:
     case SystemZ::CLRJ:
       // Relaxes to a C(L)R/BRCL sequence, which is 2 bytes longer.
index 0030ed1f950edc526dc738ee2991ecef28e73c1a..c9007e59bcbe416c89587ebd46da173a36f82c5d 100644 (file)
@@ -116,7 +116,10 @@ def : InstRW<[VBU], (instregex "(Call)?J(G)?(Asm.*)?$")>;
 def : InstRW<[FXb], (instregex "(Call)?BC(R)?(Asm.*)?$")>;
 def : InstRW<[FXb], (instregex "(Call)?B(R)?(Asm.*)?$")>;
 def : InstRW<[FXa, EndGroup], (instregex "BRCT(G)?$")>;
-def : InstRW<[FXa, FXa, FXb, FXb, Lat4, GroupAlone], (instregex "BRX(H|LE)$")>;
+def : InstRW<[FXb, FXa, Lat2, GroupAlone], (instregex "BRCTH$")>;
+def : InstRW<[FXb, FXa, Lat2, GroupAlone], (instregex "BCT(G)?(R)?$")>;
+def : InstRW<[FXa, FXa, FXb, FXb, Lat4, GroupAlone],
+             (instregex "B(R)?X(H|L).*$")>;
 
 // Compare and branch
 def : InstRW<[FXb], (instregex "C(L)?(G)?(I|R)J(Asm.*)?$")>;
@@ -466,11 +469,11 @@ def : InstRW<[FXa, FXa, Lat3, BeginGroup], (instregex "R(N|O|X)SBG$")>;
 //===----------------------------------------------------------------------===//
 
 def : InstRW<[FXb, LSU, Lat5], (instregex "C(G|Y|Mux|RL)?$")>;
-def : InstRW<[FXb], (instregex "CFI(Mux)?$")>;
+def : InstRW<[FXb], (instregex "C(F|H)I(Mux)?$")>;
 def : InstRW<[FXb], (instregex "CG(F|H)I$")>;
 def : InstRW<[FXb, LSU, Lat5], (instregex "CG(HSI|RL)$")>;
 def : InstRW<[FXb], (instregex "C(G)?R$")>;
-def : InstRW<[FXb], (instregex "C(HI|IH)$")>;
+def : InstRW<[FXb], (instregex "CIH$")>;
 def : InstRW<[FXb, LSU, Lat5], (instregex "CH(F|SI)$")>;
 def : InstRW<[FXb, LSU, Lat5], (instregex "CL(Y|Mux|FHSI)?$")>;
 def : InstRW<[FXb], (instregex "CLFI(Mux)?$")>;
index 4d4a912b5d1a7238b2683d3856d7e5081d42e85a..f8e0ccbcea0fd1744f07262d7f543df2bd410c88 100644 (file)
@@ -90,8 +90,10 @@ def : InstRW<[LSU, EndGroup], (instregex "(Call)?BRC(L)?(Asm.*)?$")>;
 def : InstRW<[LSU, EndGroup], (instregex "(Call)?J(G)?(Asm.*)?$")>;
 def : InstRW<[LSU, EndGroup], (instregex "(Call)?BC(R)?(Asm.*)?$")>;
 def : InstRW<[LSU, EndGroup], (instregex "(Call)?B(R)?(Asm.*)?$")>;
-def : InstRW<[FXU, LSU, Lat5, GroupAlone], (instregex "BRCT(G)?$")>;
-def : InstRW<[FXU, FXU, FXU, LSU, Lat7, GroupAlone], (instregex "BRX(H|LE)$")>;
+def : InstRW<[FXU, LSU, Lat5, GroupAlone], (instregex "BRCT(G|H)?$")>;
+def : InstRW<[FXU, LSU, Lat5, GroupAlone], (instregex "BCT(G)?(R)?$")>;
+def : InstRW<[FXU, FXU, FXU, LSU, Lat7, GroupAlone],
+             (instregex "B(R)?X(H|L).*$")>;
 
 // Compare and branch
 def : InstRW<[FXU, LSU, Lat5, GroupAlone],
@@ -433,11 +435,11 @@ def : InstRW<[FXU, FXU, Lat3, GroupAlone], (instregex "R(N|O|X)SBG$")>;
 //===----------------------------------------------------------------------===//
 
 def : InstRW<[FXU, LSU, Lat5], (instregex "C(G|Y|Mux|RL)?$")>;
-def : InstRW<[FXU], (instregex "CFI(Mux)?$")>;
+def : InstRW<[FXU], (instregex "C(F|H)I(Mux)?$")>;
 def : InstRW<[FXU], (instregex "CG(F|H)I$")>;
 def : InstRW<[FXU, LSU, Lat5], (instregex "CG(HSI|RL)$")>;
 def : InstRW<[FXU], (instregex "C(G)?R$")>;
-def : InstRW<[FXU], (instregex "C(HI|IH)$")>;
+def : InstRW<[FXU], (instregex "CIH$")>;
 def : InstRW<[FXU, LSU, Lat5], (instregex "CH(F|SI)$")>;
 def : InstRW<[FXU, LSU, Lat5], (instregex "CL(Y|Mux|FHSI)?$")>;
 def : InstRW<[FXU], (instregex "CLFI(Mux)?$")>;
index 69c70bbe28fd10430dcc04af72be8527c3458fd1..7300874977383d518a9dc7272de622cf385ab053 100644 (file)
@@ -93,7 +93,10 @@ def : InstRW<[VBU], (instregex "(Call)?J(G)?(Asm.*)?$")>;
 def : InstRW<[LSU, Lat4], (instregex "(Call)?BC(R)?(Asm.*)?$")>;
 def : InstRW<[LSU, Lat4], (instregex "(Call)?B(R)?(Asm.*)?$")>;
 def : InstRW<[FXU, EndGroup], (instregex "BRCT(G)?$")>;
-def : InstRW<[FXU, FXU, FXU, LSU, Lat7, GroupAlone], (instregex "BRX(H|LE)$")>;
+def : InstRW<[FXU, LSU, Lat5, GroupAlone], (instregex "BRCTH$")>;
+def : InstRW<[FXU, LSU, Lat5, GroupAlone], (instregex "BCT(G)?(R)?$")>;
+def : InstRW<[FXU, FXU, FXU, LSU, Lat7, GroupAlone],
+             (instregex "B(R)?X(H|L).*$")>;
 
 // Compare and branch
 def : InstRW<[FXU], (instregex "C(L)?(G)?(I|R)J(Asm.*)?$")>;
@@ -436,11 +439,11 @@ def : InstRW<[FXU, FXU, Lat3, GroupAlone], (instregex "R(N|O|X)SBG$")>;
 //===----------------------------------------------------------------------===//
 
 def : InstRW<[FXU, LSU, Lat5], (instregex "C(G|Y|Mux|RL)?$")>;
-def : InstRW<[FXU], (instregex "CFI(Mux)?$")>;
+def : InstRW<[FXU], (instregex "C(F|H)I(Mux)?$")>;
 def : InstRW<[FXU], (instregex "CG(F|H)I$")>;
 def : InstRW<[FXU, LSU, Lat5], (instregex "CG(HSI|RL)$")>;
 def : InstRW<[FXU], (instregex "C(G)?R$")>;
-def : InstRW<[FXU], (instregex "C(HI|IH)$")>;
+def : InstRW<[FXU], (instregex "CIH$")>;
 def : InstRW<[FXU, LSU, Lat5], (instregex "CH(F|SI)$")>;
 def : InstRW<[FXU, LSU, Lat5], (instregex "CL(Y|Mux|FHSI)?$")>;
 def : InstRW<[FXU], (instregex "CLFI(Mux)?$")>;
diff --git a/test/CodeGen/SystemZ/loop-02.ll b/test/CodeGen/SystemZ/loop-02.ll
new file mode 100644 (file)
index 0000000..a3c1cf6
--- /dev/null
@@ -0,0 +1,38 @@
+; Test BRCTH.
+
+; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -mcpu=z196 \
+; RUN:   -no-integrated-as | FileCheck %s
+
+; Test a loop that should be converted into dbr form and then use BRCTH.
+define void @f2(i32 *%src, i32 *%dest) {
+; CHECK-LABEL: f2:
+; CHECK: blah [[REG:%r[0-5]]]
+; CHECK: [[LABEL:\.[^:]*]]:{{.*}} %loop
+; CHECK: brcth [[REG]], [[LABEL]]
+; CHECK: br %r14
+entry:
+  ; Force upper bound into a high register in order to encourage the
+  ; register allocator to use a high register for the count variable.
+  %top = call i32 asm sideeffect "blah $0", "=h"()
+  br label %loop
+
+loop:
+  %count = phi i32 [ 0, %entry ], [ %next, %loop.next ]
+  %next = add i32 %count, 1
+  %val = load volatile i32 , i32 *%src
+  %cmp = icmp eq i32 %val, 0
+  br i1 %cmp, label %loop.next, label %loop.store
+
+loop.store:
+  %add = add i32 %val, 1
+  store volatile i32 %add, i32 *%dest
+  br label %loop.next
+
+loop.next:
+  %cont = icmp ne i32 %next, %top
+  br i1 %cont, label %loop, label %exit
+
+exit:
+  ret void
+}
+
index d6ef5ac1698755da4bb35c1c20d7cd6f6ae2eb5e..8c6149e193c17a8ed1c8b7968d7ce3bff7c7af5d 100644 (file)
@@ -1,7 +1,7 @@
 # Test instructions that have PC-relative operands.  There is no attempt
 # to keep the instructions in alphabetical order, since adding new instructions
 # in the middle would mean updating all later offsets.
-# RUN: llvm-mc --disassemble %s -triple=s390x-linux-gnu | FileCheck %s
+# RUN: llvm-mc --disassemble %s -triple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s
 
 # 0x00000000:
 # CHECK: brasl %r0, 0x0
 # 0x00000a34:
 # CHECK: brxle %r15, %r1, 0x10a32
 0x85 0xf1 0x7f 0xff
+
+# 0x00000a38:
+# CHECK: brxhg %r0, %r1, 0xa38
+0xec 0x01 0x00 0x00 0x00 0x44
+
+# 0x00000a3e:
+# CHECK: brxhg %r14, %r1, 0xa3e
+0xec 0xe1 0x00 0x00 0x00 0x44
+
+# 0x00000a44:
+# CHECK: brxhg %r15, %r1, 0xa44
+0xec 0xf1 0x00 0x00 0x00 0x44
+
+# 0x00000a4a:
+# CHECK: brxhg %r0, %r1, 0xa48
+0xec 0x01 0xff 0xff 0x00 0x44
+
+# 0x00000a50:
+# CHECK: brxhg %r14, %r1, 0xffffffffffff0a50
+0xec 0xe1 0x80 0x00 0x00 0x44
+
+# 0x00000a56:
+# CHECK: brxhg %r15, %r1, 0x10a54
+0xec 0xf1 0x7f 0xff 0x00 0x44
+
+# 0x00000a5c:
+# CHECK: brxlg %r0, %r1, 0xa5c
+0xec 0x01 0x00 0x00 0x00 0x45
+
+# 0x00000a62:
+# CHECK: brxlg %r14, %r1, 0xa62
+0xec 0xe1 0x00 0x00 0x00 0x45
+
+# 0x00000a68:
+# CHECK: brxlg %r15, %r1, 0xa68
+0xec 0xf1 0x00 0x00 0x00 0x45
+
+# 0x00000a6e:
+# CHECK: brxlg %r0, %r1, 0xa6c
+0xec 0x01 0xff 0xff 0x00 0x45
+
+# 0x00000a74:
+# CHECK: brxlg %r14, %r1, 0xffffffffffff0a74
+0xec 0xe1 0x80 0x00 0x00 0x45
+
+# 0x00000a7a:
+# CHECK: brxlg %r15, %r1, 0x10a78
+0xec 0xf1 0x7f 0xff 0x00 0x45
+
+# 0x00000a80:
+# CHECK: brcth %r0, 0xa80
+0xcc 0x06 0x00 0x00 0x00 0x00
+
+# 0x00000a86:
+# CHECK: brcth %r14, 0xa86
+0xcc 0xe6 0x00 0x00 0x00 0x00
+
+# 0x00000a8c:
+# CHECK: brcth %r15, 0xa8c
+0xcc 0xf6 0x00 0x00 0x00 0x00
+
+# 0x00000a92:
+# CHECK: brcth %r0, 0xa90
+0xcc 0x06 0xff 0xff 0xff 0xff
+
+# 0x00000a98:
+# CHECK: brcth %r14, 0xffffffff00000a98
+0xcc 0xe6 0x80 0x00 0x00 0x00
+
+# 0x00000a9e:
+# CHECK: brcth %r15, 0x100000a9c
+0xcc 0xf6 0x7f 0xff 0xff 0xff
+
index ccbfc5f1c5399e15b50aa98912615c2902991eff..1c521a512b6bf2896088ebc9b48d0aa4dd64ca86 100644 (file)
 # CHECK: br %r15
 0x07 0xff
 
+# CHECK: bct %r0, 0
+0x46 0x00 0x00 0x00
+
+# CHECK: bct %r0, 4095
+0x46 0x00 0x0f 0xff
+
+# CHECK: bct %r0, 0(%r1)
+0x46 0x00 0x10 0x00
+
+# CHECK: bct %r0, 0(%r15)
+0x46 0x00 0xf0 0x00
+
+# CHECK: bct %r0, 4095(%r1,%r15)
+0x46 0x01 0xff 0xff
+
+# CHECK: bct %r0, 4095(%r15,%r1)
+0x46 0x0f 0x1f 0xff
+
+# CHECK: bct %r15, 0
+0x46 0xf0 0x00 0x00
+
+# CHECK: bctr %r0, %r9
+0x06 0x09
+
+# CHECK: bctr %r0, %r15
+0x06 0x0f
+
+# CHECK: bctr %r15, %r0
+0x06 0xf0
+
+# CHECK: bctr %r15, %r9
+0x06 0xf9
+
+# CHECK: bctg %r0, -524288
+0xe3 0x00 0x00 0x00 0x80 0x46
+
+# CHECK: bctg %r0, -1
+0xe3 0x00 0x0f 0xff 0xff 0x46
+
+# CHECK: bctg %r0, 0
+0xe3 0x00 0x00 0x00 0x00 0x46
+
+# CHECK: bctg %r0, 1
+0xe3 0x00 0x00 0x01 0x00 0x46
+
+# CHECK: bctg %r0, 524287
+0xe3 0x00 0x0f 0xff 0x7f 0x46
+
+# CHECK: bctg %r0, 0(%r1)
+0xe3 0x00 0x10 0x00 0x00 0x46
+
+# CHECK: bctg %r0, 0(%r15)
+0xe3 0x00 0xf0 0x00 0x00 0x46
+
+# CHECK: bctg %r0, 524287(%r1,%r15)
+0xe3 0x01 0xff 0xff 0x7f 0x46
+
+# CHECK: bctg %r0, 524287(%r15,%r1)
+0xe3 0x0f 0x1f 0xff 0x7f 0x46
+
+# CHECK: bctg %r15, 0
+0xe3 0xf0 0x00 0x00 0x00 0x46
+
+# CHECK: bctgr %r0, %r9
+0xb9 0x46 0x00 0x09
+
+# CHECK: bctgr %r0, %r15
+0xb9 0x46 0x00 0x0f
+
+# CHECK: bctgr %r15, %r0
+0xb9 0x46 0x00 0xf0
+
+# CHECK: bctgr %r15, %r9
+0xb9 0x46 0x00 0xf9
+
+# CHECK: bxh %r0, %r0, 0
+0x86 0x00 0x00 0x00
+
+# CHECK: bxh %r0, %r15, 0
+0x86 0x0f 0x00 0x00
+
+# CHECK: bxh %r14, %r15, 0
+0x86 0xef 0x00 0x00
+
+# CHECK: bxh %r15, %r15, 0
+0x86 0xff 0x00 0x00
+
+# CHECK: bxh %r0, %r0, 4095
+0x86 0x00 0x0f 0xff
+
+# CHECK: bxh %r0, %r0, 1
+0x86 0x00 0x00 0x01
+
+# CHECK: bxh %r0, %r0, 0(%r1)
+0x86 0x00 0x10 0x00
+
+# CHECK: bxh %r0, %r0, 0(%r15)
+0x86 0x00 0xf0 0x00
+
+# CHECK: bxh %r0, %r0, 4095(%r1)
+0x86 0x00 0x1f 0xff
+
+# CHECK: bxh %r0, %r0, 4095(%r15)
+0x86 0x00 0xff 0xff
+
+# CHECK: bxhg %r0, %r0, 0
+0xeb 0x00 0x00 0x00 0x00 0x44
+
+# CHECK: bxhg %r0, %r15, 0
+0xeb 0x0f 0x00 0x00 0x00 0x44
+
+# CHECK: bxhg %r14, %r15, 0
+0xeb 0xef 0x00 0x00 0x00 0x44
+
+# CHECK: bxhg %r15, %r15, 0
+0xeb 0xff 0x00 0x00 0x00 0x44
+
+# CHECK: bxhg %r0, %r0, -524288
+0xeb 0x00 0x00 0x00 0x80 0x44
+
+# CHECK: bxhg %r0, %r0, -1
+0xeb 0x00 0x0f 0xff 0xff 0x44
+
+# CHECK: bxhg %r0, %r0, 0
+0xeb 0x00 0x00 0x00 0x00 0x44
+
+# CHECK: bxhg %r0, %r0, 1
+0xeb 0x00 0x00 0x01 0x00 0x44
+
+# CHECK: bxhg %r0, %r0, 524287
+0xeb 0x00 0x0f 0xff 0x7f 0x44
+
+# CHECK: bxhg %r0, %r0, 0(%r1)
+0xeb 0x00 0x10 0x00 0x00 0x44
+
+# CHECK: bxhg %r0, %r0, 0(%r15)
+0xeb 0x00 0xf0 0x00 0x00 0x44
+
+# CHECK: bxhg %r0, %r0, 524287(%r1)
+0xeb 0x00 0x1f 0xff 0x7f 0x44
+
+# CHECK: bxhg %r0, %r0, 524287(%r15)
+0xeb 0x00 0xff 0xff 0x7f 0x44
+
+# CHECK: bxle %r0, %r0, 0
+0x87 0x00 0x00 0x00
+
+# CHECK: bxle %r0, %r15, 0
+0x87 0x0f 0x00 0x00
+
+# CHECK: bxle %r14, %r15, 0
+0x87 0xef 0x00 0x00
+
+# CHECK: bxle %r15, %r15, 0
+0x87 0xff 0x00 0x00
+
+# CHECK: bxle %r0, %r0, 4095
+0x87 0x00 0x0f 0xff
+
+# CHECK: bxle %r0, %r0, 1
+0x87 0x00 0x00 0x01
+
+# CHECK: bxle %r0, %r0, 0(%r1)
+0x87 0x00 0x10 0x00
+
+# CHECK: bxle %r0, %r0, 0(%r15)
+0x87 0x00 0xf0 0x00
+
+# CHECK: bxle %r0, %r0, 4095(%r1)
+0x87 0x00 0x1f 0xff
+
+# CHECK: bxle %r0, %r0, 4095(%r15)
+0x87 0x00 0xff 0xff
+
+# CHECK: bxleg %r0, %r0, 0
+0xeb 0x00 0x00 0x00 0x00 0x45
+
+# CHECK: bxleg %r0, %r15, 0
+0xeb 0x0f 0x00 0x00 0x00 0x45
+
+# CHECK: bxleg %r14, %r15, 0
+0xeb 0xef 0x00 0x00 0x00 0x45
+
+# CHECK: bxleg   %r15, %r15, 0
+0xeb 0xff 0x00 0x00 0x00 0x45
+
+# CHECK: bxleg %r0, %r0, -524288
+0xeb 0x00 0x00 0x00 0x80 0x45
+
+# CHECK: bxleg %r0, %r0, -1
+0xeb 0x00 0x0f 0xff 0xff 0x45
+
+# CHECK: bxleg %r0, %r0, 0
+0xeb 0x00 0x00 0x00 0x00 0x45
+
+# CHECK: bxleg %r0, %r0, 1
+0xeb 0x00 0x00 0x01 0x00 0x45
+
+# CHECK: bxleg %r0, %r0, 524287
+0xeb 0x00 0x0f 0xff 0x7f 0x45
+
+# CHECK: bxleg %r0, %r0, 0(%r1)
+0xeb 0x00 0x10 0x00 0x00 0x45
+
+# CHECK: bxleg %r0, %r0, 0(%r15)
+0xeb 0x00 0xf0 0x00 0x00 0x45
+
+# CHECK: bxleg %r0, %r0, 524287(%r1)
+0xeb 0x00 0x1f 0xff 0x7f 0x45
+
+# CHECK: bxleg %r0, %r0, 524287(%r15)
+0xeb 0x00 0xff 0xff 0x7f 0x45
+
 # CHECK: cdbr %f0, %f0
 0xb3 0x19 0x00 0x00
 
index b2c37e172a8ec9efa2f144009ef7bbf8dcb99a91..f2771d2d6909c2311d09cbfd3abe920d8e8f478d 100644 (file)
        aih     %r0, (-1 << 31) - 1
        aih     %r0, (1 << 31)
 
+#CHECK: error: offset out of range
+#CHECK: brcth   %r0, -0x1000000002
+#CHECK: error: offset out of range
+#CHECK: brcth   %r0, -1
+#CHECK: error: offset out of range
+#CHECK: brcth   %r0, 1
+#CHECK: error: offset out of range
+#CHECK: brcth   %r0, 0x100000000
+
+        brcth   %r0, -0x1000000002
+        brcth   %r0, -1
+        brcth   %r0, 1
+        brcth   %r0, 0x100000000
+
 #CHECK: error: invalid operand
 #CHECK: cdfbra %f0, 0, %r0, -1
 #CHECK: error: invalid operand
index 5a2e63a5e85ebcfec340021b0a3ee9792e28168b..b2e31bd1a13a1969b0d30abea2bee103f3e20f3e 100644 (file)
        brcl    -1, bar
        brcl    16, bar
 
+#CHECK: error: invalid operand
+#CHECK: bct    %r0, -1
+#CHECK: error: invalid operand
+#CHECK: bct    %r0, 4096
+
+       bct     %r0, -1
+       bct     %r0, 4096
+
+#CHECK: error: invalid operand
+#CHECK: bctg   %r0, -524289
+#CHECK: error: invalid operand
+#CHECK: bctg   %r0, 524288
+
+       bctg    %r0, -524289
+       bctg    %r0, 524288
+
 #CHECK: error: offset out of range
 #CHECK: brct   %r0, -0x100002
 #CHECK: error: offset out of range
        brctg   %r0, 1
        brctg   %r0, 0x10000
 
+#CHECK: error: instruction requires: high-word
+#CHECK: brcth  %r0, 0
+
+       brcth   %r0, 0
+
+#CHECK: error: invalid operand
+#CHECK: bxh    %r0, %r0, 4096
+#CHECK: error: invalid use of indexed addressing
+#CHECK: bxh    %r0, %r0, 0(%r1,%r2)
+
+       bxh     %r0, %r0, 4096
+       bxh     %r0, %r0, 0(%r1,%r2)
+
+#CHECK: error: invalid operand
+#CHECK: bxhg   %r0, %r0, -524289
+#CHECK: error: invalid operand
+#CHECK: bxhg   %r0, %r0, 524288
+#CHECK: error: invalid use of indexed addressing
+#CHECK: bxhg   %r0, %r0, 0(%r1,%r2)
+
+       bxhg    %r0, %r0, -524289
+       bxhg    %r0, %r0, 524288
+       bxhg    %r0, %r0, 0(%r1,%r2)
+
 #CHECK: error: offset out of range
 #CHECK: brxh   %r0, %r2, -0x100002
 #CHECK: error: offset out of range
        brxh    %r0, %r2, 1
        brxh    %r0, %r2, 0x10000
 
+#CHECK: error: offset out of range
+#CHECK: brxhg  %r0, %r2, -0x100002
+#CHECK: error: offset out of range
+#CHECK: brxhg  %r0, %r2, -1
+#CHECK: error: offset out of range
+#CHECK: brxhg  %r0, %r2, 1
+#CHECK: error: offset out of range
+#CHECK: brxhg  %r0, %r2, 0x10000
+
+       brxhg   %r0, %r2, -0x100002
+       brxhg   %r0, %r2, -1
+       brxhg   %r0, %r2, 1
+       brxhg   %r0, %r2, 0x10000
+
+#CHECK: error: invalid operand
+#CHECK: bxle   %r0, %r0, 4096
+#CHECK: error: invalid use of indexed addressing
+#CHECK: bxle   %r0, %r0, 0(%r1,%r2)
+
+       bxle    %r0, %r0, 4096
+       bxle    %r0, %r0, 0(%r1,%r2)
+
+#CHECK: error: invalid operand
+#CHECK: bxhg   %r0, %r0, -524289
+#CHECK: error: invalid operand
+#CHECK: bxhg   %r0, %r0, 524288
+#CHECK: error: invalid use of indexed addressing
+#CHECK: bxhg   %r0, %r0, 0(%r1,%r2)
+
+       bxhg    %r0, %r0, -524289
+       bxhg    %r0, %r0, 524288
+       bxhg    %r0, %r0, 0(%r1,%r2)
+
 #CHECK: error: offset out of range
 #CHECK: brxle  %r0, %r2, -0x100002
 #CHECK: error: offset out of range
        brxle   %r0, %r2, 1
        brxle   %r0, %r2, 0x10000
 
+#CHECK: error: offset out of range
+#CHECK: brxlg  %r0, %r2, -0x100002
+#CHECK: error: offset out of range
+#CHECK: brxlg  %r0, %r2, -1
+#CHECK: error: offset out of range
+#CHECK: brxlg  %r0, %r2, 1
+#CHECK: error: offset out of range
+#CHECK: brxlg  %r0, %r2, 0x10000
+
+       brxlg   %r0, %r2, -0x100002
+       brxlg   %r0, %r2, -1
+       brxlg   %r0, %r2, 1
+       brxlg   %r0, %r2, 0x10000
+
 #CHECK: error: invalid operand
 #CHECK: c      %r0, -1
 #CHECK: error: invalid operand
index 5ac80156ecfccc763846f4208e3bfedec3e9cf1d..318ac2b5b2a4226f0676ccd03c9cd1029cc3bab6 100644 (file)
        cdgbra  %f4, 5, %r6, 7
        cdgbra  %f15, 0, %r0, 0
 
+#CHECK: brcth  %r0, .[[LAB:L.*]]-4294967296 # encoding: [0xcc,0x06,A,A,A,A]
+#CHECK:  fixup A - offset: 2, value: (.[[LAB]]-4294967296)+2, kind: FK_390_PC32DBL
+       brcth   %r0, -0x100000000
+#CHECK: brcth  %r0, .[[LAB:L.*]]-2     # encoding: [0xcc,0x06,A,A,A,A]
+#CHECK:  fixup A - offset: 2, value: (.[[LAB]]-2)+2, kind: FK_390_PC32DBL
+       brcth   %r0, -2
+#CHECK: brcth  %r0, .[[LAB:L.*]]       # encoding: [0xcc,0x06,A,A,A,A]
+#CHECK:  fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC32DBL
+       brcth   %r0, 0
+#CHECK: brcth  %r0, .[[LAB:L.*]]+4294967294 # encoding: [0xcc,0x06,A,A,A,A]
+#CHECK:  fixup A - offset: 2, value: (.[[LAB]]+4294967294)+2, kind: FK_390_PC32DBL
+       brcth   %r0, 0xfffffffe
+
+#CHECK: brcth  %r0, foo                # encoding: [0xcc,0x06,A,A,A,A]
+# fixup A - offset: 2, value: foo+2, kind: FK_390_PC32DBL
+#CHECK: brcth  %r15, foo               # encoding: [0xcc,0xf6,A,A,A,A]
+# fixup A - offset: 2, value: foo+2, kind: FK_390_PC32DBL
+
+       brcth   %r0,foo
+       brcth   %r15,foo
+
+#CHECK: brcth  %r3, bar+100            # encoding: [0xcc,0x36,A,A,A,A]
+# fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC32DBL
+#CHECK: brcth  %r4, bar+100            # encoding: [0xcc,0x46,A,A,A,A]
+# fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC32DBL
+
+       brcth   %r3,bar+100
+       brcth   %r4,bar+100
+
+#CHECK: brcth  %r7, frob@PLT           # encoding: [0xcc,0x76,A,A,A,A]
+# fixup A - offset: 2, value: frob@PLT+2, kind: FK_390_PC32DBL
+#CHECK: brcth  %r8, frob@PLT           # encoding: [0xcc,0x86,A,A,A,A]
+# fixup A - offset: 2, value: frob@PLT+2, kind: FK_390_PC32DBL
+
+       brcth   %r7,frob@PLT
+       brcth   %r8,frob@PLT
+
 #CHECK: cdlfbr %f0, 0, %r0, 0          # encoding: [0xb3,0x91,0x00,0x00]
 #CHECK: cdlfbr %f0, 0, %r0, 15         # encoding: [0xb3,0x91,0x0f,0x00]
 #CHECK: cdlfbr %f0, 0, %r15, 0         # encoding: [0xb3,0x91,0x00,0x0f]
index 39274b44bec62a4e172548276aa2dc0d1cabedf6..5e8a93c012a5149ff5f49b9e8a8e9b93ae41d709 100644 (file)
 #CHECK:  fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC32DBL
        jg      bar@PLT
 
+#CHECK: bct    %r0, 0                  # encoding: [0x46,0x00,0x00,0x00]
+#CHECK: bct    %r0, 4095               # encoding: [0x46,0x00,0x0f,0xff]
+#CHECK: bct    %r0, 0(%r1)             # encoding: [0x46,0x00,0x10,0x00]
+#CHECK: bct    %r0, 0(%r15)            # encoding: [0x46,0x00,0xf0,0x00]
+#CHECK: bct    %r0, 4095(%r1,%r15)     # encoding: [0x46,0x01,0xff,0xff]
+#CHECK: bct    %r0, 4095(%r15,%r1)     # encoding: [0x46,0x0f,0x1f,0xff]
+#CHECK: bct    %r15, 0                 # encoding: [0x46,0xf0,0x00,0x00]
+
+       bct     %r0, 0
+       bct     %r0, 4095
+       bct     %r0, 0(%r1)
+       bct     %r0, 0(%r15)
+       bct     %r0, 4095(%r1,%r15)
+       bct     %r0, 4095(%r15,%r1)
+       bct     %r15, 0
+
+#CHECK: bctr   %r0, %r9                # encoding: [0x06,0x09]
+#CHECK: bctr   %r0, %r15               # encoding: [0x06,0x0f]
+#CHECK: bctr   %r15, %r0               # encoding: [0x06,0xf0]
+#CHECK: bctr   %r15, %r9               # encoding: [0x06,0xf9]
+
+       bctr    %r0,%r9
+       bctr    %r0,%r15
+       bctr    %r15,%r0
+       bctr    %r15,%r9
+
+#CHECK: bctg   %r0, -524288            # encoding: [0xe3,0x00,0x00,0x00,0x80,0x46]
+#CHECK: bctg   %r0, -1                 # encoding: [0xe3,0x00,0x0f,0xff,0xff,0x46]
+#CHECK: bctg   %r0, 0                  # encoding: [0xe3,0x00,0x00,0x00,0x00,0x46]
+#CHECK: bctg   %r0, 1                  # encoding: [0xe3,0x00,0x00,0x01,0x00,0x46]
+#CHECK: bctg   %r0, 524287             # encoding: [0xe3,0x00,0x0f,0xff,0x7f,0x46]
+#CHECK: bctg   %r0, 0(%r1)             # encoding: [0xe3,0x00,0x10,0x00,0x00,0x46]
+#CHECK: bctg   %r0, 0(%r15)            # encoding: [0xe3,0x00,0xf0,0x00,0x00,0x46]
+#CHECK: bctg   %r0, 524287(%r1,%r15)   # encoding: [0xe3,0x01,0xff,0xff,0x7f,0x46]
+#CHECK: bctg   %r0, 524287(%r15,%r1)   # encoding: [0xe3,0x0f,0x1f,0xff,0x7f,0x46]
+#CHECK: bctg   %r15, 0                 # encoding: [0xe3,0xf0,0x00,0x00,0x00,0x46]
+
+       bctg    %r0, -524288
+       bctg    %r0, -1
+       bctg    %r0, 0
+       bctg    %r0, 1
+       bctg    %r0, 524287
+       bctg    %r0, 0(%r1)
+       bctg    %r0, 0(%r15)
+       bctg    %r0, 524287(%r1,%r15)
+       bctg    %r0, 524287(%r15,%r1)
+       bctg    %r15, 0
+
+#CHECK: bctgr  %r0, %r9                # encoding: [0xb9,0x46,0x00,0x09]
+#CHECK: bctgr  %r0, %r15               # encoding: [0xb9,0x46,0x00,0x0f]
+#CHECK: bctgr  %r15, %r0               # encoding: [0xb9,0x46,0x00,0xf0]
+#CHECK: bctgr  %r15, %r9               # encoding: [0xb9,0x46,0x00,0xf9]
+
+       bctgr   %r0,%r9
+       bctgr   %r0,%r15
+       bctgr   %r15,%r0
+       bctgr   %r15,%r9
+
 #CHECK: brct   %r0, .[[LAB:L.*]]-65536 # encoding: [0xa7,0x06,A,A]
 #CHECK:  fixup A - offset: 2, value: (.[[LAB]]-65536)+2, kind: FK_390_PC16DBL
        brct    %r0, -0x10000
 #CHECK:  fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
        brctg   %r15, 0
 
+#CHECK: bxh    %r0, %r0, 0             # encoding: [0x86,0x00,0x00,0x00]
+#CHECK: bxh    %r0, %r15, 0            # encoding: [0x86,0x0f,0x00,0x00]
+#CHECK: bxh    %r14, %r15, 0           # encoding: [0x86,0xef,0x00,0x00]
+#CHECK: bxh    %r15, %r15, 0           # encoding: [0x86,0xff,0x00,0x00]
+#CHECK: bxh    %r0, %r0, 4095          # encoding: [0x86,0x00,0x0f,0xff]
+#CHECK: bxh    %r0, %r0, 1             # encoding: [0x86,0x00,0x00,0x01]
+#CHECK: bxh    %r0, %r0, 0(%r1)        # encoding: [0x86,0x00,0x10,0x00]
+#CHECK: bxh    %r0, %r0, 0(%r15)       # encoding: [0x86,0x00,0xf0,0x00]
+#CHECK: bxh    %r0, %r0, 4095(%r1)     # encoding: [0x86,0x00,0x1f,0xff]
+#CHECK: bxh    %r0, %r0, 4095(%r15)    # encoding: [0x86,0x00,0xff,0xff]
+
+       bxh     %r0,%r0,0
+       bxh     %r0,%r15,0
+       bxh     %r14,%r15,0
+       bxh     %r15,%r15,0
+       bxh     %r0,%r0,4095
+       bxh     %r0,%r0,1
+       bxh     %r0,%r0,0(%r1)
+       bxh     %r0,%r0,0(%r15)
+       bxh     %r0,%r0,4095(%r1)
+       bxh     %r0,%r0,4095(%r15)
+
+#CHECK: bxhg   %r0, %r0, 0             # encoding: [0xeb,0x00,0x00,0x00,0x00,0x44]
+#CHECK: bxhg   %r0, %r15, 0            # encoding: [0xeb,0x0f,0x00,0x00,0x00,0x44]
+#CHECK: bxhg   %r14, %r15, 0           # encoding: [0xeb,0xef,0x00,0x00,0x00,0x44]
+#CHECK: bxhg   %r15, %r15, 0           # encoding: [0xeb,0xff,0x00,0x00,0x00,0x44]
+#CHECK: bxhg   %r0, %r0, -524288       # encoding: [0xeb,0x00,0x00,0x00,0x80,0x44]
+#CHECK: bxhg   %r0, %r0, -1            # encoding: [0xeb,0x00,0x0f,0xff,0xff,0x44]
+#CHECK: bxhg   %r0, %r0, 0             # encoding: [0xeb,0x00,0x00,0x00,0x00,0x44]
+#CHECK: bxhg   %r0, %r0, 1             # encoding: [0xeb,0x00,0x00,0x01,0x00,0x44]
+#CHECK: bxhg   %r0, %r0, 524287        # encoding: [0xeb,0x00,0x0f,0xff,0x7f,0x44]
+#CHECK: bxhg   %r0, %r0, 0(%r1)        # encoding: [0xeb,0x00,0x10,0x00,0x00,0x44]
+#CHECK: bxhg   %r0, %r0, 0(%r15)       # encoding: [0xeb,0x00,0xf0,0x00,0x00,0x44]
+#CHECK: bxhg   %r0, %r0, 524287(%r1)   # encoding: [0xeb,0x00,0x1f,0xff,0x7f,0x44]
+#CHECK: bxhg   %r0, %r0, 524287(%r15)  # encoding: [0xeb,0x00,0xff,0xff,0x7f,0x44]
+
+       bxhg    %r0,%r0,0
+       bxhg    %r0,%r15,0
+       bxhg    %r14,%r15,0
+       bxhg    %r15,%r15,0
+       bxhg    %r0,%r0,-524288
+       bxhg    %r0,%r0,-1
+       bxhg    %r0,%r0,0
+       bxhg    %r0,%r0,1
+       bxhg    %r0,%r0,524287
+       bxhg    %r0,%r0,0(%r1)
+       bxhg    %r0,%r0,0(%r15)
+       bxhg    %r0,%r0,524287(%r1)
+       bxhg    %r0,%r0,524287(%r15)
+
 #CHECK: brxh   %r0, %r2, .[[LAB:L.*]]-65536    # encoding: [0x84,0x02,A,A]
 #CHECK:  fixup A - offset: 2, value: (.[[LAB]]-65536)+2, kind: FK_390_PC16DBL
        brxh    %r0,%r2, -0x10000
        brxh    %r14,%r2,bar@PLT
        brxh    %r15,%r2,bar@PLT
 
+#CHECK: brxhg  %r0, %r2, .[[LAB:L.*]]-65536    # encoding: [0xec,0x02,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: (.[[LAB]]-65536)+2, kind: FK_390_PC16DBL
+       brxhg   %r0,%r2, -0x10000
+#CHECK: brxhg  %r0, %r2, .[[LAB:L.*]]-2        # encoding: [0xec,0x02,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: (.[[LAB]]-2)+2, kind: FK_390_PC16DBL
+       brxhg   %r0, %r2, -2
+#CHECK: brxhg  %r0, %r2, .[[LAB:L.*]]          # encoding: [0xec,0x02,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
+       brxhg   %r0,%r2, 0
+#CHECK: brxhg  %r0, %r2, .[[LAB:L.*]]+65534    # encoding: [0xec,0x02,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: (.[[LAB]]+65534)+2, kind: FK_390_PC16DBL
+       brxhg   %r0,%r2, 0xfffe
+
+#CHECK: brxhg  %r0, %r2, foo                   # encoding: [0xec,0x02,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: brxhg  %r14, %r2, foo                  # encoding: [0xec,0xe2,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: brxhg  %r15, %r2, foo                  # encoding: [0xec,0xf2,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+       brxhg   %r0,%r2,foo
+       brxhg   %r14,%r2,foo
+       brxhg   %r15,%r2,foo
+
+#CHECK: brxhg  %r0, %r2, bar+100               # encoding: [0xec,0x02,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+#CHECK: brxhg  %r14, %r2, bar+100              # encoding: [0xec,0xe2,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+#CHECK: brxhg  %r15, %r2, bar+100              # encoding: [0xec,0xf2,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+       brxhg   %r0,%r2,bar+100
+       brxhg   %r14,%r2,bar+100
+       brxhg   %r15,%r2,bar+100
+
+#CHECK: brxhg  %r0, %r2, bar@PLT               # encoding: [0xec,0x02,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+#CHECK: brxhg  %r14, %r2, bar@PLT              # encoding: [0xec,0xe2,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+#CHECK: brxhg  %r15, %r2, bar@PLT              # encoding: [0xec,0xf2,A,A,0x00,0x44]
+#CHECK:  fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+       brxhg   %r0,%r2,bar@PLT
+       brxhg   %r14,%r2,bar@PLT
+       brxhg   %r15,%r2,bar@PLT
+
+#CHECK: bxle   %r0, %r0, 0             # encoding: [0x87,0x00,0x00,0x00]
+#CHECK: bxle   %r0, %r15, 0            # encoding: [0x87,0x0f,0x00,0x00]
+#CHECK: bxle   %r14, %r15, 0           # encoding: [0x87,0xef,0x00,0x00]
+#CHECK: bxle   %r15, %r15, 0           # encoding: [0x87,0xff,0x00,0x00]
+#CHECK: bxle   %r0, %r0, 4095          # encoding: [0x87,0x00,0x0f,0xff]
+#CHECK: bxle   %r0, %r0, 1             # encoding: [0x87,0x00,0x00,0x01]
+#CHECK: bxle   %r0, %r0, 0(%r1)        # encoding: [0x87,0x00,0x10,0x00]
+#CHECK: bxle   %r0, %r0, 0(%r15)       # encoding: [0x87,0x00,0xf0,0x00]
+#CHECK: bxle   %r0, %r0, 4095(%r1)     # encoding: [0x87,0x00,0x1f,0xff]
+#CHECK: bxle   %r0, %r0, 4095(%r15)    # encoding: [0x87,0x00,0xff,0xff]
+
+       bxle    %r0,%r0,0
+       bxle    %r0,%r15,0
+       bxle    %r14,%r15,0
+       bxle    %r15,%r15,0
+       bxle    %r0,%r0,4095
+       bxle    %r0,%r0,1
+       bxle    %r0,%r0,0(%r1)
+       bxle    %r0,%r0,0(%r15)
+       bxle    %r0,%r0,4095(%r1)
+       bxle    %r0,%r0,4095(%r15)
+
+#CHECK: bxleg  %r0, %r0, 0             # encoding: [0xeb,0x00,0x00,0x00,0x00,0x45]
+#CHECK: bxleg  %r0, %r15, 0            # encoding: [0xeb,0x0f,0x00,0x00,0x00,0x45]
+#CHECK: bxleg  %r14, %r15, 0           # encoding: [0xeb,0xef,0x00,0x00,0x00,0x45]
+#CHECK: bxleg  %r15, %r15, 0           # encoding: [0xeb,0xff,0x00,0x00,0x00,0x45]
+#CHECK: bxleg  %r0, %r0, -524288       # encoding: [0xeb,0x00,0x00,0x00,0x80,0x45]
+#CHECK: bxleg  %r0, %r0, -1            # encoding: [0xeb,0x00,0x0f,0xff,0xff,0x45]
+#CHECK: bxleg  %r0, %r0, 0             # encoding: [0xeb,0x00,0x00,0x00,0x00,0x45]
+#CHECK: bxleg  %r0, %r0, 1             # encoding: [0xeb,0x00,0x00,0x01,0x00,0x45]
+#CHECK: bxleg  %r0, %r0, 524287        # encoding: [0xeb,0x00,0x0f,0xff,0x7f,0x45]
+#CHECK: bxleg  %r0, %r0, 0(%r1)        # encoding: [0xeb,0x00,0x10,0x00,0x00,0x45]
+#CHECK: bxleg  %r0, %r0, 0(%r15)       # encoding: [0xeb,0x00,0xf0,0x00,0x00,0x45]
+#CHECK: bxleg  %r0, %r0, 524287(%r1)   # encoding: [0xeb,0x00,0x1f,0xff,0x7f,0x45]
+#CHECK: bxleg  %r0, %r0, 524287(%r15)  # encoding: [0xeb,0x00,0xff,0xff,0x7f,0x45]
+
+       bxleg   %r0,%r0,0
+       bxleg   %r0,%r15,0
+       bxleg   %r14,%r15,0
+       bxleg   %r15,%r15,0
+       bxleg   %r0,%r0,-524288
+       bxleg   %r0,%r0,-1
+       bxleg   %r0,%r0,0
+       bxleg   %r0,%r0,1
+       bxleg   %r0,%r0,524287
+       bxleg   %r0,%r0,0(%r1)
+       bxleg   %r0,%r0,0(%r15)
+       bxleg   %r0,%r0,524287(%r1)
+       bxleg   %r0,%r0,524287(%r15)
+
 #CHECK: brxle  %r0, %r2, .[[LAB:L.*]]-65536    # encoding: [0x85,0x02,A,A]
 #CHECK:  fixup A - offset: 2, value: (.[[LAB]]-65536)+2, kind: FK_390_PC16DBL
        brxle   %r0,%r2, -0x10000
        brxle   %r14,%r2,bar@PLT
        brxle   %r15,%r2,bar@PLT
 
+#CHECK: brxlg  %r0, %r2, .[[LAB:L.*]]-65536    # encoding: [0xec,0x02,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: (.[[LAB]]-65536)+2, kind: FK_390_PC16DBL
+       brxlg   %r0,%r2, -0x10000
+#CHECK: brxlg  %r0, %r2, .[[LAB:L.*]]-2        # encoding: [0xec,0x02,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: (.[[LAB]]-2)+2, kind: FK_390_PC16DBL
+       brxlg   %r0, %r2, -2
+#CHECK: brxlg  %r0, %r2, .[[LAB:L.*]]          # encoding: [0xec,0x02,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
+       brxlg   %r0,%r2, 0
+#CHECK: brxlg  %r0, %r2, .[[LAB:L.*]]+65534    # encoding: [0xec,0x02,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: (.[[LAB]]+65534)+2, kind: FK_390_PC16DBL
+       brxlg   %r0,%r2, 0xfffe
+
+#CHECK: brxlg  %r0, %r2, foo                   # encoding: [0xec,0x02,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: brxlg  %r14, %r2, foo                  # encoding: [0xec,0xe2,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: brxlg  %r15, %r2, foo                  # encoding: [0xec,0xf2,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+       brxlg   %r0,%r2,foo
+       brxlg   %r14,%r2,foo
+       brxlg   %r15,%r2,foo
+
+#CHECK: brxlg  %r0, %r2, bar+100               # encoding: [0xec,0x02,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+#CHECK: brxlg  %r14, %r2, bar+100              # encoding: [0xec,0xe2,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+#CHECK: brxlg  %r15, %r2, bar+100              # encoding: [0xec,0xf2,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+       brxlg   %r0,%r2,bar+100
+       brxlg   %r14,%r2,bar+100
+       brxlg   %r15,%r2,bar+100
+
+#CHECK: brxlg  %r0, %r2, bar@PLT               # encoding: [0xec,0x02,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+#CHECK: brxlg  %r14, %r2, bar@PLT              # encoding: [0xec,0xe2,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+#CHECK: brxlg  %r15, %r2, bar@PLT              # encoding: [0xec,0xf2,A,A,0x00,0x45]
+#CHECK:  fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+       brxlg   %r0,%r2,bar@PLT
+       brxlg   %r14,%r2,bar@PLT
+       brxlg   %r15,%r2,bar@PLT
+
 #CHECK: c      %r0, 0                  # encoding: [0x59,0x00,0x00,0x00]
 #CHECK: c      %r0, 4095               # encoding: [0x59,0x00,0x0f,0xff]
 #CHECK: c      %r0, 0(%r1)             # encoding: [0x59,0x00,0x10,0x00]