From: Thomas Pornin Date: Mon, 12 Dec 2016 18:58:49 +0000 (+0100) Subject: Optimised T0 generated code: when possible (at most 256 words), word calls are encode... X-Git-Tag: v0.4~38 X-Git-Url: https://www.bearssl.org/gitweb//home/git/?p=BearSSL;a=commitdiff_plain;h=fb7052216d8cb257e47de57e615c3a2f573174de Optimised T0 generated code: when possible (at most 256 words), word calls are encoded over one byte, even in the 128..255 range. --- diff --git a/T0/CodeElement.cs b/T0/CodeElement.cs index 5731c5a..471a61f 100644 --- a/T0/CodeElement.cs +++ b/T0/CodeElement.cs @@ -30,7 +30,7 @@ abstract class CodeElement { internal int LastLength { get; set; } - internal abstract int Length { get; } + // internal abstract int Length { get; } internal CodeElement() { @@ -42,7 +42,19 @@ abstract class CodeElement { throw new Exception("Code element accepts no target"); } - internal abstract int Encode(BlobWriter bw); + internal abstract int GetLength(bool oneByteCode); + + internal abstract int Encode(BlobWriter bw, bool oneByteCode); + + internal static int EncodeOneByte(uint val, BlobWriter bw) + { + if (val > 255) { + throw new Exception(string.Format( + "Cannot encode '{0}' over one byte", val)); + } + bw.Append((byte)val); + return 1; + } internal static int Encode7EUnsigned(uint val, BlobWriter bw) { diff --git a/T0/CodeElementJump.cs b/T0/CodeElementJump.cs index 5abd7eb..4dae0bc 100644 --- a/T0/CodeElementJump.cs +++ b/T0/CodeElementJump.cs @@ -34,6 +34,7 @@ class CodeElementJump : CodeElement { this.jumpType = jumpType; } + /* obsolete internal override int Length { get { int len = Encode7EUnsigned(jumpType, null); @@ -46,6 +47,19 @@ class CodeElementJump : CodeElement { return len; } } + */ + + internal override int GetLength(bool oneByteCode) + { + int len = oneByteCode ? 1 : Encode7EUnsigned(jumpType, null); + int joff = JumpOff; + if (joff == Int32.MinValue) { + len ++; + } else { + len += Encode7ESigned(joff, null); + } + return len; + } internal override void SetJumpTarget(CodeElement target) { @@ -63,12 +77,17 @@ class CodeElementJump : CodeElement { } } - internal override int Encode(BlobWriter bw) + internal override int Encode(BlobWriter bw, bool oneByteCode) { if (bw == null) { - return Length; + return GetLength(oneByteCode); + } + int len; + if (oneByteCode) { + len = EncodeOneByte(jumpType, bw); + } else { + len = Encode7EUnsigned(jumpType, bw); } - int len = Encode7EUnsigned(jumpType, bw); int joff = JumpOff; if (joff == Int32.MinValue) { throw new Exception("Unresolved addresses"); diff --git a/T0/CodeElementUInt.cs b/T0/CodeElementUInt.cs index e5f3607..049cdad 100644 --- a/T0/CodeElementUInt.cs +++ b/T0/CodeElementUInt.cs @@ -33,14 +33,23 @@ class CodeElementUInt : CodeElement { this.val = val; } + /* obsolete internal override int Length { get { return Encode7EUnsigned(val, null); } } + */ - internal override int Encode(BlobWriter bw) + internal override int GetLength(bool oneByteCode) { - return Encode7EUnsigned(val, bw); + return oneByteCode ? 1 : Encode7EUnsigned(val, null); + } + + internal override int Encode(BlobWriter bw, bool oneByteCode) + { + return oneByteCode + ? EncodeOneByte(val, bw) + : Encode7EUnsigned(val, bw); } } diff --git a/T0/CodeElementUIntExpr.cs b/T0/CodeElementUIntExpr.cs index d24ba58..8dd55a5 100644 --- a/T0/CodeElementUIntExpr.cs +++ b/T0/CodeElementUIntExpr.cs @@ -38,16 +38,26 @@ class CodeElementUIntExpr : CodeElement { this.off = off; } + /* obsolete internal override int Length { get { return Encode7EUnsigned(val, null) + (cx.GetMaxBitLength(off) + 6) / 7; } } + */ - internal override int Encode(BlobWriter bw) + internal override int GetLength(bool oneByteCode) { - int len1 = Encode7EUnsigned(val, bw); + int len = oneByteCode ? 1 : Encode7EUnsigned(val, null); + return len + (cx.GetMaxBitLength(off) + 6) / 7; + } + + internal override int Encode(BlobWriter bw, bool oneByteCode) + { + int len1 = oneByteCode + ? EncodeOneByte(val, bw) + : Encode7EUnsigned(val, bw); int len2 = (cx.GetMaxBitLength(off) + 6) / 7; bw.Append(String.Format("T0_INT{0}({1})", len2, cx.ToCExpr(off))); diff --git a/T0/CodeElementUIntInt.cs b/T0/CodeElementUIntInt.cs index 022ffb8..0223e27 100644 --- a/T0/CodeElementUIntInt.cs +++ b/T0/CodeElementUIntInt.cs @@ -35,16 +35,26 @@ class CodeElementUIntInt : CodeElement { this.val2 = val2; } + /* obsolete internal override int Length { get { return Encode7EUnsigned(val1, null) + Encode7ESigned(val2, null); } } + */ - internal override int Encode(BlobWriter bw) + internal override int GetLength(bool oneByteCode) { - int len = Encode7EUnsigned(val1, bw); + return (oneByteCode ? 1 : Encode7EUnsigned(val1, null)) + + Encode7ESigned(val2, null); + } + + internal override int Encode(BlobWriter bw, bool oneByteCode) + { + int len = oneByteCode + ? EncodeOneByte(val1, bw) + : Encode7EUnsigned(val1, bw); len += Encode7ESigned(val2, bw); return len; } diff --git a/T0/CodeElementUIntUInt.cs b/T0/CodeElementUIntUInt.cs index 3d4ee33..6f94de5 100644 --- a/T0/CodeElementUIntUInt.cs +++ b/T0/CodeElementUIntUInt.cs @@ -34,16 +34,26 @@ class CodeElementUIntUInt : CodeElement { this.val2 = val2; } + /* obsolete internal override int Length { get { return Encode7EUnsigned(val1, null) + Encode7EUnsigned(val2, null); } } + */ - internal override int Encode(BlobWriter bw) + internal override int GetLength(bool oneByteCode) { - int len = Encode7EUnsigned(val1, bw); + return (oneByteCode ? 1 : Encode7EUnsigned(val1, null)) + + Encode7EUnsigned(val2, null); + } + + internal override int Encode(BlobWriter bw, bool oneByteCode) + { + int len = oneByteCode + ? EncodeOneByte(val1, bw) + : Encode7EUnsigned(val1, bw); len += Encode7EUnsigned(val2, bw); return len; } diff --git a/T0/T0Comp.cs b/T0/T0Comp.cs index 143badb..20adc04 100644 --- a/T0/T0Comp.cs +++ b/T0/T0Comp.cs @@ -1626,6 +1626,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 +1648,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 ++) { @@ -1756,7 +1770,7 @@ static const uint8_t t0_datablock[]; tw.Write("static const uint8_t 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 +1819,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 +1875,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; @@ -1932,7 +1956,7 @@ t0_exit: 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 +1968,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) diff --git a/T0Comp.exe b/T0Comp.exe index 411645c..b951fab 100755 Binary files a/T0Comp.exe and b/T0Comp.exe differ