Added "ctmulq" implementation of Poly1305 (using 64->128 multiplications when available).
[BearSSL] / T0 / T0Comp.cs
index 143badb..7a397f7 100644 (file)
@@ -251,6 +251,12 @@ public class T0Comp {
         */
        List<string> extraCode;
 
+       /*
+        * 'extraCodeDefer' is for C code that is to be added in the C
+        * output _after_ the data and code blocks.
+        */
+       List<string> extraCodeDefer;
+
        /*
         * 'dataBlock' is the data block in which constant data bytes
         * are accumulated.
@@ -287,6 +293,7 @@ public class T0Comp {
                        StringComparer.Ordinal);
                compiling = false;
                extraCode = new List<string>();
+               extraCodeDefer = new List<string>();
                enableFlowAnalysis = true;
 
                /*
@@ -348,6 +355,15 @@ public class T0Comp {
                        extraCode.Add(ParseCCode());
                });
 
+               /*
+                * postamble
+                * Parses a C code snippet, then adds it to the generated
+                * output after the data and code blocks.
+                */
+               AddNative("postamble", false, SType.BLANK, cpu => {
+                       extraCodeDefer.Add(ParseCCode());
+               });
+
                /*
                 * make-CX
                 * Expects two integers and a string, and makes a
@@ -1626,6 +1642,20 @@ public class T0Comp {
                }
                CodeElement[] gcode = gcodeList.ToArray();
 
+               /*
+                * If there are less than 256 words in total (C +
+                * interpreted) then we can use "one-byte code" which is
+                * more compact when the number of words is in the
+                * 128..255 range.
+                */
+               bool oneByteCode;
+               if (slotInterpreted + numInterpreted >= 256) {
+                       Console.WriteLine("WARNING: more than 255 words");
+                       oneByteCode = false;
+               } else {
+                       oneByteCode = true;
+               }
+
                /*
                 * Compute all addresses and offsets. This loops until
                 * the addresses stabilize.
@@ -1634,7 +1664,7 @@ public class T0Comp {
                int[] gcodeLen = new int[gcode.Length];
                for (;;) {
                        for (int i = 0; i < gcode.Length; i ++) {
-                               gcodeLen[i] = gcode[i].Length;
+                               gcodeLen[i] = gcode[i].GetLength(oneByteCode);
                        }
                        int off = 0;
                        for (int i = 0; i < gcode.Length; i ++) {
@@ -1715,7 +1745,7 @@ t0_parse7E_signed(const unsigned char **p)
 #define T0_INT4(x)       T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
 #define T0_INT5(x)       T0_SBYTE(x), T0_VBYTE(x, 21), T0_VBYTE(x, 14), T0_VBYTE(x, 7), T0_FBYTE(x, 0)
 
-static const uint8_t t0_datablock[];
+/* static const unsigned char t0_datablock[]; */
 ");
 
                        /*
@@ -1743,7 +1773,8 @@ static const uint8_t t0_datablock[];
 
                        BlobWriter bw;
                        tw.WriteLine();
-                       tw.Write("static const uint8_t t0_datablock[] = {");
+                       tw.Write("static const unsigned char"
+                               + " t0_datablock[] = {");
                        bw = new BlobWriter(tw, 78, 1);
                        bw.Append((byte)0);
                        foreach (ConstData cd in blocks.Values) {
@@ -1753,10 +1784,11 @@ static const uint8_t t0_datablock[];
                        tw.WriteLine("};");
 
                        tw.WriteLine();
-                       tw.Write("static const uint8_t t0_codeblock[] = {");
+                       tw.Write("static const unsigned char"
+                               + " t0_codeblock[] = {");
                        bw = new BlobWriter(tw, 78, 1);
                        foreach (CodeElement ce in gcode) {
-                               ce.Encode(bw);
+                               ce.Encode(bw, oneByteCode);
                        }
                        tw.WriteLine();
                        tw.WriteLine("};");
@@ -1805,6 +1837,14 @@ name(void *ctx) \
                                        wordSet[ep].Slot);
                        }
                        tw.WriteLine();
+                       if (oneByteCode) {
+                               tw.WriteLine("{0}",
+@"#define T0_NEXT(t0ipp)   (*(*(t0ipp)) ++)");
+                       } else {
+                               tw.WriteLine("{0}",
+@"#define T0_NEXT(t0ipp)   t0_parse7E_unsigned(t0ipp)");
+                       }
+                       tw.WriteLine();
                        tw.WriteLine("void");
                        tw.WriteLine("{0}_run(void *t0ctx)", coreRun);
                        tw.WriteLine("{0}",
@@ -1853,15 +1893,17 @@ name(void *ctx) \
 #define T0_CO()         do { \
        goto t0_exit; \
 } while (0)
-#define T0_RET()        break
+#define T0_RET()        goto t0_next
 
        dp = ((t0_context *)t0ctx)->dp;
        rp = ((t0_context *)t0ctx)->rp;
        ip = ((t0_context *)t0ctx)->ip;
+       goto t0_next;
        for (;;) {
                uint32_t t0x;
 
-               t0x = t0_parse7E_unsigned(&ip);
+       t0_next:
+               t0x = T0_NEXT(&ip);
                if (t0x < T0_INTERPRETED) {
                        switch (t0x) {
                                int32_t t0off;
@@ -1928,11 +1970,22 @@ t0_exit:
        ((t0_context *)t0ctx)->rp = rp;
        ((t0_context *)t0ctx)->ip = ip;
 }");
+
+                       /*
+                        * Add the "postamblr" elements here. These are
+                        * elements that may need access to the data
+                        * block or code block, so they must occur after
+                        * their definition.
+                        */
+                       foreach (string pp in extraCodeDefer) {
+                               tw.WriteLine();
+                               tw.WriteLine("{0}", pp);
+                       }
                }
 
                int codeLen = 0;
                foreach (CodeElement ce in gcode) {
-                       codeLen += ce.Length;
+                       codeLen += ce.GetLength(oneByteCode);
                }
                int dataBlockLen = 0;
                foreach (ConstData cd in blocks.Values) {
@@ -1944,8 +1997,8 @@ t0_exit:
                 */
                Console.WriteLine("code length: {0,6} byte(s)", codeLen);
                Console.WriteLine("data length: {0,6} byte(s)", dataLen);
-               Console.WriteLine("interpreted words: {0}",
-                       interpretedEntry.Length);
+               Console.WriteLine("total words: {0} (interpreted: {1})",
+                       slotInterpreted + numInterpreted, numInterpreted);
        }
 
        internal Word Lookup(string name)