diff --git a/bfd/config.bfd b/bfd/config.bfd
index 92a6cff938b..de1c4cd4fd7 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -249,9 +249,9 @@ case "${targ}" in
     targ_selvecs="aarch64_elf64_be_vec aarch64_elf32_le_vec aarch64_elf32_be_vec arm_elf32_le_vec arm_elf32_be_vec aarch64_pei_le_vec aarch64_pe_le_vec"
     want64=true
     ;;
-  aarch64-*-pe*)
+  aarch64-*-pe* | aarch64-*-mingw*)
     targ_defvec=aarch64_pe_le_vec
-    targ_selvecs="aarch64_pe_le_vec aarch64_pei_le_vec"
+    targ_selvecs="aarch64_pe_le_vec aarch64_pei_le_vec aarch64_elf64_le_vec aarch64_elf64_be_vec aarch64_elf32_le_vec aarch64_elf32_be_vec arm_elf32_le_vec arm_elf32_be_vec pdb_vec"
     want64=true
     targ_underscore=no
     ;;
diff --git a/bfd/peicode.h b/bfd/peicode.h
index f7ba24ae10a..26e95dc1f1b 100644
--- a/bfd/peicode.h
+++ b/bfd/peicode.h
@@ -440,7 +440,7 @@ pe_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd)
 #define SIZEOF_IDATA2		(5 * 4)
 
 /* For PEx64 idata4 & 5 have thumb size of 8 bytes.  */
-#ifdef COFF_WITH_pex64
+#if defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64)
 #define SIZEOF_IDATA4		(2 * 4)
 #define SIZEOF_IDATA5		(2 * 4)
 #else
diff --git a/binutils/configure b/binutils/configure
index 5a3e5017b46..a88b66dae8f 100755
--- a/binutils/configure
+++ b/binutils/configure
@@ -14578,6 +14578,16 @@ do
 	esac
 
 	case $targ in
+	aarch64-*-mingw*)
+	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+	  if test -z "$DLLTOOL_DEFAULT"; then
+	    DLLTOOL_DEFAULT="-DDLLTOOL_DEFAULT_AARCH64"
+	  fi
+	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_AARCH64"
+	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+	  BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)'
+	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+	  ;;
 	arm-wince-pe* | arm-*-wince | arm*-*-cegcc* | arm*-*-mingw32ce*)
   	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
 	  if test -z "$DLLTOOL_DEFAULT"; then
diff --git a/binutils/configure.ac b/binutils/configure.ac
index 6243a2b0c2d..b51aeb9f38f 100644
--- a/binutils/configure.ac
+++ b/binutils/configure.ac
@@ -355,6 +355,16 @@ do
 	esac
 
 	case $targ in
+	aarch64-*-mingw*)
+	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
+	  if test -z "$DLLTOOL_DEFAULT"; then
+	    DLLTOOL_DEFAULT="-DDLLTOOL_DEFAULT_AARCH64"
+	  fi
+	  DLLTOOL_DEFS="$DLLTOOL_DEFS -DDLLTOOL_AARCH64"
+	  BUILD_WINDRES='$(WINDRES_PROG)$(EXEEXT)'
+	  BUILD_WINDMC='$(WINDMC_PROG)$(EXEEXT)'
+	  BUILD_DLLWRAP='$(DLLWRAP_PROG)$(EXEEXT)'
+	  ;;
 	arm-wince-pe* | arm-*-wince | arm*-*-cegcc* | arm*-*-mingw32ce*)
   	  BUILD_DLLTOOL='$(DLLTOOL_PROG)$(EXEEXT)'
 	  if test -z "$DLLTOOL_DEFAULT"; then
diff --git a/binutils/dlltool.c b/binutils/dlltool.c
index a3c5e0f778e..c9c53919dbf 100644
--- a/binutils/dlltool.c
+++ b/binutils/dlltool.c
@@ -442,6 +442,11 @@ static const char *mname = "arm";
 static const char *mname = "arm-wince";
 #endif
 
+#ifdef DLLTOOL_DEFAULT_AARCH64
+/* arm64 rather than aarch64 to match llvm-dlltool */
+static const char *mname = "arm64";
+#endif
+
 #ifdef DLLTOOL_DEFAULT_I386
 static const char *mname = "i386";
 #endif
@@ -560,6 +565,14 @@ static const unsigned char mcore_le_jtab[] =
   0x00, 0x00, 0x00, 0x00 /* <address>      */
 };
 
+static const unsigned char aarch64_jtab[] =
+{
+  0x10, 0x00, 0x00, 0x90, /* adrp x16, 0        */
+  0x10, 0x02, 0x00, 0x91, /* add x16, x16, #0x0 */
+  0x10, 0x02, 0x40, 0xf9, /* ldr x16, [x16]     */
+  0x00, 0x02, 0x1f, 0xd6  /* br x16             */
+};
+
 static const char i386_trampoline[] =
   "\tpushl %%ecx\n"
   "\tpushl %%edx\n"
@@ -717,6 +730,15 @@ mtable[] =
     i386_x64_dljtab, sizeof (i386_x64_dljtab), 2, 9, 14, true, i386_x64_trampoline
   }
   ,
+  {
+#define MAARCH64 10
+    "arm64", ".byte", ".short", ".long", ".asciz", "//",
+    "bl ", ".global", ".space", ".balign\t2", ".balign\t4", "",
+    "pe-aarch64-little", bfd_arch_aarch64,
+    aarch64_jtab, sizeof (aarch64_jtab), 0,
+    0, 0, 0, 0, 0, false, 0
+  }
+  ,
   { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
 };
 
@@ -864,6 +886,7 @@ rvaafter (int mach)
     case MMCORE_ELF:
     case MMCORE_ELF_LE:
     case MARM_WINCE:
+    case MAARCH64:
       break;
     default:
       /* xgettext:c-format */
@@ -888,6 +911,7 @@ rvabefore (int mach)
     case MMCORE_ELF:
     case MMCORE_ELF_LE:
     case MARM_WINCE:
+    case MAARCH64:
       return ".rva\t";
     default:
       /* xgettext:c-format */
@@ -910,6 +934,7 @@ asm_prefix (int mach, const char *name)
     case MMCORE_ELF:
     case MMCORE_ELF_LE:
     case MARM_WINCE:
+    case MAARCH64:
       break;
     case M386:
     case MX86:
@@ -2474,6 +2499,8 @@ make_one_lib_file (export_type *exp, int i, int delay)
 	case TEXT:
 	  if (! exp->data)
 	    {
+	      unsigned int rpp_len;
+
 	      si->size = HOW_JTAB_SIZE;
 	      si->data = xmalloc (HOW_JTAB_SIZE);
 	      memcpy (si->data, HOW_JTAB, HOW_JTAB_SIZE);
@@ -2481,7 +2508,12 @@ make_one_lib_file (export_type *exp, int i, int delay)
 	      /* Add the reloc into idata$5.  */
 	      rel = xmalloc (sizeof (arelent));
 
-	      rpp = xmalloc (sizeof (arelent *) * (delay ? 4 : 2));
+	      rpp_len = delay ? 4 : 2;
+
+	      if (machine == MAARCH64)
+		rpp_len++;
+
+	      rpp = xmalloc (sizeof (arelent *) * rpp_len);
 	      rpp[0] = rel;
 	      rpp[1] = 0;
 
@@ -2507,6 +2539,22 @@ make_one_lib_file (export_type *exp, int i, int delay)
 						      BFD_RELOC_32_PCREL);
 		  rel->sym_ptr_ptr = iname_pp;
 		}
+	      else if (machine == MAARCH64)
+		{
+		  arelent *rel_add;
+
+		  rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL);
+		  rel->sym_ptr_ptr = secdata[IDATA5].sympp;
+
+		  rel_add = xmalloc (sizeof (arelent));
+		  rel_add->address = 4;
+		  rel_add->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_AARCH64_ADD_LO12);
+		  rel_add->sym_ptr_ptr = secdata[IDATA5].sympp;
+		  rel_add->addend = 0;
+
+		  rpp[rpp_len - 2] = rel_add;
+		  rpp[rpp_len - 1] = 0;
+		}
 	      else
 		{
 		  rel->howto = bfd_reloc_type_lookup (abfd, BFD_RELOC_32);
@@ -2527,7 +2575,7 @@ make_one_lib_file (export_type *exp, int i, int delay)
 	        }
 
 	      sec->orelocation = rpp;
-	      sec->reloc_count = delay ? 3 : 1;
+	      sec->reloc_count = rpp_len - 1;
 	    }
 	  break;
 
@@ -3674,7 +3722,7 @@ usage (FILE *file, int status)
   fprintf (file, _("Usage %s <option(s)> <object-file(s)>\n"), program_name);
   /* xgetext:c-format */
   fprintf (file, _("   -m --machine <machine>    Create as DLL for <machine>.  [default: %s]\n"), mname);
-  fprintf (file, _("        possible <machine>: arm[_interwork], i386, mcore[-elf]{-le|-be}, thumb\n"));
+  fprintf (file, _("        possible <machine>: arm[_interwork], arm64, i386, mcore[-elf]{-le|-be}, thumb\n"));
   fprintf (file, _("   -e --output-exp <outname> Generate an export file.\n"));
   fprintf (file, _("   -l --output-lib <outname> Generate an interface library.\n"));
   fprintf (file, _("   -y --output-delaylib <outname> Create a delay-import library.\n"));
@@ -3967,7 +4015,8 @@ main (int ac, char **av)
   machine = i;
 
   /* Check if we generated PE+.  */
-  create_for_pep = strcmp (mname, "i386:x86-64") == 0;
+  create_for_pep = strcmp (mname, "i386:x86-64") == 0 ||
+		   strcmp (mname, "arm64") == 0;
 
   {
     /* Check the default underscore */
diff --git a/binutils/rescoff.c b/binutils/rescoff.c
index 83b08634c7f..1ae02598313 100644
--- a/binutils/rescoff.c
+++ b/binutils/rescoff.c
@@ -463,6 +463,9 @@ write_coff_file (const char *filename, const char *target,
 #elif defined DLLTOOL_ARM
   if (! bfd_set_arch_mach (abfd, bfd_arch_arm, 0))
     bfd_fatal ("bfd_set_arch_mach(arm)");
+#elif defined DLLTOOL_AARCH64
+  if (! bfd_set_arch_mach (abfd, bfd_arch_aarch64, 0))
+    bfd_fatal ("bfd_set_arch_mach(aarch64)");
 #else
   /* FIXME: This is obviously i386 specific.  */
   if (! bfd_set_arch_mach (abfd, bfd_arch_i386, 0))
diff --git a/gas/configure.tgt b/gas/configure.tgt
index 82f2d44f418..ba49003bc80 100644
--- a/gas/configure.tgt
+++ b/gas/configure.tgt
@@ -135,7 +135,7 @@ case ${generic_target} in
     esac ;;
   aarch64*-*-netbsd*)			fmt=elf em=nbsd;;
   aarch64*-*-openbsd*)			fmt=elf;;
-  aarch64*-*-pe*)			fmt=coff em=pepaarch64 ;;
+  aarch64*-*-pe* | aarch64*-*-mingw*)	fmt=coff em=pepaarch64 ;;
   alpha-*-*vms*)			fmt=evax ;;
   alpha-*-osf*)				fmt=ecoff ;;
   alpha-*-linux*ecoff*)			fmt=ecoff ;;
diff --git a/gas/testsuite/gas/pe/pe.exp b/gas/testsuite/gas/pe/pe.exp
index 8df750f9dd0..231cdecb12b 100644
--- a/gas/testsuite/gas/pe/pe.exp
+++ b/gas/testsuite/gas/pe/pe.exp
@@ -54,7 +54,7 @@ if ([istarget "x86_64-*-mingw*"]) then {
 
 
 # This test is only for AArch64
-if ([istarget "aarch64-*-pe*"]) {
+if {[istarget "aarch64-*-pe*"] || [istarget "aarch64-*-mingw*"]} {
 	run_dump_test "pe-aarch64"
 }
 
diff --git a/ld/configure.tgt b/ld/configure.tgt
index 6b833f26248..d8566daf8cf 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -118,9 +118,9 @@ aarch64-*-linux*)	targ_emul=aarch64linux
 aarch64-*-haiku*)	targ_emul=aarch64haiku
 			targ_extra_emuls="aarch64elf aarch64elf32 aarch64elf32b aarch64elfb armelf armelfb armelf_haiku $targ_extra_libpath"
 			;;
-aarch64-*-pe*)
+aarch64-*-pe* | aarch64-*-mingw*)
 			targ_emul=arm64pe
-			targ_extra_ofiles="deffilep.o pep-dll-aarch64.o"
+			targ_extra_ofiles="deffilep.o pep-dll-aarch64.o pe-dll.o"
 			;;
 alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
 			targ_emul=elf64alpha_fbsd
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index e20339fa874..e5cc15723a4 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -106,7 +106,7 @@ fragment <<EOF
 #define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT}
 #endif
 
-#ifdef TARGET_IS_i386pep
+#if defined(TARGET_IS_i386pep) || defined(TARGET_IS_arm64pe)
 #define DLL_SUPPORT
 #endif
 
@@ -115,7 +115,7 @@ fragment <<EOF
 					 | IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA \
   					 | IMAGE_DLL_CHARACTERISTICS_NX_COMPAT)
 
-#if defined(TARGET_IS_i386pep) || ! defined(DLL_SUPPORT)
+#if defined(TARGET_IS_i386pep) || defined(TARGET_IS_arm64pe) || ! defined(DLL_SUPPORT)
 #define	PE_DEF_SUBSYSTEM		3
 #undef NT_EXE_IMAGE_BASE
 #define NT_EXE_IMAGE_BASE \
@@ -1195,6 +1195,7 @@ make_import_fixup (arelent *rel, asection *s, char *name, const char *symname)
       else if (suc)
 	_addend = bfd_get_16 (s->owner, addend);
       break;
+    case 26:
     case 32:
       suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 4);
       if (suc && rel->howto->pc_relative)
@@ -1541,14 +1542,14 @@ gld${EMULATION_NAME}_after_open (void)
   if (pep_enable_stdcall_fixup) /* -1=warn or 1=enable */
     pep_fixup_stdcalls ();
 
-#ifndef TARGET_IS_i386pep
+#if !defined(TARGET_IS_i386pep) && !defined(TARGET_IS_arm64pe)
   if (bfd_link_pic (&link_info))
 #else
   if (!bfd_link_relocatable (&link_info))
 #endif
     pep_dll_build_sections (link_info.output_bfd, &link_info);
 
-#ifndef TARGET_IS_i386pep
+#if !defined(TARGET_IS_i386pep) && !defined(TARGET_IS_arm64pe)
   else
     pep_exe_build_sections (link_info.output_bfd, &link_info);
 #endif
@@ -1844,6 +1845,8 @@ gld${EMULATION_NAME}_recognized_file (lang_input_statement_type *entry ATTRIBUTE
 #ifdef DLL_SUPPORT
 #ifdef TARGET_IS_i386pep
   pep_dll_id_target ("pei-x86-64");
+#elif defined(TARGET_IS_arm64pe)
+  pep_dll_id_target ("pei-aarch64-little");
 #endif
   if (pep_bfd_is_dll (entry->the_bfd))
     return pep_implied_import_dll (entry->filename);
diff --git a/ld/pe-dll.c b/ld/pe-dll.c
index df16e85bbe0..edfcda9cf16 100644
--- a/ld/pe-dll.c
+++ b/ld/pe-dll.c
@@ -2257,13 +2257,12 @@ static const unsigned char jmp_ix86_bytes[] =
   0xff, 0x25, 0x00, 0x00, 0x00, 0x00, 0x90, 0x90
 };
 
-/* _function:
-  b <__imp_function>
-  nop */
 static const unsigned char jmp_aarch64_bytes[] =
 {
-  0x00, 0x00, 0x00, 0x14,
-  0x1f, 0x20, 0x03, 0xD5
+  0x10, 0x00, 0x00, 0x90, /* adrp x16, 0        */
+  0x10, 0x02, 0x00, 0x91, /* add x16, x16, #0x0 */
+  0x10, 0x02, 0x40, 0xf9, /* ldr x16, [x16]     */
+  0x00, 0x02, 0x1f, 0xd6  /* br x16             */
 };
 
 /* _function:
@@ -2431,7 +2430,8 @@ make_one (def_file_export *exp, bfd *parent, bool include_jmp_stub)
 	  quick_reloc (abfd, 8, BFD_RELOC_32, 2);
 	  break;
 	case PE_ARCH_aarch64:
-	  quick_reloc (abfd, 0, BFD_RELOC_AARCH64_JUMP26, 2);
+	  quick_reloc (abfd, 0, BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL, 2);
+	  quick_reloc (abfd, 4, BFD_RELOC_AARCH64_ADD_LO12, 2);
 	  break;
 	default:
 	  abort ();
diff --git a/ld/testsuite/ld-pe/pe-aarch64.d b/ld/testsuite/ld-pe/pe-aarch64.d
index fac02b5fd87..ab6370fb514 100644
--- a/ld/testsuite/ld-pe/pe-aarch64.d
+++ b/ld/testsuite/ld-pe/pe-aarch64.d
@@ -6,11 +6,20 @@
 
 Disassembly of section .text:
 
-0000000140001000 <__rt_psrelocs_end>:
+0000000140001000 <___crt_xc_end__>:
    140001000:	d2800281 	mov	x1, #0x14                  	// #20
    140001004:	14000001 	b	140001008 <foo>
 
 0000000140001008 <foo>:
    140001008:	d65f03c0 	ret
    14000100c:	00000000 	udf	#0
-#...
+
+0000000140001010 <__CTOR_LIST__>:
+   140001010:	ffffffff 	.inst	0xffffffff ; undefined
+   140001014:	ffffffff 	.inst	0xffffffff ; undefined
+	...
+
+0000000140001020 <__DTOR_LIST__>:
+   140001020:	ffffffff 	.inst	0xffffffff ; undefined
+   140001024:	ffffffff 	.inst	0xffffffff ; undefined
+	...
diff --git a/ld/testsuite/ld-pe/pe.exp b/ld/testsuite/ld-pe/pe.exp
index 83b20d0da45..58158cc657d 100644
--- a/ld/testsuite/ld-pe/pe.exp
+++ b/ld/testsuite/ld-pe/pe.exp
@@ -78,7 +78,7 @@ if {[istarget i*86-*-cygwin*]
     run_ld_link_tests $pe_tests
 }
 
-if {[istarget "aarch64-*-pe*"]} {
+if {[istarget "aarch64-*-pe*"] || [istarget "aarch64-*-mingw*"]} {
     run_dump_test "pe-aarch64"
 
     set pe_tests {
diff --git a/ld/testsuite/ld-scripts/weak.exp b/ld/testsuite/ld-scripts/weak.exp
index 68d70240f7b..2826e3bee78 100644
--- a/ld/testsuite/ld-scripts/weak.exp
+++ b/ld/testsuite/ld-scripts/weak.exp
@@ -31,6 +31,7 @@ if {! [is_elf_format] && ! [is_pecoff_format]} {
 # Weak symbols are broken for most PE targets.
 if {! [istarget i?86-*-*] && ! [istarget sh-*-*]} {
     setup_xfail *-*-pe*
+    setup_xfail *-*-mingw*
 }
 
 # hppa64 is incredibly broken
