Optimised T0 generated code: when possible (at most 256 words), word calls are encoded over one byte, even in the 128..255 range.
This commit is contained in:
parent
e61ad42191
commit
fb7052216d
8 changed files with 114 additions and 20 deletions
|
|
@ -30,7 +30,7 @@ abstract class CodeElement {
|
||||||
|
|
||||||
internal int LastLength { get; set; }
|
internal int LastLength { get; set; }
|
||||||
|
|
||||||
internal abstract int Length { get; }
|
// internal abstract int Length { get; }
|
||||||
|
|
||||||
internal CodeElement()
|
internal CodeElement()
|
||||||
{
|
{
|
||||||
|
|
@ -42,7 +42,19 @@ abstract class CodeElement {
|
||||||
throw new Exception("Code element accepts no target");
|
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)
|
internal static int Encode7EUnsigned(uint val, BlobWriter bw)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ class CodeElementJump : CodeElement {
|
||||||
this.jumpType = jumpType;
|
this.jumpType = jumpType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* obsolete
|
||||||
internal override int Length {
|
internal override int Length {
|
||||||
get {
|
get {
|
||||||
int len = Encode7EUnsigned(jumpType, null);
|
int len = Encode7EUnsigned(jumpType, null);
|
||||||
|
|
@ -46,6 +47,19 @@ class CodeElementJump : CodeElement {
|
||||||
return len;
|
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)
|
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) {
|
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;
|
int joff = JumpOff;
|
||||||
if (joff == Int32.MinValue) {
|
if (joff == Int32.MinValue) {
|
||||||
throw new Exception("Unresolved addresses");
|
throw new Exception("Unresolved addresses");
|
||||||
|
|
|
||||||
|
|
@ -33,14 +33,23 @@ class CodeElementUInt : CodeElement {
|
||||||
this.val = val;
|
this.val = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* obsolete
|
||||||
internal override int Length {
|
internal override int Length {
|
||||||
get {
|
get {
|
||||||
return Encode7EUnsigned(val, null);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,16 +38,26 @@ class CodeElementUIntExpr : CodeElement {
|
||||||
this.off = off;
|
this.off = off;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* obsolete
|
||||||
internal override int Length {
|
internal override int Length {
|
||||||
get {
|
get {
|
||||||
return Encode7EUnsigned(val, null)
|
return Encode7EUnsigned(val, null)
|
||||||
+ (cx.GetMaxBitLength(off) + 6) / 7;
|
+ (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;
|
int len2 = (cx.GetMaxBitLength(off) + 6) / 7;
|
||||||
bw.Append(String.Format("T0_INT{0}({1})",
|
bw.Append(String.Format("T0_INT{0}({1})",
|
||||||
len2, cx.ToCExpr(off)));
|
len2, cx.ToCExpr(off)));
|
||||||
|
|
|
||||||
|
|
@ -35,16 +35,26 @@ class CodeElementUIntInt : CodeElement {
|
||||||
this.val2 = val2;
|
this.val2 = val2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* obsolete
|
||||||
internal override int Length {
|
internal override int Length {
|
||||||
get {
|
get {
|
||||||
return Encode7EUnsigned(val1, null)
|
return Encode7EUnsigned(val1, null)
|
||||||
+ Encode7ESigned(val2, 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);
|
len += Encode7ESigned(val2, bw);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,16 +34,26 @@ class CodeElementUIntUInt : CodeElement {
|
||||||
this.val2 = val2;
|
this.val2 = val2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* obsolete
|
||||||
internal override int Length {
|
internal override int Length {
|
||||||
get {
|
get {
|
||||||
return Encode7EUnsigned(val1, null)
|
return Encode7EUnsigned(val1, null)
|
||||||
+ Encode7EUnsigned(val2, 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);
|
len += Encode7EUnsigned(val2, bw);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
38
T0/T0Comp.cs
38
T0/T0Comp.cs
|
|
@ -1626,6 +1626,20 @@ public class T0Comp {
|
||||||
}
|
}
|
||||||
CodeElement[] gcode = gcodeList.ToArray();
|
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
|
* Compute all addresses and offsets. This loops until
|
||||||
* the addresses stabilize.
|
* the addresses stabilize.
|
||||||
|
|
@ -1634,7 +1648,7 @@ public class T0Comp {
|
||||||
int[] gcodeLen = new int[gcode.Length];
|
int[] gcodeLen = new int[gcode.Length];
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (int i = 0; i < gcode.Length; i ++) {
|
for (int i = 0; i < gcode.Length; i ++) {
|
||||||
gcodeLen[i] = gcode[i].Length;
|
gcodeLen[i] = gcode[i].GetLength(oneByteCode);
|
||||||
}
|
}
|
||||||
int off = 0;
|
int off = 0;
|
||||||
for (int i = 0; i < gcode.Length; i ++) {
|
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[] = {");
|
tw.Write("static const uint8_t t0_codeblock[] = {");
|
||||||
bw = new BlobWriter(tw, 78, 1);
|
bw = new BlobWriter(tw, 78, 1);
|
||||||
foreach (CodeElement ce in gcode) {
|
foreach (CodeElement ce in gcode) {
|
||||||
ce.Encode(bw);
|
ce.Encode(bw, oneByteCode);
|
||||||
}
|
}
|
||||||
tw.WriteLine();
|
tw.WriteLine();
|
||||||
tw.WriteLine("};");
|
tw.WriteLine("};");
|
||||||
|
|
@ -1805,6 +1819,14 @@ name(void *ctx) \
|
||||||
wordSet[ep].Slot);
|
wordSet[ep].Slot);
|
||||||
}
|
}
|
||||||
tw.WriteLine();
|
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("void");
|
||||||
tw.WriteLine("{0}_run(void *t0ctx)", coreRun);
|
tw.WriteLine("{0}_run(void *t0ctx)", coreRun);
|
||||||
tw.WriteLine("{0}",
|
tw.WriteLine("{0}",
|
||||||
|
|
@ -1853,15 +1875,17 @@ name(void *ctx) \
|
||||||
#define T0_CO() do { \
|
#define T0_CO() do { \
|
||||||
goto t0_exit; \
|
goto t0_exit; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define T0_RET() break
|
#define T0_RET() goto t0_next
|
||||||
|
|
||||||
dp = ((t0_context *)t0ctx)->dp;
|
dp = ((t0_context *)t0ctx)->dp;
|
||||||
rp = ((t0_context *)t0ctx)->rp;
|
rp = ((t0_context *)t0ctx)->rp;
|
||||||
ip = ((t0_context *)t0ctx)->ip;
|
ip = ((t0_context *)t0ctx)->ip;
|
||||||
|
goto t0_next;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
uint32_t t0x;
|
uint32_t t0x;
|
||||||
|
|
||||||
t0x = t0_parse7E_unsigned(&ip);
|
t0_next:
|
||||||
|
t0x = T0_NEXT(&ip);
|
||||||
if (t0x < T0_INTERPRETED) {
|
if (t0x < T0_INTERPRETED) {
|
||||||
switch (t0x) {
|
switch (t0x) {
|
||||||
int32_t t0off;
|
int32_t t0off;
|
||||||
|
|
@ -1932,7 +1956,7 @@ t0_exit:
|
||||||
|
|
||||||
int codeLen = 0;
|
int codeLen = 0;
|
||||||
foreach (CodeElement ce in gcode) {
|
foreach (CodeElement ce in gcode) {
|
||||||
codeLen += ce.Length;
|
codeLen += ce.GetLength(oneByteCode);
|
||||||
}
|
}
|
||||||
int dataBlockLen = 0;
|
int dataBlockLen = 0;
|
||||||
foreach (ConstData cd in blocks.Values) {
|
foreach (ConstData cd in blocks.Values) {
|
||||||
|
|
@ -1944,8 +1968,8 @@ t0_exit:
|
||||||
*/
|
*/
|
||||||
Console.WriteLine("code length: {0,6} byte(s)", codeLen);
|
Console.WriteLine("code length: {0,6} byte(s)", codeLen);
|
||||||
Console.WriteLine("data length: {0,6} byte(s)", dataLen);
|
Console.WriteLine("data length: {0,6} byte(s)", dataLen);
|
||||||
Console.WriteLine("interpreted words: {0}",
|
Console.WriteLine("total words: {0} (interpreted: {1})",
|
||||||
interpretedEntry.Length);
|
slotInterpreted + numInterpreted, numInterpreted);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Word Lookup(string name)
|
internal Word Lookup(string name)
|
||||||
|
|
|
||||||
BIN
T0Comp.exe
BIN
T0Comp.exe
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue