diff --git a/gcc/config.gcc b/gcc/config.gcc
index cdd4fb4392a..9d686019b28 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -368,6 +368,7 @@ arm*-*-*)
 	c_target_objs="arm-c.o"
 	cxx_target_objs="arm-c.o"
 	d_target_objs="arm-d.o"
+        rust_target_objs="arm-rust.o"
 	extra_options="${extra_options} arm/arm-tables.opt"
 	target_gtfiles="\$(srcdir)/config/arm/arm-builtins.cc \$(srcdir)/config/arm/arm-mve-builtins.h \$(srcdir)/config/arm/arm-mve-builtins.cc"
 	;;
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index f8aabbdae37..9513f96fdbc 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -406,6 +406,9 @@ extern void arm_cpu_cpp_builtins (struct cpp_reader *);
 extern void arm_d_target_versions (void);
 extern void arm_d_register_target_info (void);
 
+/* Defined in arm-rust.c  */
+extern void arm_rust_target_cpu_info (void);
+
 extern bool arm_is_constant_pool_ref (rtx);
 
 /* The bits in this mask specify which instruction scheduling options should
diff --git a/gcc/config/arm/arm-rust.cc b/gcc/config/arm/arm-rust.cc
new file mode 100644
index 00000000000..7c83e3fa3a6
--- /dev/null
+++ b/gcc/config/arm/arm-rust.cc
@@ -0,0 +1,304 @@
+/* Subroutines for the Rust front end on the ARM architecture.
+   Copyright (C) 2020 Free Software Foundation, Inc.
+
+GCC 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, or (at your option)
+any later version.
+
+GCC 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 GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tm_p.h"
+#include "rust/rust-target.h"
+#include "rust/rust-target-def.h"
+
+/* Implement TARGET_RUST_CPU_INFO for ARM targets.  */
+
+void arm_rust_target_cpu_info(void) {
+    rust_add_target_info("target_arch", "arm");
+
+    /* TODO: further research support for CLREX, acquire-release (lda/ldaex), slow-fp-brcc (slow FP
+     * compare and branch), perfmon, trustzone, fpao, fuse-aes, fuse-literals, read-tp-hard, zcz,
+     * prof-unpr, slow-vgetlni32, slow-vdup32, prefer-vmovsr, prefer-ishst, muxed-units, slow-odd-reg,
+     * slow-load-D-subreg, wide-stride-vfp, dont-widen-vmovs, splat-vfp-neon, expand-fp-mlx,
+     * vmlx-hazards, neon-fpmovs, neonfp (as in using neon for scalar fp), vldn-align,
+     * nonpipelined-vfp, slowfpvmlx, slowfpvfmx, vmlx-forwarding, 32bit (prefer 32-bit Thumb),
+     * loop-align, mve1beat, mve2beat, mve4beat, avoid-partial-cpsr, cheap-predictable-cpsr,
+     * avoid-movs-shop, ret-addr-stack, no-branch-predictor, virtualization, nacl-trap, execute-only,
+     * reserve-r9, no-movt, no-neg-immediates, use-misched, disable-postra-scheduler, lob (Low
+     * Overhead Branch), noarm, cde - can't find them. */
+    /* TODO: figure out if gcc has an equivalent to "fpregs" (floating-point registers even if only
+     * used for integer - shared between VFP and MVE).  */
+    if (TARGET_VFPD32)
+        rust_add_target_info("target_feature", "d32");
+    bool hasFeatureVFP2 = bitmap_bit_p(arm_active_target.isa, isa_bit_vfpv2) && TARGET_VFP_DOUBLE;
+    if (hasFeatureVFP2) {
+        rust_add_target_info("target_feature", "vfp2");
+
+        // also added implied features that aren't separately supported in gcc
+        rust_add_target_info("target_feature", "vfp2sp");
+    }
+    // minimal VFPv3 support - support for instruction set, not necessarily full
+    bool minVFP3 = TARGET_VFP3 && bitmap_bit_p(arm_active_target.isa, isa_bit_vfpv2);
+    if (minVFP3) {
+        rust_add_target_info("target_feature", "vfp3d16sp");
+
+        if (TARGET_VFPD32)
+            rust_add_target_info("target_feature", "vfp3sp");
+
+        if (TARGET_VFP_DOUBLE) {
+            rust_add_target_info("target_feature", "vfp3d16");
+
+            if (TARGET_VFPD32) {
+                rust_add_target_info("target_feature", "vfp3");
+
+                if (bitmap_bit_p(arm_active_target.isa, isa_bit_neon))
+                    rust_add_target_info("target_feature", "neon");
+            }
+        }
+    }
+    bool hasFeatureVFP3 = minVFP3 && TARGET_VFP_DOUBLE && TARGET_VFPD32;
+    bool hasFeatureFP16 = bitmap_bit_p(arm_active_target.isa, isa_bit_fp16conv);
+    if (hasFeatureFP16)
+        rust_add_target_info("target_info", "fp16");
+    bool minVFP4 = minVFP3 && bitmap_bit_p(arm_active_target.isa, isa_bit_vfpv4) && hasFeatureFP16;
+    if (minVFP4) {
+        rust_add_target_info("target_feature", "vfp4d16sp");
+
+        if (TARGET_VFPD32)
+            rust_add_target_info("target_feature", "vfp4sp");
+
+        if (TARGET_VFP_DOUBLE) {
+            rust_add_target_info("target_feature", "vfp4d16");
+
+            if (TARGET_VFPD32) {
+                rust_add_target_info("target_feature", "vfp4");
+            }
+        }
+    }
+    // NOTE: supposedly "fp-armv8" features in llvm are the same as "fpv5", so creating them based on
+    // that
+    bool minFP_ARMv8 = minVFP4 && TARGET_VFP5;
+    if (minFP_ARMv8) {
+        rust_add_target_info("target_feature", "fp-armv8d16sp");
+
+        if (TARGET_VFPD32)
+            rust_add_target_info("target_feature", "fp-armv8sp");
+
+        if (TARGET_VFP_DOUBLE) {
+            rust_add_target_info("target_feature", "fp-armv8d16");
+
+            if (TARGET_VFPD32) {
+                rust_add_target_info("target_feature", "fp-armv8");
+            }
+        }
+
+        if (bitmap_bit_p(arm_active_target.isa, isa_bit_fp16)) {
+            rust_add_target_info("target_feature", "fullfp16");
+
+            if (bitmap_bit_p(arm_active_target.isa, isa_bit_fp16fml))
+                rust_add_target_info("target_feature", "fp16fml");
+        }
+    }
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_tdiv))
+        rust_add_target_info("target_feature", "hwdiv");
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_adiv))
+        rust_add_target_info("target_feature", "hwdiv-arm");
+    // TODO: I'm not sure if there's an exact correlation here (data barrier), so maybe research
+    // There's also the question of whether this also means "full data barrier" ("fdb" in llvm)
+    if (TARGET_HAVE_MEMORY_BARRIER)
+        rust_add_target_info("target_feature", "db");
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_cmse))
+        rust_add_target_info("target_feature", "8msecext");
+    /* TODO: note that sha2 is an option for aarch64 in gcc but not for arm, so no feature here
+     * possible. The same goes for aes. However, as llvm has them as prerequisites for crypto, they
+     * are enabled with it. */
+    if (TARGET_CRYPTO) {
+        rust_add_target_info("target_feature", "crypto");
+        rust_add_target_info("target_feature", "sha2");
+        rust_add_target_info("target_feature", "aes");
+    }
+    if (TARGET_CRC32)
+        rust_add_target_info("target_feature", "crc");
+    if (TARGET_DOTPROD)
+        rust_add_target_info("target_feature", "dotprod");
+    // TODO: supposedly gcc supports RAS, but I couldn't find the option, so leaving out "ras" for now
+    if (TARGET_DSP_MULTIPLY)
+        rust_add_target_info("target_feature", "dsp");
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_mp))
+        rust_add_target_info("target_feature", "mp");
+    // TODO: figure out the exact strict-align feature, which I'm pretty sure GCC has
+    // TODO: figure out how to access long call data (which is in GCC) for "long-calls"
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_sb))
+        rust_add_target_info("target_feature", "sb");
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_bf16))
+        rust_add_target_info("target_feature", "bf16");
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_i8mm))
+        rust_add_target_info("target_feature", "i8mm");
+    switch (TARGET_ARM_ARCH_PROFILE) {
+        case 'A':
+            rust_add_target_info("target_feature", "aclass");
+            break;
+        case 'R':
+            rust_add_target_info("target_feature", "rclass");
+            break;
+        case 'M':
+            rust_add_target_info("target_feature", "mclass");
+            break;
+        default:
+            fprintf(stderr, "Screwed up profile selection in arm-rust.c - unknown profile '%c'",
+              TARGET_ARM_ARCH_PROFILE);
+            break;
+    }
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_thumb2))
+        rust_add_target_info("target_feature", "thumb2");
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_armv4)
+        && bitmap_bit_p(arm_active_target.isa, isa_bit_notm)
+        && bitmap_bit_p(arm_active_target.isa, isa_bit_thumb)) {
+        rust_add_target_info("target_feature", "v4t");
+
+        if (bitmap_bit_p(arm_active_target.isa, isa_bit_armv5t)) {
+            rust_add_target_info("target_feature", "v5t");
+
+            if (bitmap_bit_p(arm_active_target.isa, isa_bit_armv5te)) {
+                rust_add_target_info("target_feature", "v5te");
+
+                if (bitmap_bit_p(arm_active_target.isa, isa_bit_armv6)
+                    && bitmap_bit_p(arm_active_target.isa, isa_bit_be8)) {
+                    rust_add_target_info("target_feature", "v6");
+
+                    // note: this definition of "ARMv6m" listed as "suspect" in arm-cpus.in
+                    rust_add_target_info("target_feature", "v6m");
+
+                    bool hasV8BaselineOps = bitmap_bit_p(arm_active_target.isa, isa_bit_armv8)
+                                            && bitmap_bit_p(arm_active_target.isa, isa_bit_cmse)
+                                            && bitmap_bit_p(arm_active_target.isa, isa_bit_tdiv);
+                    if (hasV8BaselineOps)
+                        rust_add_target_info("target_feature", "v8m");
+
+                    bool hasV6kOps = bitmap_bit_p(arm_active_target.isa, isa_bit_armv6k);
+                    if (hasV6kOps) {
+                        rust_add_target_info("target_feature", "v6k");
+                    }
+
+                    if (bitmap_bit_p(arm_active_target.isa, isa_bit_thumb2) && hasV8BaselineOps
+                        && hasV6kOps) {
+                        rust_add_target_info("target_feature", "v6t2");
+
+                        // note that arm-cpus.in refers to this (ARMv7) as suspect
+                        if (bitmap_bit_p(arm_active_target.isa, isa_bit_armv7)) {
+                            rust_add_target_info("target_feature", "v7");
+
+                            rust_add_target_info("target_feature", "v8m.main");
+
+                            if (bitmap_bit_p(arm_active_target.isa, isa_bit_armv8_1m_main))
+                                rust_add_target_info("target_feature", "v8.1m.main");
+
+                            // dummy: can't find feature acquire-release, so dummy true variable
+                            bool hasAcquireRelease = true;
+                            if (hasAcquireRelease && bitmap_bit_p(arm_active_target.isa, isa_bit_adiv)
+                                && bitmap_bit_p(arm_active_target.isa, isa_bit_lpae)
+                                && bitmap_bit_p(arm_active_target.isa, isa_bit_mp)
+                                && bitmap_bit_p(arm_active_target.isa, isa_bit_sec)) {
+                                rust_add_target_info("target_feature", "v8");
+
+                                if (TARGET_CRC32
+                                    && bitmap_bit_p(arm_active_target.isa, isa_bit_armv8_1)) {
+                                    rust_add_target_info("target_feature", "v8.1a");
+
+                                    if (bitmap_bit_p(arm_active_target.isa, isa_bit_armv8_2)) {
+                                        rust_add_target_info("target_feature", "v8.2a");
+
+                                        if (bitmap_bit_p(arm_active_target.isa, isa_bit_armv8_3)) {
+                                            rust_add_target_info("target_feature", "v8.3a");
+
+                                            if (bitmap_bit_p(
+                                                  arm_active_target.isa, isa_bit_armv8_4)) {
+                                                rust_add_target_info("target_feature", "v8.4a");
+                                                // note: llvm, but not gcc, also wants dotprod for
+                                                // v8.4
+
+                                                if (bitmap_bit_p(arm_active_target.isa, isa_bit_sb)
+                                                    && bitmap_bit_p(
+                                                      arm_active_target.isa, isa_bit_predres)
+                                                    && bitmap_bit_p(
+                                                      arm_active_target.isa, isa_bit_armv8_5)) {
+                                                    rust_add_target_info("target_feature", "v8.5a");
+
+                                                    if (bitmap_bit_p(
+                                                          arm_active_target.isa, isa_bit_armv8_6))
+                                                        rust_add_target_info(
+                                                          "target_feature", "v8.6a");
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_mve)
+        && bitmap_bit_p(arm_active_target.isa, isa_bit_vfp_base)
+        && bitmap_bit_p(arm_active_target.isa, isa_bit_armv7em)) {
+        rust_add_target_info("target_feature", "mve");
+
+        if (minFP_ARMv8 && bitmap_bit_p(arm_active_target.isa, isa_bit_fp16)
+            && bitmap_bit_p(arm_active_target.isa, isa_bit_mve_float))
+            rust_add_target_info("target_feature", "mve.fp");
+    }
+    // Note: no direct option for "cde" found, but it is implicitly activated via cdecpx, so do it
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_cdecp0)) {
+        rust_add_target_info("target_feature", "cdecp0");
+        rust_add_target_info("target_feature", "cde");
+    }
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_cdecp1)) {
+        rust_add_target_info("target_feature", "cdecp1");
+        rust_add_target_info("target_feature", "cde");
+    }
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_cdecp2)) {
+        rust_add_target_info("target_feature", "cdecp2");
+        rust_add_target_info("target_feature", "cde");
+    }
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_cdecp3)) {
+        rust_add_target_info("target_feature", "cdecp3");
+        rust_add_target_info("target_feature", "cde");
+    }
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_cdecp4)) {
+        rust_add_target_info("target_feature", "cdecp4");
+        rust_add_target_info("target_feature", "cde");
+    }
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_cdecp5)) {
+        rust_add_target_info("target_feature", "cdecp5");
+        rust_add_target_info("target_feature", "cde");
+    }
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_cdecp6)) {
+        rust_add_target_info("target_feature", "cdecp6");
+        rust_add_target_info("target_feature", "cde");
+    }
+    if (bitmap_bit_p(arm_active_target.isa, isa_bit_cdecp7)) {
+        rust_add_target_info("target_feature", "cdecp7");
+        rust_add_target_info("target_feature", "cde");
+    }
+    if (TARGET_SOFT_FLOAT)
+        rust_add_target_info("target_feature", "soft-float");
+    // should be correct option (i.e. thumb mode rather than just thumb-aware) as TARGET_ARM is
+    // inverse
+    if (TARGET_THUMB)
+        rust_add_target_info("target_feature", "thumb-mode");
+    // TODO: consider doing the processors as target features, but honestly they don't seem to fit
+}
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index f479540812a..abaec9e71e6 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -51,6 +51,9 @@ extern char arm_arch_name[];
 #define TARGET_D_CPU_VERSIONS arm_d_target_versions
 #define TARGET_D_REGISTER_CPU_TARGET_INFO arm_d_register_target_info
 
+/* Target CPU info for Rust.  */
+#define TARGET_RUST_CPU_INFO arm_rust_target_cpu_info
+
 #include "config/arm/arm-opts.h"
 
 /* The processor for which instructions should be scheduled.  */
diff --git a/gcc/config/arm/bpabi.h b/gcc/config/arm/bpabi.h
index 70984ddd147..0df5dd0f31a 100644
--- a/gcc/config/arm/bpabi.h
+++ b/gcc/config/arm/bpabi.h
@@ -104,6 +104,17 @@
 #define TARGET_OS_CPP_BUILTINS() \
   TARGET_BPABI_CPP_BUILTINS()
 
+#define BPABI_TARGET_RUST_OS_INFO() \
+  do { \
+    /*TODO: is this even an OS? What should go here?*/ \
+  } while (0)
+
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in bpabi.h - c++ undefines it and redefines it."
+#endif
+#define TARGET_RUST_OS_INFO() \
+  BPABI_TARGET_RUST_OS_INFO()
+
 /* The BPABI specifies the use of .{init,fini}_array.  Therefore, we
    do not want GCC to put anything into the .{init,fini} sections.  */
 #undef INIT_SECTION_ASM_OP
diff --git a/gcc/config/arm/freebsd.h b/gcc/config/arm/freebsd.h
index 2bd0dc97df3..d662ab005d6 100644
--- a/gcc/config/arm/freebsd.h
+++ b/gcc/config/arm/freebsd.h
@@ -83,6 +83,15 @@
     }						\
   while (false)
 
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in freebsd.h (arm) - c++ undefines it and redefines it."
+#endif
+#define TARGET_RUST_OS_INFO() 		\
+  do {						\
+    FBSD_TARGET_RUST_OS_INFO ();		\
+    BPABI_TARGET_RUST_OS_INFO ();		\
+  } while (0)
+
 /* We default to a soft-float ABI so that binaries can run on all
    target hardware.  */
 #undef TARGET_DEFAULT_FLOAT_ABI
diff --git a/gcc/config/arm/linux-eabi.h b/gcc/config/arm/linux-eabi.h
index 50cc0bc6d08..a255ac0f1a7 100644
--- a/gcc/config/arm/linux-eabi.h
+++ b/gcc/config/arm/linux-eabi.h
@@ -33,6 +33,14 @@
 #define EXTRA_TARGET_D_OS_VERSIONS()		\
   ANDROID_TARGET_D_OS_VERSIONS();
 
+#define EXTRA_TARGET_RUST_OS_INFO()		\
+  do { 						\
+    BPABI_TARGET_RUST_OS_INFO();		\
+    GNU_USER_TARGET_RUST_OS_INFO();		\
+    ANDROID_TARGET_RUST_OS_INFO();		\
+    /*TODO: ensure that this makes target_os 'linux' properly and stuff*/ \
+  while (0)
+
 /* We default to a soft-float ABI so that binaries can run on all
    target hardware.  If you override this to use the hard-float ABI then
    change the setting of GLIBC_DYNAMIC_LINKER_DEFAULT as well.  */
diff --git a/gcc/config/arm/linux-elf.h b/gcc/config/arm/linux-elf.h
index df3da67c4f0..0859945ed05 100644
--- a/gcc/config/arm/linux-elf.h
+++ b/gcc/config/arm/linux-elf.h
@@ -83,6 +83,11 @@
     }						\
   while (0)
 
+#define TARGET_RUST_OS_INFO()		\
+   do {						\
+	   GNU_USER_TARGET_RUST_OS_INFO();	\
+   } while (0)
+
 /* Call the function profiler with a given profile label.  */
 #undef  ARM_FUNCTION_PROFILER
 #define ARM_FUNCTION_PROFILER(STREAM, LABELNO)  			\
diff --git a/gcc/config/arm/netbsd-eabi.h b/gcc/config/arm/netbsd-eabi.h
index c85fcd3e385..a47b2ca3776 100644
--- a/gcc/config/arm/netbsd-eabi.h
+++ b/gcc/config/arm/netbsd-eabi.h
@@ -64,6 +64,16 @@
     }						\
   while (0)
 
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in netbsd-eabi.h (arm) - c++ undefines it and redefines it."
+#endif
+#define TARGET_RUST_OS_INFO()		\
+  do {						\
+  	if (TARGET_AAPCS_BASED)			\
+      BPABI_TARGET_RUST_OS_INFO();		\
+    NETBSD_TARGET_RUST_OS_INFO();		\
+  } while (0)
+
 #undef SUBTARGET_CPP_SPEC
 #define SUBTARGET_CPP_SPEC NETBSD_CPP_SPEC
 
diff --git a/gcc/config/arm/netbsd-elf.h b/gcc/config/arm/netbsd-elf.h
index d239c734c5c..e74cdcc6503 100644
--- a/gcc/config/arm/netbsd-elf.h
+++ b/gcc/config/arm/netbsd-elf.h
@@ -51,6 +51,14 @@
     }					\
   while (0)
 
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in netbsd-elf.h (arm) - c++ undefines it and redefines it."
+#endif
+#define TARGET_RUST_OS_INFO()	\
+  do {					\
+    NETBSD_TARGET_RUST_OS_INFO();	\
+  } while (0)
+
 #undef SUBTARGET_CPP_SPEC
 #define SUBTARGET_CPP_SPEC NETBSD_CPP_SPEC
 
diff --git a/gcc/config/arm/rtems.h b/gcc/config/arm/rtems.h
index a569343451a..56f978bf73e 100644
--- a/gcc/config/arm/rtems.h
+++ b/gcc/config/arm/rtems.h
@@ -33,4 +33,18 @@
 	TARGET_BPABI_CPP_BUILTINS();    	\
     } while (0)
 
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in rtems.h (arm) - c++ undefines it and redefines it."
+#endif
+#define TARGET_RUST_OS_INFO()		\
+  do {					\
+    /*note: as far as I know, rustc has no supported for rtems, so this is just guessed*/ \
+    /*everything is subject to change, especially target_env and target_family - TODO*/ \
+    builtin_rust_info ("target_family", "unix");	\
+    builtin_rust_info ("target_os", "rtems");	\
+    builtin_rust_info ("target_vendor", "unknown");	\
+    builtin_rust_info ("target_env", "");	\
+    BPABI_TARGET_RUST_OS_INFO();	\
+  } while (0)
+
 #define ARM_DEFAULT_SHORT_ENUMS false
diff --git a/gcc/config/arm/symbian.h b/gcc/config/arm/symbian.h
index 7df39170180..81c7cc00a27 100644
--- a/gcc/config/arm/symbian.h
+++ b/gcc/config/arm/symbian.h
@@ -78,6 +78,21 @@
     }								\
   while (false)
 
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in symbian.h (arm) - c++ undefines it and redefines it."
+#endif
+#define TARGET_RUST_OS_INFO()		\
+  do {					\
+    /*note: as far as I know, rustc has no supported for symbian, so this is just guessed*/ \
+    /*everything is subject to change, especially target_env and target_vendor - TODO*/ \
+    /*some triple examples i've seen are "arm-nokia-symbian-eabi" and possibly "arm-none-symbian-elf"*/ \
+    builtin_rust_info ("target_family", "");	\
+    builtin_rust_info ("target_os", "symbian");	\
+    builtin_rust_info ("target_vendor", "unknown");	\
+    builtin_rust_info ("target_env", "");	\
+    BPABI_TARGET_RUST_OS_INFO();	\
+  } while (0)
+
 /* On SymbianOS, these sections are not writable, so we use "a",
    rather than "aw", for the section attributes.  */
 #undef ARM_EABI_CTORS_SECTION_OP
diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm
index 041cc6ec045..d093f3c789c 100644
--- a/gcc/config/arm/t-arm
+++ b/gcc/config/arm/t-arm
@@ -172,6 +172,10 @@ arm-d.o: $(srcdir)/config/arm/arm-d.cc
 	$(COMPILE) $<
 	$(POSTCOMPILE)
 
+arm-rust.o: $(srcdir)/config/arm/arm-rust.cc
+	$(COMPILE) $<
+	$(POSTCOMPILE)
+
 arm-common.o: arm-cpu-cdata.h
 
 driver-arm.o: arm-native.h
diff --git a/gcc/config/arm/uclinux-eabi.h b/gcc/config/arm/uclinux-eabi.h
index 362d2b5ebd8..54bf78cdc0d 100644
--- a/gcc/config/arm/uclinux-eabi.h
+++ b/gcc/config/arm/uclinux-eabi.h
@@ -46,6 +46,19 @@
     }						\
   while (false)
 
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in uclinux-eabi.h (arm) - c++ undefines it and redefines it."
+#endif
+#define TARGET_RUST_OS_INFO()		\
+  do {					\
+    BPABI_TARGET_RUST_OS_INFO();	\
+    /*note: as far as I know, rustc does not distinguish between uclinux and regular linux kernels*/ \
+    builtin_rust_info ("target_family", "unix");	   \
+    builtin_rust_info ("target_os", "linux");	      \
+    builtin_rust_info ("target_vendor", "unknown");	\
+    builtin_rust_info ("target_env", "gnu");	         \
+  } while (0)
+
 #undef SUBTARGET_EXTRA_LINK_SPEC
 #define SUBTARGET_EXTRA_LINK_SPEC " -m armelf_linux_eabi -elf2flt" \
   " --pic-veneer --target2=abs"
diff --git a/gcc/config/arm/uclinux-elf.h b/gcc/config/arm/uclinux-elf.h
index 921440d49bd..3fcaf2d6acb 100644
--- a/gcc/config/arm/uclinux-elf.h
+++ b/gcc/config/arm/uclinux-elf.h
@@ -48,6 +48,18 @@
     }						\
   while (false)
 
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in uclinux-elf.h (arm) - c++ undefines it and redefines it."
+#endif
+#define TARGET_RUST_OS_INFO()		\
+  do {					\
+    /*note: as far as I know, rustc does not distinguish between uclinux and regular linux kernels*/ \
+    builtin_rust_info ("target_family", "unix");	   \
+    builtin_rust_info ("target_os", "linux");	      \
+    builtin_rust_info ("target_vendor", "unknown");	\
+    builtin_rust_info ("target_env", "gnu");	         \
+  } while (0)
+
 /* The GNU C++ standard library requires that these macros be defined.  */
 #undef CPLUSPLUS_CPP_SPEC
 #define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
diff --git a/gcc/config/arm/vxworks.h b/gcc/config/arm/vxworks.h
index 2bcd01edc97..0d4989cb52a 100644
--- a/gcc/config/arm/vxworks.h
+++ b/gcc/config/arm/vxworks.h
@@ -75,6 +75,20 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     MAYBE_TARGET_BPABI_CPP_BUILTINS ();			\
   } while (0)
 
+#ifdef TARGET_RUST_OS_INFO
+# error "TARGET_RUST_OS_INFO already defined in vxworks.h (arm) - c++ undefines it and redefines it."
+#endif
+#ifdef BPABI_TARGET_RUST_OS_INFO
+# define MAYBE_BPABI_TARGET_RUST_OS_INFO BPABI_TARGET_RUST_OS_INFO
+#else
+# define MAYBE_BPABI_TARGET_RUST_OS_INFO()
+#endif
+#define TARGET_RUST_OS_INFO()			\
+  do {			\
+    VXWORKS_TARGET_RUST_OS_INFO ();			\
+    MAYBE_BPABI_TARGET_RUST_OS_INFO ();			\
+  } while (0)
+
 #undef SUBTARGET_OVERRIDE_OPTIONS
 #define SUBTARGET_OVERRIDE_OPTIONS VXWORKS_OVERRIDE_OPTIONS
 
