diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp
index 00cd4e79de9..8e809f0f153 100644
--- a/lib/Target/ARM/ARMAsmBackend.cpp
+++ b/lib/Target/ARM/ARMAsmBackend.cpp
@@ -146,13 +146,33 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
     // The value doesn't encode the low bit (always zero) and is offset by
     // four. The value is encoded into disjoint bit positions in the destination
     // opcode. x = unchanged, I = immediate value bit, S = sign extension bit
-    // xxxxxSIIIIIIIIII xxxxxIIIIIIIIIII
+    // 
+    //   BL:  xxxxxSIIIIIIIIII xxxxxIIIIIIIIIII
+    // 
     // Note that the halfwords are stored high first, low second; so we need
     // to transpose the fixup value here to map properly.
-    // FIXME: Something isn't quite right with this. Some, but not all, BLX
-    // instructions are getting the encoded value off by one.
+    unsigned isNeg = (int64_t(Value) < 0) ? 1 : 0;
     uint32_t Binary = 0x3fffff & ((Value - 4) >> 1);
-    Binary = ((Binary & 0x7ff) << 16) | (Binary >> 11);
+    Binary  = (Binary & 0x7ff) << 16;    // Low imm11 value.
+    Binary |= (Binary & 0x1ffc00) >> 11; // High imm10 value.
+    Binary |= isNeg << 10;               // Sign bit.
+    return Binary;
+  }
+  case ARM::fixup_arm_thumb_blx: {
+    // The value doesn't encode the low two bits (always zero) and is offset by
+    // four (see fixup_arm_thumb_cp). The value is encoded into disjoint bit
+    // positions in the destination opcode. x = unchanged, I = immediate value
+    // bit, S = sign extension bit, 0 = zero.
+    // 
+    //   BLX: xxxxxSIIIIIIIIII xxxxxIIIIIIIIII0
+    // 
+    // Note that the halfwords are stored high first, low second; so we need
+    // to transpose the fixup value here to map properly.
+    unsigned isNeg = (int64_t(Value) < 0) ? 1 : 0;
+    uint32_t Binary = 0xfffff & ((Value - 2) >> 2);
+    Binary  = (Binary & 0x3ff) << 17;    // Low imm10L value.
+    Binary |= (Binary & 0xffc00) >> 10;  // High imm10H value.
+    Binary |= isNeg << 10;               // Sign bit.
     return Binary;
   }
   case ARM::fixup_arm_thumb_cp:
@@ -291,6 +311,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
   case ARM::fixup_t2_branch:
   case ARM::fixup_t2_pcrel_10:
   case ARM::fixup_arm_thumb_bl:
+  case ARM::fixup_arm_thumb_blx:
     return 4;
   }
 }
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index da806f77c52..3892948d622 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -173,6 +173,8 @@ namespace {
       const { return 0; }
     unsigned getThumbBLTargetOpValue(const MachineInstr &MI, unsigned Op)
       const { return 0; }
+    unsigned getThumbBLXTargetOpValue(const MachineInstr &MI, unsigned Op)
+      const { return 0; }
     unsigned getThumbBRTargetOpValue(const MachineInstr &MI, unsigned Op)
       const { return 0; }
     unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned Op)
diff --git a/lib/Target/ARM/ARMFixupKinds.h b/lib/Target/ARM/ARMFixupKinds.h
index c18d84861e2..997b22ef71d 100644
--- a/lib/Target/ARM/ARMFixupKinds.h
+++ b/lib/Target/ARM/ARMFixupKinds.h
@@ -35,9 +35,12 @@ enum Fixups {
   // instructions.
   fixup_t2_branch,
 
-  // fixup_arm_thumb_bl - Fixup for Thumb BL/BLX instructions.
+  // fixup_arm_thumb_blx - Fixup for Thumb BL instructions.
   fixup_arm_thumb_bl,
 
+  // fixup_arm_thumb_blx - Fixup for Thumb BLX instructions.
+  fixup_arm_thumb_blx,
+
   // fixup_arm_thumb_br - Fixup for Thumb branch instructions.
   fixup_arm_thumb_br,
 
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index 46e25583abc..7322b035c98 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -82,6 +82,10 @@ def t_bltarget : Operand<i32> {
   let EncoderMethod = "getThumbBLTargetOpValue";
 }
 
+def t_blxtarget : Operand<i32> {
+  let EncoderMethod = "getThumbBLXTargetOpValue";
+}
+
 def MemModeThumbAsmOperand : AsmOperandClass {
   let Name = "MemModeThumb";
   let SuperClasses = [];
@@ -395,7 +399,7 @@ let isCall = 1,
 
   // ARMv5T and above, also used for Thumb2
   def tBLXi : TIx2<0b11110, 0b11, 0,
-                   (outs), (ins t_bltarget:$func, variable_ops), IIC_Br,
+                   (outs), (ins t_blxtarget:$func, variable_ops), IIC_Br,
                    "blx\t$func",
                    [(ARMcall tglobaladdr:$func)]>,
               Requires<[IsThumb, HasV5T, IsNotDarwin]> {
@@ -448,7 +452,7 @@ let isCall = 1,
 
   // ARMv5T and above, also used for Thumb2
   def tBLXi_r9 : TIx2<0b11110, 0b11, 0,
-                      (outs), (ins pred:$p, t_bltarget:$func, variable_ops),
+                      (outs), (ins pred:$p, t_blxtarget:$func, variable_ops),
                       IIC_Br, "blx${p}\t$func",
                       [(ARMcall tglobaladdr:$func)]>,
                  Requires<[IsThumb, HasV5T, IsDarwin]> {
diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp
index ebcab8b8d33..8fbeb0e6e0d 100644
--- a/lib/Target/ARM/ARMMCCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp
@@ -53,6 +53,7 @@ public:
       { "fixup_arm_branch",         1,    24,   MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_t2_branch",          0,    32,   MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_arm_thumb_bl",       0,    32,   MCFixupKindInfo::FKF_IsPCRel },
+      { "fixup_arm_thumb_blx",      0,    32,   MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_arm_thumb_br",       0,    16,   MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_arm_thumb_cp",       1,    8,    MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_arm_movt_hi16",      0,    16,   0 },
@@ -87,10 +88,15 @@ public:
                               SmallVectorImpl<MCFixup> &Fixups) const;
 
   /// getThumbBLTargetOpValue - Return encoding info for Thumb immediate
-  /// branch target.
+  /// BL branch target.
   uint32_t getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
                                    SmallVectorImpl<MCFixup> &Fixups) const;
 
+  /// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate
+  /// BLX branch target.
+  uint32_t getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
+                                    SmallVectorImpl<MCFixup> &Fixups) const;
+
   /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target.
   uint32_t getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
                                    SmallVectorImpl<MCFixup> &Fixups) const;
@@ -443,6 +449,14 @@ getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
   return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bl, Fixups);
 }
 
+/// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate
+/// BLX branch target.
+uint32_t ARMMCCodeEmitter::
+getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx,
+                         SmallVectorImpl<MCFixup> &Fixups) const {
+  return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_blx, Fixups);
+}
+
 /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target.
 uint32_t ARMMCCodeEmitter::
 getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
@@ -740,17 +754,7 @@ getAddrModeS1OpValue(const MCInst &MI, unsigned OpIdx,
 uint32_t ARMMCCodeEmitter::
 getAddrModePCOpValue(const MCInst &MI, unsigned OpIdx,
                      SmallVectorImpl<MCFixup> &Fixups) const {
-  const MCOperand &MO = MI.getOperand(OpIdx);
-
-  // If the destination is an immediate, we have nothing to do.
-  if (MO.isImm()) return MO.getImm();
-  assert (MO.isExpr() && "Unexpected branch target type!");
-  const MCExpr *Expr = MO.getExpr();
-  MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_thumb_cp);
-  Fixups.push_back(MCFixup::Create(0, Expr, Kind));
-
-  // All of the information is in the fixup.
-  return 0;
+  return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_cp, Fixups);
 }
 
 /// getAddrMode5OpValue - Return encoding info for 'reg +/- imm10' operand.
diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp
index 6bd1e639692..3393a07a901 100644
--- a/utils/TableGen/EDEmitter.cpp
+++ b/utils/TableGen/EDEmitter.cpp
@@ -590,6 +590,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
   MISC("t_brtarget", "kOperandTypeARMBranchTarget");              // ?
   MISC("bltarget", "kOperandTypeARMBranchTarget");                // ?
   MISC("t_bltarget", "kOperandTypeARMBranchTarget");              // ?
+  MISC("t_blxtarget", "kOperandTypeARMBranchTarget");             // ?
   MISC("so_reg", "kOperandTypeARMSoReg");                         // R, R, I
   MISC("shift_so_reg", "kOperandTypeARMSoReg");                   // R, R, I
   MISC("t2_so_reg", "kOperandTypeThumb2SoReg");                   // R, I