diff --git a/bfd/.gitignore b/bfd/.gitignore
index e93eb658453..b4955275cde 100644
--- a/bfd/.gitignore
+++ b/bfd/.gitignore
@@ -12,6 +12,7 @@
 /pex64igen.c
 /pe-aarch64igen.c
 /pe-loongarch64igen.c
+/pe-riscv64igen.c
 /stmp-bfd-h
 /targmatch.h
 
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index a88c6a0034d..bbd19edfa5d 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -578,11 +578,13 @@ BFD64_BACKENDS = \
 	mmo.lo \
 	pe-aarch64igen.lo \
 	pe-loongarch64igen.lo \
+	pe-riscv64igen.lo \
 	pe-x86_64.lo \
 	pei-aarch64.lo \
 	pe-aarch64.lo \
 	pei-ia64.lo \
 	pei-loongarch64.lo \
+	pei-riscv64.lo \
 	pei-x86_64.lo \
 	pepigen.lo \
 	pex64igen.lo \
@@ -627,6 +629,7 @@ BFD64_BACKENDS_CFILES = \
 	pei-aarch64.c \
 	pei-ia64.c \
 	pei-loongarch64.c \
+	pei-riscv64.c \
 	pei-x86_64.c \
 	vms-alpha.c
 
@@ -686,7 +689,8 @@ BUILD_CFILES = \
 	elf32-ia64.c elf64-ia64.c \
 	elf32-loongarch.c elf64-loongarch.c \
 	elf32-riscv.c elf64-riscv.c \
-	peigen.c pepigen.c pex64igen.c pe-aarch64igen.c pe-loongarch64igen.c
+	peigen.c pepigen.c pex64igen.c \
+	pe-aarch64igen.c pe-loongarch64igen.c pe-riscv64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
 
@@ -907,6 +911,10 @@ pe-loongarch64igen.c: peXXigen.c
 	$(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@
 	$(AM_V_GEN)$(SED) -e s/XX/peLoongArch64/g < $< >> $@
 
+pe-riscv64igen.c: peXXigen.c
+	$(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@
+	$(AM_V_GEN)$(SED) -e s/XX/peRISCV64/g < $< >> $@
+
 host-aout.lo: Makefile
 
 # The following program can be used to generate a simple config file
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index d5cc5cb1e17..0ca67ba341f 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -1048,11 +1048,13 @@ BFD64_BACKENDS = \
 	mmo.lo \
 	pe-aarch64igen.lo \
 	pe-loongarch64igen.lo \
+	pe-riscv64igen.lo \
 	pe-x86_64.lo \
 	pei-aarch64.lo \
 	pe-aarch64.lo \
 	pei-ia64.lo \
 	pei-loongarch64.lo \
+	pei-riscv64.lo \
 	pei-x86_64.lo \
 	pepigen.lo \
 	pex64igen.lo \
@@ -1155,7 +1157,8 @@ BUILD_CFILES = \
 	elf32-ia64.c elf64-ia64.c \
 	elf32-loongarch.c elf64-loongarch.c \
 	elf32-riscv.c elf64-riscv.c \
-	peigen.c pepigen.c pex64igen.c pe-aarch64igen.c pe-loongarch64igen.c
+	peigen.c pepigen.c pex64igen.c pe-aarch64igen.c \
+	pe-loongarch64igen.c pe-riscv64igen.c
 
 CFILES = $(SOURCE_CFILES) $(BUILD_CFILES)
 SOURCE_HFILES = \
@@ -1710,6 +1713,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-arm.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-i386.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-loongarch64igen.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-riscv64igen.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-mcore.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-sh.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pe-x86_64.Plo@am__quote@
@@ -1720,6 +1724,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-i386.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-ia64.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-loongarch64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-riscv64.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-mcore.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-sh.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pei-x86_64.Plo@am__quote@
@@ -2426,6 +2431,10 @@ pe-loongarch64igen.c: peXXigen.c
 	$(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@
 	$(AM_V_GEN)$(SED) -e s/XX/peLoongArch64/g < $< >> $@
 
+pe-riscv64igen.c: peXXigen.c
+	$(AM_V_at)echo "#line 1 \"peXXigen.c\"" > $@
+	$(AM_V_GEN)$(SED) -e s/XX/peRISCV64/g < $< >> $@
+
 host-aout.lo: Makefile
 
 # The following program can be used to generate a simple config file
diff --git a/bfd/bfd.c b/bfd/bfd.c
index b9d4aa44d9c..17c296acba1 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -1748,6 +1748,7 @@ bfd_get_sign_extend_vma (bfd *abfd)
       || strcmp (name, "pe-arm-wince-little") == 0
       || strcmp (name, "pei-arm-wince-little") == 0
       || strcmp (name, "pei-loongarch64") == 0
+      || strcmp (name, "pei-riscv64") == 0
       || strcmp (name, "aixcoff-rs6000") == 0
       || strcmp (name, "aix5coff64-rs6000") == 0)
     return 1;
diff --git a/bfd/coff-riscv64.c b/bfd/coff-riscv64.c
new file mode 100644
index 00000000000..b541a6c0daf
--- /dev/null
+++ b/bfd/coff-riscv64.c
@@ -0,0 +1,170 @@
+/* BFD back-end for LoongArch64 COFF files.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+
+#ifndef COFF_WITH_peRISCV64
+#define COFF_WITH_peRISCV64
+#endif
+
+/* Note we have to make sure not to include headers twice.
+   Not all headers are wrapped in #ifdef guards, so we define
+   PEI_HEADERS to prevent double including here.  */
+#ifndef PEI_HEADERS
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "coff/riscv64.h"
+#include "coff/internal.h"
+#include "coff/pe.h"
+#include "libcoff.h"
+#include "libiberty.h"
+#endif
+
+#include "libcoff.h"
+
+/* The page size is a guess based on ELF.  */
+
+#define COFF_PAGE_SIZE 0x4000
+
+/* All users of this file have bfd_octets_per_byte (abfd, sec) == 1.  */
+#define OCTETS_PER_BYTE(ABFD, SEC) 1
+
+#ifndef PCRELOFFSET
+#define PCRELOFFSET true
+#endif
+
+/* Currently we don't handle any relocations.  */
+static reloc_howto_type pe_riscv64_std_reloc_howto[] =
+  {
+
+  };
+
+#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER  2
+
+#ifndef NUM_ELEM
+#define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))
+#endif
+
+#define NUM_RELOCS NUM_ELEM (pe_riscv64_std_reloc_howto)
+
+#define RTYPE2HOWTO(cache_ptr, dst)             \
+  (cache_ptr)->howto = NULL
+
+#ifndef bfd_pe_print_pdata
+#define bfd_pe_print_pdata      NULL
+#endif
+
+/* Handle include/coff/riscv64.h external_reloc.  */
+#define SWAP_IN_RELOC_OFFSET	H_GET_32
+#define SWAP_OUT_RELOC_OFFSET	H_PUT_32
+
+/* Return TRUE if this relocation should
+   appear in the output .reloc section.  */
+
+static bool
+in_reloc_p (bfd * abfd ATTRIBUTE_UNUSED,
+	    reloc_howto_type * howto)
+{
+  return !howto->pc_relative;
+}
+
+#include "coffcode.h"
+
+/* Target vectors.  */
+const bfd_target
+#ifdef TARGET_SYM
+  TARGET_SYM =
+#else
+  riscv64_pei_vec =
+#endif
+{
+#ifdef TARGET_NAME
+  TARGET_NAME,
+#else
+ "pei-riscv64",			/* Name.  */
+#endif
+  bfd_target_coff_flavour,
+  BFD_ENDIAN_LITTLE,		/* Data byte order is little.  */
+  BFD_ENDIAN_LITTLE,		/* Header byte order is little.  */
+
+  (HAS_RELOC | EXEC_P		/* Object flags.  */
+   | HAS_LINENO | HAS_DEBUG
+   | HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | BFD_COMPRESS | BFD_DECOMPRESS),
+
+  (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* Section flags.  */
+#if defined(COFF_WITH_PE)
+   | SEC_LINK_ONCE | SEC_LINK_DUPLICATES | SEC_READONLY | SEC_DEBUGGING
+#endif
+   | SEC_CODE | SEC_DATA | SEC_EXCLUDE ),
+
+#ifdef TARGET_UNDERSCORE
+  TARGET_UNDERSCORE,		/* Leading underscore.  */
+#else
+  0,				/* Leading underscore.  */
+#endif
+  '/',				/* Ar_pad_char.  */
+  15,				/* Ar_max_namelen.  */
+  0,				/* match priority.  */
+  TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
+
+     /* Data conversion functions.  */
+     bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Data.  */
+     /* Header conversion functions.  */
+     bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+     bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+     bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* Hdrs.  */
+
+  /* Note that we allow an object file to be treated as a core file as well.  */
+  {				/* bfd_check_format.  */
+    _bfd_dummy_target,
+    coff_object_p,
+    bfd_generic_archive_p,
+    coff_object_p
+  },
+  {				/* bfd_set_format.  */
+    _bfd_bool_bfd_false_error,
+    coff_mkobject,
+    _bfd_generic_mkarchive,
+    _bfd_bool_bfd_false_error
+  },
+  {				/* bfd_write_contents.  */
+    _bfd_bool_bfd_false_error,
+    coff_write_object_contents,
+    _bfd_write_archive_contents,
+    _bfd_bool_bfd_false_error
+  },
+
+  BFD_JUMP_TABLE_GENERIC (coff),
+  BFD_JUMP_TABLE_COPY (coff),
+  BFD_JUMP_TABLE_CORE (_bfd_nocore),
+  BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
+  BFD_JUMP_TABLE_SYMBOLS (coff),
+  BFD_JUMP_TABLE_RELOCS (coff),
+  BFD_JUMP_TABLE_WRITE (coff),
+  BFD_JUMP_TABLE_LINK (coff),
+  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+  NULL,
+
+  COFF_SWAP_TABLE
+};
+
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index 52027981c3f..ed162f918df 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -2237,6 +2237,12 @@ coff_set_arch_mach_hook (bfd *abfd, void * filehdr)
       machine = internal_f->f_flags & F_LOONGARCH64_ARCHITECTURE_MASK;
       break;
 #endif
+#ifdef RISCV64MAGIC
+    case RISCV64MAGIC:
+      arch = bfd_arch_riscv;
+      machine = internal_f->f_flags & F_RISCV64_ARCHITECTURE_MASK;
+      break;
+#endif
 #ifdef Z80MAGIC
     case Z80MAGIC:
       arch = bfd_arch_z80;
@@ -2807,6 +2813,12 @@ coff_set_flags (bfd * abfd,
       return true;
 #endif
 
+#ifdef RISCV64MAGIC
+    case bfd_arch_riscv:
+        * magicp = RISCV64MAGIC;
+	return true;
+#endif
+
 #ifdef ARMMAGIC
     case bfd_arch_arm:
 #ifdef ARM_WINCE
@@ -3902,7 +3914,7 @@ coff_write_object_contents (bfd * abfd)
     internal_f.f_flags |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
 #endif
 
-#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
 #ifdef COFF_WITH_PE
   internal_f.f_flags |= IMAGE_FILE_32BIT_MACHINE;
 #else
@@ -3961,6 +3973,11 @@ coff_write_object_contents (bfd * abfd)
     internal_a.magic = ZMAGIC;
 #endif
 
+#if defined(RISCV64)
+#define __A_MAGIC_SET__
+    internal_a.magic = ZMAGIC;
+#endif
+
 #if defined MCORE_PE
 #define __A_MAGIC_SET__
     internal_a.magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
diff --git a/bfd/config.bfd b/bfd/config.bfd
index 0bc27fdce97..6377f413482 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -1223,7 +1223,7 @@ case "${targ}" in
     ;;
   riscv64*-*-*)
     targ_defvec=riscv_elf64_vec
-    targ_selvecs="riscv_elf32_vec riscv_elf64_vec riscv_elf32_be_vec riscv_elf64_be_vec"
+    targ_selvecs="riscv_elf32_vec riscv_elf64_vec riscv_elf32_be_vec riscv_elf64_be_vec riscv64_pei_vec"
     want64=true
     ;;
 #endif
diff --git a/bfd/configure b/bfd/configure
index 74bc5a18471..feeecc440bf 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -13782,6 +13782,7 @@ do
     riscv_elf64_vec)		 tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;;
     riscv_elf32_be_vec)		 tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;;
     riscv_elf64_be_vec)		 tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;;
+    riscv64_pei_vec)		 tb="$tb pei-riscv64.lo pe-riscv64igen.lo $coff"; target_size=64 ;;
     rl78_elf32_vec)		 tb="$tb elf32-rl78.lo elf32.lo $elf" ;;
     rs6000_xcoff64_vec)		 tb="$tb coff64-rs6000.lo aix5ppc-core.lo $xcoff"; target_size=64 ;;
     rs6000_xcoff64_aix_vec)	 tb="$tb coff64-rs6000.lo aix5ppc-core.lo $xcoff"; target_size=64 ;;
diff --git a/bfd/configure.ac b/bfd/configure.ac
index 5d450a4ad25..e7c3e58d352 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -583,6 +583,7 @@ do
     riscv_elf64_vec)		 tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;;
     riscv_elf32_be_vec)		 tb="$tb elf32-riscv.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf" ;;
     riscv_elf64_be_vec)		 tb="$tb elf64-riscv.lo elf64.lo elfxx-riscv.lo elf-ifunc.lo elf32.lo $elf"; target_size=64 ;;
+    riscv64_pei_vec)		 tb="$tb pei-riscv64.lo pe-riscv64igen.lo $coff"; target_size=64 ;;
     rl78_elf32_vec)		 tb="$tb elf32-rl78.lo elf32.lo $elf" ;;
     rs6000_xcoff64_vec)		 tb="$tb coff64-rs6000.lo aix5ppc-core.lo $xcoff"; target_size=64 ;;
     rs6000_xcoff64_aix_vec)	 tb="$tb coff64-rs6000.lo aix5ppc-core.lo $xcoff"; target_size=64 ;;
diff --git a/bfd/libpei.h b/bfd/libpei.h
index 98e951d8839..cd1c7753f53 100644
--- a/bfd/libpei.h
+++ b/bfd/libpei.h
@@ -345,6 +345,41 @@
 #define _bfd_XXi_write_codeview_record			_bfd_peLoongArch64i_write_codeview_record
 #define _bfd_XXi_slurp_codeview_record			_bfd_peLoongArch64i_slurp_codeview_record
 
+#elif defined COFF_WITH_peRISCV64
+
+#define GET_OPTHDR_IMAGE_BASE		 H_GET_64
+#define PUT_OPTHDR_IMAGE_BASE		 H_PUT_64
+#define GET_OPTHDR_SIZE_OF_STACK_RESERVE H_GET_64
+#define PUT_OPTHDR_SIZE_OF_STACK_RESERVE H_PUT_64
+#define GET_OPTHDR_SIZE_OF_STACK_COMMIT	 H_GET_64
+#define PUT_OPTHDR_SIZE_OF_STACK_COMMIT	 H_PUT_64
+#define GET_OPTHDR_SIZE_OF_HEAP_RESERVE	 H_GET_64
+#define PUT_OPTHDR_SIZE_OF_HEAP_RESERVE	 H_PUT_64
+#define GET_OPTHDR_SIZE_OF_HEAP_COMMIT	 H_GET_64
+#define PUT_OPTHDR_SIZE_OF_HEAP_COMMIT	 H_PUT_64
+#define GET_PDATA_ENTRY			 bfd_get_32
+
+#define _bfd_XX_bfd_copy_private_bfd_data_common	_bfd_peRISCV64_bfd_copy_private_bfd_data_common
+#define _bfd_XX_bfd_copy_private_section_data		_bfd_peRISCV64_bfd_copy_private_section_data
+#define _bfd_XX_get_symbol_info				_bfd_peRISCV64_get_symbol_info
+#define _bfd_XX_only_swap_filehdr_out			_bfd_peRISCV64_only_swap_filehdr_out
+#define _bfd_XX_print_private_bfd_data_common		_bfd_peRISCV64_print_private_bfd_data_common
+#define _bfd_XXi_final_link_postscript			_bfd_peRISCV64i_final_link_postscript
+#define _bfd_XXi_only_swap_filehdr_out			_bfd_peRISCV64i_only_swap_filehdr_out
+#define _bfd_XXi_swap_aouthdr_in			_bfd_peRISCV64i_swap_aouthdr_in
+#define _bfd_XXi_swap_aouthdr_out			_bfd_peRISCV64i_swap_aouthdr_out
+#define _bfd_XXi_swap_aux_in				_bfd_peRISCV64i_swap_aux_in
+#define _bfd_XXi_swap_aux_out				_bfd_peRISCV64i_swap_aux_out
+#define _bfd_XXi_swap_lineno_in				_bfd_peRISCV64i_swap_lineno_in
+#define _bfd_XXi_swap_lineno_out			_bfd_peRISCV64i_swap_lineno_out
+#define _bfd_XXi_swap_scnhdr_out			_bfd_peRISCV64i_swap_scnhdr_out
+#define _bfd_XXi_swap_sym_in				_bfd_peRISCV64i_swap_sym_in
+#define _bfd_XXi_swap_sym_out				_bfd_peRISCV64i_swap_sym_out
+#define _bfd_XXi_swap_debugdir_in			_bfd_peRISCV64i_swap_debugdir_in
+#define _bfd_XXi_swap_debugdir_out			_bfd_peRISCV64i_swap_debugdir_out
+#define _bfd_XXi_write_codeview_record			_bfd_peRISCV64i_write_codeview_record
+#define _bfd_XXi_slurp_codeview_record			_bfd_peRISCV64i_slurp_codeview_record
+
 #else /* !COFF_WITH_pep */
 
 #define GET_OPTHDR_IMAGE_BASE H_GET_32
@@ -443,5 +478,6 @@ bool _bfd_pe64_print_ce_compressed_pdata (bfd *, void *);
 bool _bfd_pex64_print_ce_compressed_pdata (bfd *, void *);
 bool _bfd_peAArch64_print_ce_compressed_pdata (bfd *, void *);
 bool _bfd_peLoongArch64_print_ce_compressed_pdata (bfd *, void *);
+bool _bfd_peRISCV64_print_ce_compressed_pdata (bfd *, void *);
 bool _bfd_pep_print_ce_compressed_pdata (bfd *, void *);
 
diff --git a/bfd/peXXigen.c b/bfd/peXXigen.c
index 0232a63d558..33393bfec7c 100644
--- a/bfd/peXXigen.c
+++ b/bfd/peXXigen.c
@@ -61,8 +61,8 @@
    wasting too much time.  */
 
 /* This expands into COFF_WITH_pe, COFF_WITH_pep, COFF_WITH_pex64,
-   COFF_WITH_peAArch64 or COFF_WITH_peLoongArch64 depending on whether we're
-   compiling for straight PE or PE+.  */
+   COFF_WITH_peAArch64 ,COFF_WITH_peLoongArch64 or COFF_WITH_peRISCV64
+   depending on whether we're compiling for straight PE or PE+.  */
 #define COFF_WITH_XX
 
 #include "sysdep.h"
@@ -88,6 +88,8 @@
 # include "coff/aarch64.h"
 #elif defined COFF_WITH_peLoongArch64
 # include "coff/loongarch64.h"
+#elif defined COFF_WITH_peRISCV64
+# include "coff/riscv64.h"
 #else
 # include "coff/i386.h"
 #endif
@@ -97,7 +99,7 @@
 #include "libpei.h"
 #include "safe-ctype.h"
 
-#if defined COFF_WITH_pep || defined COFF_WITH_pex64 || defined COFF_WITH_peAArch64 || defined COFF_WITH_peLoongArch64
+#if defined COFF_WITH_pep || defined COFF_WITH_pex64 || defined COFF_WITH_peAArch64 || defined COFF_WITH_peLoongArch64 || defined COFF_WITH_peRISCV64
 # undef AOUTSZ
 # define AOUTSZ		PEPAOUTSZ
 # define PEAOUTHDR	PEPAOUTHDR
@@ -474,7 +476,7 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
   aouthdr_int->text_start =
     GET_AOUTHDR_TEXT_START (abfd, aouthdr_ext->text_start);
 
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
   /* PE32+ does not have data_start member!  */
   aouthdr_int->data_start =
     GET_AOUTHDR_DATA_START (abfd, aouthdr_ext->data_start);
@@ -541,7 +543,7 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
   if (aouthdr_int->entry)
     {
       aouthdr_int->entry += a->ImageBase;
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       aouthdr_int->entry &= 0xffffffff;
 #endif
     }
@@ -549,12 +551,12 @@ _bfd_XXi_swap_aouthdr_in (bfd * abfd,
   if (aouthdr_int->tsize)
     {
       aouthdr_int->text_start += a->ImageBase;
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       aouthdr_int->text_start &= 0xffffffff;
 #endif
     }
 
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
   /* PE32+ does not have data_start member!  */
   if (aouthdr_int->dsize)
     {
@@ -614,7 +616,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   if (aouthdr_in->tsize)
     {
       aouthdr_in->text_start -= ib;
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       aouthdr_in->text_start &= 0xffffffff;
 #endif
     }
@@ -622,7 +624,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   if (aouthdr_in->dsize)
     {
       aouthdr_in->data_start -= ib;
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       aouthdr_in->data_start &= 0xffffffff;
 #endif
     }
@@ -630,7 +632,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   if (aouthdr_in->entry)
     {
       aouthdr_in->entry -= ib;
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       aouthdr_in->entry &= 0xffffffff;
 #endif
     }
@@ -744,7 +746,7 @@ _bfd_XXi_swap_aouthdr_out (bfd * abfd, void * in, void * out)
   PUT_AOUTHDR_TEXT_START (abfd, aouthdr_in->text_start,
 			  aouthdr_out->standard.text_start);
 
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
   /* PE32+ does not have data_start member!  */
   PUT_AOUTHDR_DATA_START (abfd, aouthdr_in->data_start,
 			  aouthdr_out->standard.data_start);
@@ -930,7 +932,7 @@ _bfd_XXi_swap_scnhdr_out (bfd * abfd, void * in, void * out)
     _bfd_error_handler (_("%pB:%.8s: section below image base"),
                         abfd, scnhdr_int->s_name);
   /* Do not compare lower 32-bits for 64-bit vma.  */
-#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
   else if(ss != (ss & 0xffffffff))
     _bfd_error_handler (_("%pB:%.8s: RVA truncated"), abfd, scnhdr_int->s_name);
   PUT_SCNHDR_VADDR (abfd, ss & 0xffffffff, scnhdr_ext->s_vaddr);
@@ -1814,7 +1816,7 @@ pe_print_edata (bfd * abfd, void * vfile)
 static bool
 pe_print_pdata (bfd * abfd, void * vfile)
 {
-#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
 # define PDATA_ROW_SIZE	(3 * 8)
 #else
 # define PDATA_ROW_SIZE	(5 * 4)
@@ -1841,7 +1843,7 @@ pe_print_pdata (bfd * abfd, void * vfile)
 
   fprintf (file,
 	   _("\nThe Function Table (interpreted .pdata section contents)\n"));
-#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
   fprintf (file,
 	   _(" vma:\t\t\tBegin Address    End Address      Unwind Info\n"));
 #else
@@ -1878,7 +1880,7 @@ pe_print_pdata (bfd * abfd, void * vfile)
       bfd_vma eh_handler;
       bfd_vma eh_data;
       bfd_vma prolog_end_addr;
-#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined(COFF_WITH_peRISCV64)
       int em_data;
 #endif
 
@@ -1896,7 +1898,7 @@ pe_print_pdata (bfd * abfd, void * vfile)
 	/* We are probably into the padding of the section now.  */
 	break;
 
-#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined(COFF_WITH_peRISCV64)
       em_data = ((eh_handler & 0x1) << 2) | (prolog_end_addr & 0x3);
 #endif
       eh_handler &= ~(bfd_vma) 0x3;
@@ -1907,7 +1909,7 @@ pe_print_pdata (bfd * abfd, void * vfile)
       bfd_fprintf_vma (abfd, file, begin_addr); fputc (' ', file);
       bfd_fprintf_vma (abfd, file, end_addr); fputc (' ', file);
       bfd_fprintf_vma (abfd, file, eh_handler);
-#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) || defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined(COFF_WITH_peRISCV64)
       fputc (' ', file);
       bfd_fprintf_vma (abfd, file, eh_data); fputc (' ', file);
       bfd_fprintf_vma (abfd, file, prolog_end_addr);
@@ -2803,7 +2805,7 @@ _bfd_XX_print_private_bfd_data_common (bfd * abfd, void * vfile)
   bfd_fprintf_vma (abfd, file, i->AddressOfEntryPoint);
   fprintf (file, "\nBaseOfCode\t\t");
   bfd_fprintf_vma (abfd, file, i->BaseOfCode);
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
   /* PE32+ does not have BaseOfData member!  */
   fprintf (file, "\nBaseOfData\t\t");
   bfd_fprintf_vma (abfd, file, i->BaseOfData);
@@ -3118,7 +3120,7 @@ _bfd_XX_get_symbol_info (bfd * abfd, asymbol *symbol, symbol_info *ret)
   coff_get_symbol_info (abfd, symbol, ret);
 }
 
-#if !defined(COFF_WITH_pep) && (defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64))
+#if !defined(COFF_WITH_pep) && (defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined(COFF_WITH_peRISCV64))
 static int
 sort_x64_pdata (const void *l, const void *r)
 {
@@ -4537,7 +4539,7 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
 	the TLS data directory consists of 4 pointers, followed
 	by two 4-byte integer. This implies that the total size
 	is different for 32-bit and 64-bit executables.  */
-#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pep) && !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].Size = 0x18;
 #else
       pe_data (abfd)->pe_opthdr.DataDirectory[PE_TLS_TABLE].Size = 0x28;
@@ -4546,7 +4548,7 @@ _bfd_XXi_final_link_postscript (bfd * abfd, struct coff_final_link_info *pfinfo)
 
 /* If there is a .pdata section and we have linked pdata finally, we
      need to sort the entries ascending.  */
-#if !defined(COFF_WITH_pep) && (defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64))
+#if !defined(COFF_WITH_pep) && (defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined(COFF_WITH_peRISCV64))
   {
     asection *sec = bfd_get_section_by_name (abfd, ".pdata");
 
diff --git a/bfd/pei-riscv64.c b/bfd/pei-riscv64.c
new file mode 100644
index 00000000000..69c16a2862f
--- /dev/null
+++ b/bfd/pei-riscv64.c
@@ -0,0 +1,76 @@
+/* BFD back-end for RISCV64 PE IMAGE COFF files.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#define TARGET_SYM		riscv64_pei_vec
+#define TARGET_NAME		"pei-riscv64"
+#define TARGET_ARCHITECTURE	bfd_arch_riscv
+#define TARGET_PAGESIZE		0x4000
+#define TARGET_BIG_ENDIAN	0
+#define TARGET_ARCHIVE		0
+#define TARGET_PRIORITY		0
+
+#define COFF_IMAGE_WITH_PE
+/* Rename the above into...  */
+#define COFF_WITH_peRISCV64
+#define COFF_WITH_PE
+#define PCRELOFFSET	   true
+
+/* Long section names not allowed in executable images, only object files.  */
+#define COFF_LONG_SECTION_NAMES 0
+
+#define COFF_SECTION_ALIGNMENT_ENTRIES \
+{ COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
+  COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
+
+#define PEI_HEADERS
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "coff/riscv64.h"
+#include "coff/internal.h"
+#include "coff/pe.h"
+#include "libcoff.h"
+#include "libpei.h"
+#include "libiberty.h"
+
+/* Make sure we're setting a 64-bit format.  */
+#undef AOUTSZ
+#define AOUTSZ          PEPAOUTSZ
+#define PEAOUTHDR       PEPAOUTHDR
+
+#include "coff-riscv64.c"
+
diff --git a/bfd/peicode.h b/bfd/peicode.h
index f7ba24ae10a..b606210796e 100644
--- a/bfd/peicode.h
+++ b/bfd/peicode.h
@@ -233,7 +233,7 @@ coff_swap_scnhdr_in (bfd * abfd, void * ext, void * in)
     {
       scnhdr_int->s_vaddr += pe_data (abfd)->pe_opthdr.ImageBase;
       /* Do not cut upper 32-bits for 64-bit vma.  */
-#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64)
+#if !defined(COFF_WITH_pex64) && !defined(COFF_WITH_peAArch64) && !defined(COFF_WITH_peLoongArch64) && !defined(COFF_WITH_peRISCV64)
       scnhdr_int->s_vaddr &= 0xffffffff;
 #endif
     }
@@ -774,6 +774,16 @@ static const jump_table jtab[] =
     4, 0
   },
 
+#endif
+
+#ifdef RISCV64MAGIC
+/* We don't currently support jumping to DLLs, so if
+   someone does try emit a runtime trap.  Through BREAK 0.  */
+  { RISCV64MAGIC,
+    { 0x00, 0x00, 0x00, 0x00 },
+    4, 0
+  },
+
 #endif
 
   { 0, { 0 }, 0, 0 }
@@ -933,7 +943,7 @@ pe_ILF_build_a_bfd (bfd *	    abfd,
 	/* See PR 20907 for a reproducer.  */
 	goto error_return;
 
-#if defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64)
+#if defined(COFF_WITH_pex64) || defined(COFF_WITH_peAArch64) || defined(COFF_WITH_peLoongArch64) || defined(COFF_WITH_peRISCV64)
       ((unsigned int *) id4->contents)[0] = ordinal;
       ((unsigned int *) id4->contents)[1] = 0x80000000;
       ((unsigned int *) id5->contents)[0] = ordinal;
@@ -1241,6 +1251,12 @@ pe_ILF_object_p (bfd * abfd)
 #endif
       break;
 
+    case IMAGE_FILE_MACHINE_RISCV64:
+#ifdef RISCV64MAGIC
+      magic = RISCV64MAGIC;
+#endif
+      break;
+
     case IMAGE_FILE_MACHINE_THUMB:
 #ifdef THUMBPEMAGIC
       {
diff --git a/bfd/targets.c b/bfd/targets.c
index 0bb85b64cc2..457b16e18ab 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -864,6 +864,7 @@ extern const bfd_target riscv_elf32_vec;
 extern const bfd_target riscv_elf64_vec;
 extern const bfd_target riscv_elf32_be_vec;
 extern const bfd_target riscv_elf64_be_vec;
+extern const bfd_target riscv64_pei_vec;
 extern const bfd_target rl78_elf32_vec;
 extern const bfd_target rs6000_xcoff64_vec;
 extern const bfd_target rs6000_xcoff64_aix_vec;
@@ -1258,6 +1259,7 @@ static const bfd_target * const _bfd_target_vector[] =
 	&riscv_elf64_vec,
 	&riscv_elf32_be_vec,
 	&riscv_elf64_be_vec,
+	&riscv64_pei_vec,
 #endif
 	&rl78_elf32_vec,
 
diff --git a/binutils/testsuite/binutils-all/riscv/pei-riscv64.d b/binutils/testsuite/binutils-all/riscv/pei-riscv64.d
new file mode 100644
index 00000000000..bc170ef020d
--- /dev/null
+++ b/binutils/testsuite/binutils-all/riscv/pei-riscv64.d
@@ -0,0 +1,15 @@
+#ld: -e0
+#PROG: objcopy
+#objcopy: -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel -j .rela -j .rel.* -j .rela.* -j .rel* -j .rela* -j .reloc --target=pei-riscv64
+#objdump: -h -f
+#name: Check if efi app format is recognized
+
+.*:     file format pei-riscv64
+architecture: riscv, flags 0x00000132:
+EXEC_P, HAS_SYMS, HAS_LOCALS, D_PAGED
+start address 0x0000000000000000
+
+Sections:
+Idx Name          Size      VMA               LMA               File off  Algn
+  0 \.text         00000010  0[^ ]+  0[^ ]+  0[^ ]+  2\*\*2
+                  CONTENTS, ALLOC, LOAD, READONLY, CODE
diff --git a/binutils/testsuite/binutils-all/riscv/pei-riscv64.s b/binutils/testsuite/binutils-all/riscv/pei-riscv64.s
new file mode 100644
index 00000000000..a2ac0352fd1
--- /dev/null
+++ b/binutils/testsuite/binutils-all/riscv/pei-riscv64.s
@@ -0,0 +1,20 @@
+        .file   "test_pei.c"
+        .option nopic
+        .attribute arch, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"
+        .attribute unaligned_access, 0
+        .attribute stack_align, 16
+        .text
+        .align  1
+        .globl  main
+        .type   main, @function
+main:
+        addi    sp,sp,-16
+        sd      s0,8(sp)
+        addi    s0,sp,16
+        li      a5,0
+        mv      a0,a5
+        ld      s0,8(sp)
+        addi    sp,sp,16
+        jr      ra
+        .size   main, .-main
+        .ident  "GCC: (gf120196382a) 13.0.0 20221124 (experimental)"
diff --git a/include/coff/pe.h b/include/coff/pe.h
index da600e1c781..6d68b8afe50 100644
--- a/include/coff/pe.h
+++ b/include/coff/pe.h
@@ -164,6 +164,7 @@
 #define IMAGE_FILE_MACHINE_WCEMIPSV2         0x0169
 #define IMAGE_FILE_MACHINE_AMD64             0x8664
 #define IMAGE_FILE_MACHINE_LOONGARCH64       0x6264
+#define IMAGE_FILE_MACHINE_RISCV64           0x5064
 
 #define IMAGE_SUBSYSTEM_UNKNOWN			 0
 #define IMAGE_SUBSYSTEM_NATIVE			 1
diff --git a/include/coff/riscv64.h b/include/coff/riscv64.h
new file mode 100644
index 00000000000..0eb3a40690a
--- /dev/null
+++ b/include/coff/riscv64.h
@@ -0,0 +1,62 @@
+/* RISCV64 COFF support for BFD.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+
+   This file is part of BFD, the Binary File Descriptor library.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#define COFFRISCV64 1
+
+#define L_LNNO_SIZE 2
+#define INCLUDE_COMDAT_FIELDS_IN_AUXENT
+#include "coff/external.h"
+
+#define F_RISCV64_ARCHITECTURE_MASK	(0x4000)
+
+#define RISCV64MAGIC	0x5064  /* From Microsoft specification. */
+
+#undef  BADMAG
+#define BADMAG(x) ((x).f_magic != RISCV64MAGIC)
+#define RISCV64         1                 /* Customize coffcode.h.  */
+
+#define IMAGE_NT_OPTIONAL_HDR64_MAGIC      0x20b
+
+#define OMAGIC          0404    /* Object files, eg as output.  */
+#define ZMAGIC          IMAGE_NT_OPTIONAL_HDR64_MAGIC    /* Demand load format, eg normal ld output 0x10b.  */
+#define STMAGIC		0401	/* Target shlib.  */
+#define SHMAGIC		0443	/* Host   shlib.  */
+
+/* define some NT default values */
+/*  #define NT_IMAGE_BASE        0x400000 moved to internal.h */
+#define NT_SECTION_ALIGNMENT 0x1000
+#define NT_FILE_ALIGNMENT    0x200
+#define NT_DEF_RESERVE       0x100000
+#define NT_DEF_COMMIT        0x1000
+
+/* We use the .rdata section to hold read only data.  */
+#define _LIT	".rdata"
+
+/********************** RELOCATION DIRECTIVES **********************/
+struct external_reloc
+{
+  char r_vaddr[4];
+  char r_symndx[4];
+  char r_type[2];
+  char r_offset[4];
+};
+
+#define RELOC struct external_reloc
+#define RELSZ 14
+
