{"thread":{"id":"4102","subject":"[PATCH] improve base85 generated assembly code","startedAt":"2006-05-08T15:31:11Z","lastAt":"2006-05-08T15:31:11Z","messageCount":1,"participants":["Nicolas Pitre"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"19715","messageId":"Pine.LNX.4.64.0605081010150.24505@localhost.localdomain","threadId":"4102","inReplyTo":null,"subject":"[PATCH] improve base85 generated assembly code","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2006-05-08T15:31:11Z","receivedAt":"2006-05-08T15:31:11Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"This code is arguably pretty hot, if you use binary patches of course. \nThis patch helps gcc generate both smaller and faster code especially in \nthe error free path.\n\nSigned-off-by: Nicolas Pitre <nico@cam.org>\n\n---\n\ndiff --git a/base85.c b/base85.c\nindex b97f7f9..a9e97f8 100644\n--- a/base85.c\n+++ b/base85.c\n@@ -44,34 +44,38 @@ int decode_85(char *dst, char *buffer, i\n \tsay2(\"decode 85 <%.*s>\", len/4*5, buffer);\n \twhile (len) {\n \t\tunsigned acc = 0;\n-\t\tint cnt;\n-\t\tfor (cnt = 0; cnt < 5; cnt++, buffer++) {\n-\t\t\tint ch = *((unsigned char *)buffer);\n-\t\t\tint de = de85[ch];\n-\t\t\tif (!de)\n+\t\tint de, cnt = 4;\n+\t\tunsigned char ch;\n+\t\tdo {\n+\t\t\tch = *buffer++;\n+\t\t\tde = de85[ch];\n+\t\t\tif (--de < 0)\n \t\t\t\treturn error(\"invalid base85 alphabet %c\", ch);\n-\t\t\tde--;\n-\t\t\tif (cnt == 4) {\n-\t\t\t\t/*\n-\t\t\t\t * Detect overflow.  The largest\n-\t\t\t\t * 5-letter possible is \"|NsC0\" to\n-\t\t\t\t * encode 0xffffffff, and \"|NsC\" gives\n-\t\t\t\t * 0x03030303 at this point (i.e.\n-\t\t\t\t * 0xffffffff = 0x03030303 * 85).\n-\t\t\t\t */\n-\t\t\t\tif (0x03030303 < acc ||\n-\t\t\t\t    (0x03030303 == acc && de))\n-\t\t\t\t\terror(\"invalid base85 sequence %.5s\",\n-\t\t\t\t\t      buffer-3);\n-\t\t\t}\n \t\t\tacc = acc * 85 + de;\n-\t\t\tsay1(\" <%08x>\", acc);\n-\t\t}\n+\t\t} while (--cnt);\n+\t\tch = *buffer++;\n+\t\tde = de85[ch];\n+\t\tif (--de < 0)\n+\t\t\treturn error(\"invalid base85 alphabet %c\", ch);\n+\t\t/*\n+\t\t * Detect overflow.  The largest\n+\t\t * 5-letter possible is \"|NsC0\" to\n+\t\t * encode 0xffffffff, and \"|NsC\" gives\n+\t\t * 0x03030303 at this point (i.e.\n+\t\t * 0xffffffff = 0x03030303 * 85).\n+\t\t */\n+\t\tif (0x03030303 < acc ||\n+\t\t    0xffffffff - de < (acc *= 85))\n+\t\t\terror(\"invalid base85 sequence %.5s\", buffer-5);\n+\t\tacc += de;\n \t\tsay1(\" %08x\", acc);\n-\t\tfor (cnt = 0; cnt < 4 && len; cnt++, len--) {\n-\t\t\t*dst++ = (acc >> 24) & 0xff;\n-\t\t\tacc = acc << 8;\n-\t\t}\n+\n+\t\tcnt = (len < 4) ? len : 4;\n+\t\tlen -= cnt;\n+\t\tdo {\n+\t\t\tacc = (acc << 8) | (acc >> 24);\n+\t\t\t*dst++ = acc;\n+\t\t} while (--cnt);\n \t}\n \tsay(\"\\n\");\n \n@@ -86,15 +90,17 @@ void encode_85(char *buf, unsigned char \n \twhile (bytes) {\n \t\tunsigned acc = 0;\n \t\tint cnt;\n-\t\tfor (cnt = 0; cnt < 4 && bytes; cnt++, bytes--) {\n+\t\tfor (cnt = 24; cnt >= 0; cnt -= 8) {\n \t\t\tint ch = *data++;\n-\t\t\tacc |= ch << ((3-cnt)*8);\n+\t\t\tacc |= ch << cnt;\n+\t\t\tif (--bytes == 0)\n+\t\t\t\tbreak;\n \t\t}\n \t\tsay1(\" %08x\", acc);\n-\t\tfor (cnt = 0; cnt < 5; cnt++) {\n+\t\tfor (cnt = 4; cnt >= 0; cnt--) {\n \t\t\tint val = acc % 85;\n \t\t\tacc /= 85;\n-\t\t\tbuf[4-cnt] = en85[val];\n+\t\t\tbuf[cnt] = en85[val];\n \t\t}\n \t\tbuf += 5;\n \t}\n"}]}