diff --git a/ChangeLog b/ChangeLog
index 03be20185814f6641b2d43b9453743934cfa4e1e..3739dd6e4e16c74194d0823bc9e472ee1cc941be 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2015-01-19  Niels Möller  <nisse@lysator.liu.se>
 
+	* configure.ac: Fat library setup for arm.
+	* fat-arm.c: New file.
+	* arm/fat/aes-encrypt-internal.asm: New files.
+	* arm/fat/aes-encrypt-internal-2.asm: New file.
+	* arm/fat/aes-decrypt-internal.asm: New file.
+	* arm/fat/aes-decrypt-internal-2.asm: New file.
+
 	* Makefile.in (DISTFILES): Added fat-setup.h.
 
 	* fat-setup.h: New file, declarations moved from...
diff --git a/arm/fat/aes-decrypt-internal-2.asm b/arm/fat/aes-decrypt-internal-2.asm
new file mode 100644
index 0000000000000000000000000000000000000000..2110f310f583ee17759aaaa822fc40eb510b9d0e
--- /dev/null
+++ b/arm/fat/aes-decrypt-internal-2.asm
@@ -0,0 +1,35 @@
+C arm/fat/aes-decrypt-internal-2.asm
+
+
+ifelse(<
+   Copyright (C) 2015 Niels Möller
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+>)
+
+define(<fat_transform>, <$1_armv6>)
+include_src(<arm/v6/aes-decrypt-internal.asm>)
diff --git a/arm/fat/aes-decrypt-internal.asm b/arm/fat/aes-decrypt-internal.asm
new file mode 100644
index 0000000000000000000000000000000000000000..8d76388958ef29e79169bf6b41ba1c72fbd86f7e
--- /dev/null
+++ b/arm/fat/aes-decrypt-internal.asm
@@ -0,0 +1,35 @@
+C arm/fat/aes-decrypt-internal.asm
+
+
+ifelse(<
+   Copyright (C) 2015 Niels Möller
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+>)
+
+define(<fat_transform>, <$1_arm>)
+include_src(<arm/aes-decrypt-internal.asm>)
diff --git a/arm/fat/aes-encrypt-internal-2.asm b/arm/fat/aes-encrypt-internal-2.asm
new file mode 100644
index 0000000000000000000000000000000000000000..490a52bec6225f7b9f70a54ac61adfec9a710df2
--- /dev/null
+++ b/arm/fat/aes-encrypt-internal-2.asm
@@ -0,0 +1,35 @@
+C arm/fat/aes-encrypt-internal-2.asm
+
+
+ifelse(<
+   Copyright (C) 2015 Niels Möller
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+>)
+
+define(<fat_transform>, <$1_armv6>)
+include_src(<arm/v6/aes-encrypt-internal.asm>)
diff --git a/arm/fat/aes-encrypt-internal.asm b/arm/fat/aes-encrypt-internal.asm
new file mode 100644
index 0000000000000000000000000000000000000000..e695a2895e13d92175aa462fa26c4903860b7cde
--- /dev/null
+++ b/arm/fat/aes-encrypt-internal.asm
@@ -0,0 +1,35 @@
+C arm/fat/aes-encrypt-internal.asm
+
+
+ifelse(<
+   Copyright (C) 2015 Niels Möller
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+>)
+
+define(<fat_transform>, <$1_arm>)
+include_src(<arm/aes-encrypt-internal.asm>)
diff --git a/configure.ac b/configure.ac
index 2ebdb0b0aa44711dcfe82b571bd08db012512fc2..4c0f31575219650c6771038602c6389a2da5857f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -267,18 +267,25 @@ if test "x$enable_assembler" = xyes ; then
 	asm_path=sparc32
       fi
       ;;
-    armv6* | armv7*)
-      NETTLE_CHECK_ARM_NEON
+    arm*)
+      asm_path=arm
+      if test "x$enable_fat" = xyes ; then
+	asm_path="arm/fat $asm_path"
+	OPT_NETTLE_SOURCES="fat-arm.c $OPT_NETTLE_SOURCES"
+      else
+	case "$host_cpu" in
+	  armv6* | armv7*)
+	    NETTLE_CHECK_ARM_NEON
 
-      asm_path="arm/v6 arm"
+	    asm_path="arm/v6 arm"
       
-      if test "x$enable_arm_neon" = xyes ; then
-	asm_path="arm/neon $asm_path"
+	    if test "x$enable_arm_neon" = xyes ; then
+	      asm_path="arm/neon $asm_path"
+	    fi
+	    ;;
+	esac
       fi
       ;;
-    arm*)
-      asm_path=arm
-      ;;
     *)
       enable_assembler=no
       ;;
diff --git a/fat-arm.c b/fat-arm.c
new file mode 100644
index 0000000000000000000000000000000000000000..9ddf582f09c6708f50951dfa14a1381eb52ac1cd
--- /dev/null
+++ b/fat-arm.c
@@ -0,0 +1,164 @@
+/* fat-arm.c
+
+   Copyright (C) 2015 Niels Möller
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle 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 copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "nettle-types.h"
+
+#include "aes-internal.h"
+#include "fat-setup.h"
+
+struct arm_features
+{
+  /* /proc/cpuinfo "CPU Architecture" doesn't correspond exactly to
+     ARM architecture version, but it's good enough for our purposes.
+     Will be set to 5, 6, 7 or 8. */
+  unsigned arch_version;
+  int have_neon;
+};
+
+static void
+get_arm_features (struct arm_features *features)
+{
+  FILE *f;
+  char line[200];
+  int seen_arch = 0;
+  int seen_features = 0;
+
+  features->arch_version = 5;
+  features->have_neon = 0;
+
+  f = fopen ("/proc/cpuinfo", "r");
+  if (!f)
+    return;
+  while (seen_features + seen_arch < 2
+	 && fgets (line, sizeof(line), f))
+    {
+      char *sep;
+      char *p;
+      sep = strchr (line, ':');
+      if (!sep)
+	continue;
+      for (p = sep; p - line > 0 && p[-1] == '\t'; p--)
+	;
+
+      *p = '\0';
+      p = sep+1;
+
+      if (strcmp (line, "Features") == 0)
+	{
+	  features->have_neon = (strstr (p, " neon ") != NULL);
+	  seen_features = 1;
+	}
+      else if (strcmp (line, "CPU architecture") == 0)
+	{
+	  /* Don't use strtol, since it's locale dependent. */
+	  while (p[0] == ' ')
+	    p++;
+	  if (p[0] > '5' && p[0] <= '9')
+	    features->arch_version = p[0] - '0';
+	  else if (strcmp (p, "AArch64") == 0)
+	    features->arch_version = 8;
+	  seen_arch = 1;	  
+	}
+    }
+  if (features->arch_version >= 8)
+    {
+      /* Neon is not required, and maybe not listed in feature flags */
+      features->have_neon = 1;
+    }
+  fclose (f);
+}
+
+DECLARE_FAT_FUNC(_nettle_aes_encrypt, aes_crypt_internal_func)
+DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, arm)
+DECLARE_FAT_FUNC_VAR(aes_encrypt, aes_crypt_internal_func, armv6)
+
+DECLARE_FAT_FUNC(_nettle_aes_decrypt, aes_crypt_internal_func)
+DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, arm)
+DECLARE_FAT_FUNC_VAR(aes_decrypt, aes_crypt_internal_func, armv6)
+
+static void CONSTRUCTOR
+fat_init (void)
+{
+  static volatile int initialized = 0;
+  struct arm_features features;
+  int verbose;
+
+  if (initialized)
+    return;
+
+  get_arm_features (&features);
+
+  verbose = getenv (ENV_VERBOSE) != NULL;
+  if (verbose)
+    fprintf (stderr,
+	     "libnettle: cpu arch: %u, neon: %s\n",
+	     features.arch_version, features.have_neon ? "yes" : "no");
+
+  if (features.arch_version >= 6)
+    {
+      if (verbose)
+	fprintf (stderr, "libnettle: enabling armv6 code.\n");
+      _nettle_aes_encrypt_vec = _nettle_aes_encrypt_armv6;
+      _nettle_aes_decrypt_vec = _nettle_aes_decrypt_armv6;
+    }
+  else
+    {
+      if (verbose)
+	fprintf (stderr, "libnettle: not enabling armv6 code.\n");
+      _nettle_aes_encrypt_vec = _nettle_aes_encrypt_arm;
+      _nettle_aes_decrypt_vec = _nettle_aes_decrypt_arm;
+    }
+  /* FIXME: Needs memory barrier, to enforce store ordering. */
+  initialized = 1;
+}
+  
+DEFINE_FAT_FUNC(_nettle_aes_encrypt, void,
+		(unsigned rounds, const uint32_t *keys,
+		 const struct aes_table *T,
+		 size_t length, uint8_t *dst,
+		 const uint8_t *src),
+		(rounds, keys, T, length, dst, src))
+
+DEFINE_FAT_FUNC(_nettle_aes_decrypt, void,
+		(unsigned rounds, const uint32_t *keys,
+		 const struct aes_table *T,
+		 size_t length, uint8_t *dst,
+		 const uint8_t *src),
+		(rounds, keys, T, length, dst, src))