diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp
index d99be9be7c36..acf9a615f20b 100644
--- a/lld/ELF/Arch/ARM.cpp
+++ b/lld/ELF/Arch/ARM.cpp
@@ -97,10 +97,19 @@ ARM::ARM() {
 }
 
 uint32_t ARM::calcEFlags() const {
+  // The ABIFloatType is used by loaders to detect the floating point calling
+  // convention.
+  uint32_t ABIFloatType = 0;
+  if (Config->ARMVFPArgs == ARMVFPArgKind::Base ||
+      Config->ARMVFPArgs == ARMVFPArgKind::Default)
+    ABIFloatType = EF_ARM_ABI_FLOAT_SOFT;
+  else if (Config->ARMVFPArgs == ARMVFPArgKind::VFP)
+    ABIFloatType = EF_ARM_ABI_FLOAT_HARD;
+
   // We don't currently use any features incompatible with EF_ARM_EABI_VER5,
   // but we don't have any firm guarantees of conformance. Linux AArch64
   // kernels (as of 2016) require an EABI version to be set.
-  return EF_ARM_EABI_VER5;
+  return EF_ARM_EABI_VER5 | ABIFloatType;
 }
 
 RelExpr ARM::getRelExpr(RelType Type, const Symbol &S,
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 997fade64777..622324c13e2d 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -58,6 +58,9 @@ enum class SortSectionPolicy { Default, None, Alignment, Name, Priority };
 // For --target2
 enum class Target2Policy { Abs, Rel, GotRel };
 
+// For tracking ARM Float Argument PCS
+enum class ARMVFPArgKind { Default, Base, VFP, ToolChain };
+
 struct SymbolVersion {
   llvm::StringRef Name;
   bool IsExternCpp;
@@ -196,6 +199,7 @@ struct Configuration {
   StripPolicy Strip;
   UnresolvedPolicy UnresolvedSymbols;
   Target2Policy Target2;
+  ARMVFPArgKind ARMVFPArgs = ARMVFPArgKind::Default;
   BuildIdKind BuildId = BuildIdKind::None;
   ELFKind EKind = ELFNoneKind;
   uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL;
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 6da722f6f30e..0eb605a556ae 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -494,6 +494,46 @@ void ObjFile<ELFT>::initializeSections(
   }
 }
 
+// For ARM only, to set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD
+// flag in the ELF Header we need to look at Tag_ABI_VFP_args to find out how
+// the input objects have been compiled.
+static void updateARMVFPArgs(const ARMAttributeParser &Attributes,
+                             const InputFile *F) {
+  if (!Attributes.hasAttribute(ARMBuildAttrs::ABI_VFP_args))
+    // If an ABI tag isn't present then it is implicitly given the value of 0
+    // which maps to ARMBuildAttrs::BaseAAPCS. However many assembler files,
+    // including some in glibc that don't use FP args (and should have value 3)
+    // don't have the attribute so we do not consider an implicit value of 0
+    // as a clash.
+    return;
+
+  unsigned VFPArgs = Attributes.getAttributeValue(ARMBuildAttrs::ABI_VFP_args);
+  ARMVFPArgKind Arg;
+  switch (VFPArgs) {
+  case ARMBuildAttrs::BaseAAPCS:
+    Arg = ARMVFPArgKind::Base;
+    break;
+  case ARMBuildAttrs::HardFPAAPCS:
+    Arg = ARMVFPArgKind::VFP;
+    break;
+  case ARMBuildAttrs::ToolChainFPPCS:
+    // Tool chain specific convention that conforms to neither AAPCS variant.
+    Arg = ARMVFPArgKind::ToolChain;
+    break;
+  case ARMBuildAttrs::CompatibleFPAAPCS:
+    // Object compatible with all conventions.
+    return;
+  default:
+    error(toString(F) + ": unknown Tag_ABI_VFP_args value: " + Twine(VFPArgs));
+    return;
+  }
+  // Follow ld.bfd and error if there is a mix of calling conventions.
+  if (Config->ARMVFPArgs != Arg && Config->ARMVFPArgs != ARMVFPArgKind::Default)
+    error(toString(F) + ": incompatible Tag_ABI_VFP_args");
+  else
+    Config->ARMVFPArgs = Arg;
+}
+
 // The ARM support in lld makes some use of instructions that are not available
 // on all ARM architectures. Namely:
 // - Use of BLX instruction for interworking between ARM and Thumb state.
@@ -573,6 +613,8 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
     ArrayRef<uint8_t> Contents = check(this->getObj().getSectionContents(&Sec));
     Attributes.Parse(Contents, /*isLittle*/ Config->EKind == ELF32LEKind);
     updateSupportedARMFeatures(Attributes);
+    updateARMVFPArgs(Attributes, this);
+
     // FIXME: Retain the first attribute section we see. The eglibc ARM
     // dynamic loaders require the presence of an attribute section for dlopen
     // to work. In a full implementation we would merge all attribute sections.
diff --git a/lld/test/ELF/Inputs/arm-vfp-arg-base.s b/lld/test/ELF/Inputs/arm-vfp-arg-base.s
new file mode 100644
index 000000000000..9625c0a7ceff
--- /dev/null
+++ b/lld/test/ELF/Inputs/arm-vfp-arg-base.s
@@ -0,0 +1,16 @@
+	.arch armv7-a
+	.eabi_attribute 20, 1
+	.eabi_attribute 21, 1
+	.eabi_attribute 23, 3
+	.eabi_attribute 24, 1
+	.eabi_attribute 25, 1
+	.eabi_attribute 26, 2
+	.eabi_attribute 30, 6
+	.eabi_attribute 34, 1
+	.eabi_attribute 18, 4
+        .eabi_attribute 28, 0 // Tag_ABI_VFP_args = 0 (AAPCS, Base variant)
+
+        .syntax unified
+        .global f0
+        .type f0, %function
+f0:     bx lr
diff --git a/lld/test/ELF/Inputs/arm-vfp-arg-compat.s b/lld/test/ELF/Inputs/arm-vfp-arg-compat.s
new file mode 100644
index 000000000000..78f6ef6854b1
--- /dev/null
+++ b/lld/test/ELF/Inputs/arm-vfp-arg-compat.s
@@ -0,0 +1,16 @@
+	.arch armv7-a
+	.eabi_attribute 20, 1
+	.eabi_attribute 21, 1
+	.eabi_attribute 23, 3
+	.eabi_attribute 24, 1
+	.eabi_attribute 25, 1
+	.eabi_attribute 26, 2
+	.eabi_attribute 30, 6
+	.eabi_attribute 34, 1
+	.eabi_attribute 18, 4
+        .eabi_attribute 28, 3 // Tag_ABI_VFP_args = 3 (Compatible with all)
+
+        .syntax unified
+        .global f3
+        .type f3, %function
+f3:     bx lr
diff --git a/lld/test/ELF/Inputs/arm-vfp-arg-toolchain.s b/lld/test/ELF/Inputs/arm-vfp-arg-toolchain.s
new file mode 100644
index 000000000000..bc8eb14e3442
--- /dev/null
+++ b/lld/test/ELF/Inputs/arm-vfp-arg-toolchain.s
@@ -0,0 +1,15 @@
+	.arch armv7-a
+	.eabi_attribute 20, 1
+	.eabi_attribute 21, 1
+	.eabi_attribute 23, 3
+	.eabi_attribute 24, 1
+	.eabi_attribute 25, 1
+	.eabi_attribute 26, 2
+	.eabi_attribute 30, 6
+	.eabi_attribute 34, 1
+	.eabi_attribute 18, 4
+	.eabi_attribute 28, 2 // Tag_ABI_VFP_args = 2 (Toolchain specific)
+        .syntax unified
+        .global f2
+        .type f1, %function
+f2:     bx lr
diff --git a/lld/test/ELF/Inputs/arm-vfp-arg-vfp.s b/lld/test/ELF/Inputs/arm-vfp-arg-vfp.s
new file mode 100644
index 000000000000..e8c8a66a2ced
--- /dev/null
+++ b/lld/test/ELF/Inputs/arm-vfp-arg-vfp.s
@@ -0,0 +1,15 @@
+	.arch armv7-a
+	.eabi_attribute 20, 1
+	.eabi_attribute 21, 1
+	.eabi_attribute 23, 3
+	.eabi_attribute 24, 1
+	.eabi_attribute 25, 1
+	.eabi_attribute 26, 2
+	.eabi_attribute 30, 6
+	.eabi_attribute 34, 1
+	.eabi_attribute 18, 4
+	.eabi_attribute 28, 1 // Tag_ABI_VFP_args = 1 (AAPCS, VFP variant)
+        .syntax unified
+        .global f1
+        .type f1, %function
+f1:     bx lr
diff --git a/lld/test/ELF/arm-eabi-version.s b/lld/test/ELF/arm-eabi-version.s
index a08374c132f0..4b4f8603db6a 100644
--- a/lld/test/ELF/arm-eabi-version.s
+++ b/lld/test/ELF/arm-eabi-version.s
@@ -9,6 +9,7 @@ _start:
  bx lr
 
 // CHECK:  Flags [
+// CHECK-NEXT:    0x200        
 // CHECK-NEXT:    0x1000000
 // CHECK-NEXT:    0x4000000
 // CHECK-NEXT:  ]
diff --git a/lld/test/ELF/arm-tag-vfp-args-errs.s b/lld/test/ELF/arm-tag-vfp-args-errs.s
new file mode 100644
index 000000000000..03e84edc1e91
--- /dev/null
+++ b/lld/test/ELF/arm-tag-vfp-args-errs.s
@@ -0,0 +1,29 @@
+// REQUIRES:arm
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-base.s -o %tbase.o
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-vfp.s -o %tvfp.o
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-toolchain.s -o %ttoolchain.o
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+// RUN: not ld.lld %t.o %tbase.o %tvfp.o 2>&1 | FileCheck %s
+// RUN: not ld.lld %t.o %tbase.o %ttoolchain.o 2>&1 | FileCheck %s
+// RUN: not ld.lld %t.o %tvfp.o %tbase.o 2>&1 | FileCheck %s
+// RUN: not ld.lld %t.o %tvfp.o %ttoolchain.o 2>&1 | FileCheck %s
+// RUN: not ld.lld %t.o %ttoolchain.o %tbase.o 2>&1 | FileCheck %s
+// RUN: not ld.lld %t.o %ttoolchain.o %tvfp.o 2>&1 | FileCheck %s
+
+// CHECK: incompatible Tag_ABI_VFP_args
+	.arch armv7-a
+	.eabi_attribute 20, 1
+	.eabi_attribute 21, 1
+	.eabi_attribute 23, 3
+	.eabi_attribute 24, 1
+	.eabi_attribute 25, 1
+	.eabi_attribute 26, 2
+	.eabi_attribute 30, 6
+	.eabi_attribute 34, 1
+	.eabi_attribute 18, 4
+        .eabi_attribute 28, 3 // Tag_ABI_VFP_args = 3 (Compatible with all)
+
+        .syntax unified
+        .globl _start
+        .type _start, %function
+_start: bx lr
diff --git a/lld/test/ELF/arm-tag-vfp-args-illegal.s b/lld/test/ELF/arm-tag-vfp-args-illegal.s
new file mode 100644
index 000000000000..471a024b3c09
--- /dev/null
+++ b/lld/test/ELF/arm-tag-vfp-args-illegal.s
@@ -0,0 +1,21 @@
+// REQUIRES:arm
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+// RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
+
+// CHECK: arm-tag-vfp-args-illegal.s.tmp.o: unknown Tag_ABI_VFP_args value: 5
+        .arch armv7-a
+        .eabi_attribute 20, 1
+        .eabi_attribute 21, 1
+        .eabi_attribute 23, 3
+        .eabi_attribute 24, 1
+        .eabi_attribute 25, 1
+        .eabi_attribute 26, 2
+        .eabi_attribute 30, 6
+        .eabi_attribute 34, 1
+        .eabi_attribute 18, 4
+        .eabi_attribute 28, 5 // Tag_ABI_VFP_args = 5 (Illegal value)
+
+        .syntax unified
+        .globl _start
+        .type _start, %function
+_start: bx lr
diff --git a/lld/test/ELF/arm-tag-vfp-args.s b/lld/test/ELF/arm-tag-vfp-args.s
new file mode 100644
index 000000000000..b0ff095687f1
--- /dev/null
+++ b/lld/test/ELF/arm-tag-vfp-args.s
@@ -0,0 +1,72 @@
+// REQUIRES:arm
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-base.s -o %tbase.o
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-vfp.s -o %tvfp.o
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-toolchain.s -o %ttoolchain.o
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-vfp-arg-compat.s -o %tcompat.o
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+
+// The default for this file is 0 (Base AAPCS)
+// RUN: ld.lld %t.o -o %tdefault
+// RUN: llvm-readobj -file-headers %tdefault | FileCheck -check-prefix=CHECK-BASE %s
+
+// Expect explicit Base AAPCS.
+// RUN: ld.lld %t.o %tbase.o -o %tbase
+// RUN: llvm-readobj -file-headers %tbase | FileCheck -check-prefix=CHECK-BASE %s
+
+// Expect explicit Base AAPCS when linking Base and Compatible.
+// RUN: ld.lld %t.o %tbase.o %tcompat.o -o %tbasecompat
+// RUN: llvm-readobj -file-headers %tbasecompat | FileCheck -check-prefix=CHECK-BASE %s
+
+// CHECK-BASE:   Flags [ (0x5000200)
+// CHECK-BASE-NEXT:     0x200
+// CHECK-BASE-NEXT:     0x1000000
+// CHECK-BASE-NEXT:     0x4000000
+// CHECK-BASE-NEXT:   ]
+
+// Expect Hard float VFP AAPCS
+// RUN: ld.lld %t.o %tvfp.o -o %tvfp
+// RUN: llvm-readobj -file-headers %tvfp | FileCheck -check-prefix=CHECK-VFP %s
+
+// Expect Hard float VFP AAPCS when linking VFP and Compatible
+// RUN: ld.lld %t.o %tvfp.o %tcompat.o -o %tvfpcompat
+// RUN: llvm-readobj -file-headers %tvfpcompat | FileCheck -check-prefix=CHECK-VFP %s
+
+// CHECK-VFP:   Flags [ (0x5000400)
+// CHECK-VFP-NEXT:     0x400
+// CHECK-VFP-NEXT:     0x1000000
+// CHECK-VFP-NEXT:     0x4000000
+// CHECK-VFP-NEXT:   ]
+
+// Expect Toolchain specifc to not use either Base or VFP AAPCS
+// RUN: ld.lld %t.o %ttoolchain.o -o %ttoolchain
+// RUN: llvm-readobj -file-headers %ttoolchain | FileCheck -check-prefix=CHECK-TOOLCHAIN %s
+
+// Expect Toolchain and Compatible to have same affect as Toolchain.
+// RUN: ld.lld %t.o %ttoolchain.o %tcompat.o -o %ttoolchaincompat
+// RUN: llvm-readobj -file-headers %ttoolchaincompat | FileCheck -check-prefix=CHECK-TOOLCHAIN %s
+
+// CHECK-TOOLCHAIN:   Flags [ (0x5000000)
+// CHECK-TOOLCHAIN-NEXT:     0x1000000
+// CHECK-TOOLCHAIN-NEXT:     0x4000000
+// CHECK-TOOLCHAIN-NEXT:   ]
+
+        .arch armv7-a
+        .eabi_attribute 20, 1
+        .eabi_attribute 21, 1
+        .eabi_attribute 23, 3
+        .eabi_attribute 24, 1
+        .eabi_attribute 25, 1
+        .eabi_attribute 26, 2
+        .eabi_attribute 30, 6
+        .eabi_attribute 34, 1
+        .eabi_attribute 18, 4
+        // We do not specify Tag_ABI_VFP_args (.eabi_attribute 28) in this file.
+        // When omitted the value of the tag defaults to 0, however if there
+        // are other files with explicit Tag_ABI_VFP_args we use that in
+        // preference.
+
+
+        .syntax unified
+        .globl _start
+        .type _start, %function
+_start:  bx lr