path: root/block-sha1/sha1.c
diff options
authorNicolas Pitre <>2009-08-12 19:46:41 (GMT)
committerJunio C Hamano <>2009-08-12 20:35:54 (GMT)
commitdc52fd29738c2af98f3e986691eca34addfd4914 (patch)
tree89cb72a4bdaa2a152022e1eece078c5a07558fb5 /block-sha1/sha1.c
parent30ba0de726d92ccfc93009eb60f2c30b0886f61b (diff)
block-sha1: split the different "hacks" to be individually selected
This is to make it easier for them to be selected individually depending on the architecture instead of the other way around i.e. having each architecture select a list of hacks up front. That makes for clearer documentation as well. Signed-off-by: Nicolas Pitre <> Signed-off-by: Junio C Hamano <>
Diffstat (limited to 'block-sha1/sha1.c')
1 files changed, 18 insertions, 5 deletions
diff --git a/block-sha1/sha1.c b/block-sha1/sha1.c
index c3f1ae5..67c9bd0 100644
--- a/block-sha1/sha1.c
+++ b/block-sha1/sha1.c
@@ -11,10 +11,16 @@
#if defined(__i386__) || defined(__x86_64__)
+ * Force usage of rol or ror by selecting the one with the smaller constant.
+ * It _can_ generate slightly smaller code (a constant of 1 is special), but
+ * perhaps more importantly it's possibly faster on any uarch that does a
+ * rotate with a loop.
+ */
#define SHA_ASM(op, x, n) ({ unsigned int __res; __asm__(op " %1,%0":"=r" (__res):"i" (n), "0" (x)); __res; })
#define SHA_ROL(x,n) SHA_ASM("rol", x, n)
#define SHA_ROR(x,n) SHA_ASM("ror", x, n)
@@ -24,9 +30,6 @@
-/* This "rolls" over the 512-bit array */
-#define W(x) (array[(x)&15])
* If you have 32 registers or more, the compiler can (and should)
* try to change the array[] accesses into registers. However, on
@@ -43,13 +46,23 @@
* Ben Herrenschmidt reports that on PPC, the C version comes close
* to the optimized asm with this (ie on PPC you don't want that
* 'volatile', since there are lots of registers).
+ *
+ * On ARM we get the best code generation by forcing a full memory barrier
+ * between each SHA_ROUND, otherwise gcc happily get wild with spilling and
+ * the stack frame size simply explode and performance goes down the drain.
+#if defined(__i386__) || defined(__x86_64__)
#define setW(x, val) (*(volatile unsigned int *)&W(x) = (val))
+#elif defined(__arm__)
+ #define setW(x, val) do { W(x) = (val); __asm__("":::"memory"); } while (0)
#define setW(x, val) (W(x) = (val))
+/* This "rolls" over the 512-bit array */
+#define W(x) (array[(x)&15])
* Where do we get the source from? The first 16 iterations get it from
* the input data, the next mix it from the 512-bit array.