From ca1ee83377c498ea95cfba0ee060e74e2b3089c4 Mon Sep 17 00:00:00 2001 From: cannoli-fruit Date: Thu, 30 Jul 2026 04:54:05 -0400 Subject: [PATCH] Monstrous commit smh, made a custom ssa intermediate representation to remove some stack ops, glendasay is about 40% faster (and i'm sure the other ones have some improvement too) --- bldit.lua | 2 +- flagpole/bldit.lua | 2 +- flagpole/fvm.inc | 1 + flagpole/fvmstd.fp | 4 +- flagpole/irtests/2vars.fp | 5 + flagpole/irtests/cat.fp | 13 + flagpole/irtests/cat1.fp | 11 + flagpole/irtests/divgrow.fp | 10 + flagpole/irtests/dumbstring.fp | 3 + flagpole/irtests/eq.fp | 5 + flagpole/irtests/gt.fp | 6 + flagpole/irtests/hex.fp | 7 + flagpole/irtests/loop.fp | 10 + flagpole/irtests/num.fp | 5 + flagpole/irtests/putuint.fp | 5 + flagpole/irtests/uadd.fp | 3 + flagpole/irtests/usub.fp | 3 + flagpole/irtests/var.fp | 4 + flagpole/irtests/varmover.fp | 14 + flagpole/src/ir.c | 285 +++++++++++++++ flagpole/src/ir.h | 51 +++ flagpole/src/main.c | 629 +++++++++++++++++++++++++-------- flagpole/tests/fibloop.fp | 14 + src/interp.c | 102 ++++-- 24 files changed, 1018 insertions(+), 176 deletions(-) create mode 120000 flagpole/fvm.inc create mode 100644 flagpole/irtests/2vars.fp create mode 100644 flagpole/irtests/cat.fp create mode 100644 flagpole/irtests/cat1.fp create mode 100644 flagpole/irtests/divgrow.fp create mode 100644 flagpole/irtests/dumbstring.fp create mode 100644 flagpole/irtests/eq.fp create mode 100644 flagpole/irtests/gt.fp create mode 100644 flagpole/irtests/hex.fp create mode 100644 flagpole/irtests/loop.fp create mode 100644 flagpole/irtests/num.fp create mode 100644 flagpole/irtests/putuint.fp create mode 100644 flagpole/irtests/uadd.fp create mode 100644 flagpole/irtests/usub.fp create mode 100644 flagpole/irtests/var.fp create mode 100644 flagpole/irtests/varmover.fp create mode 100644 flagpole/src/ir.c create mode 100644 flagpole/src/ir.h create mode 100644 flagpole/tests/fibloop.fp diff --git a/bldit.lua b/bldit.lua index a963e45..a0458c3 100644 --- a/bldit.lua +++ b/bldit.lua @@ -34,7 +34,7 @@ targets = { for f in p:lines() do base = f:match("([^/]+)%.c$") obj = "build/"..base..".o" - cc = "cc -c '"..f.."' -o '"..obj.."' "..includes + cc = "cc -c -O3 '"..f.."' -o '"..obj.."' "..includes e,h,c = execute(cc) if c ~= 0 and c ~= nil then print("Compilation Error") diff --git a/flagpole/bldit.lua b/flagpole/bldit.lua index 1377498..6903d24 100644 --- a/flagpole/bldit.lua +++ b/flagpole/bldit.lua @@ -34,7 +34,7 @@ targets = { for f in p:lines() do base = f:match("([^/]+)%.c$") obj = "build/"..base..".o" - cc = "cc -c '"..f.."' -o '"..obj.."' "..includes + cc = "cc -c -ggdb '"..f.."' -o '"..obj.."' "..includes e,h,c = execute(cc) if c ~= 0 and c ~= nil then print("Compilation Error") diff --git a/flagpole/fvm.inc b/flagpole/fvm.inc new file mode 120000 index 0000000..055040b --- /dev/null +++ b/flagpole/fvm.inc @@ -0,0 +1 @@ +../tests/fvm.inc \ No newline at end of file diff --git a/flagpole/fvmstd.fp b/flagpole/fvmstd.fp index aa8cca9..11b84ef 100644 --- a/flagpole/fvmstd.fp +++ b/flagpole/fvmstd.fp @@ -64,7 +64,7 @@ proc putuint 1 @divisor while &val &divisor u/ 9 u> do - 10 &divisor u* @divisor + &divisor 10 u* @divisor endwhile while &divisor 0 u> do @@ -90,7 +90,7 @@ proc puts dup ld8 :putchar 1 u+ endwhile - pop + drop endproc proc newline diff --git a/flagpole/irtests/2vars.fp b/flagpole/irtests/2vars.fp new file mode 100644 index 0000000..8235f11 --- /dev/null +++ b/flagpole/irtests/2vars.fp @@ -0,0 +1,5 @@ +proc main + 2 @a + 3 @b + &a &b u+ +endproc diff --git a/flagpole/irtests/cat.fp b/flagpole/irtests/cat.fp new file mode 100644 index 0000000..2399c2f --- /dev/null +++ b/flagpole/irtests/cat.fp @@ -0,0 +1,13 @@ +proc putchar + 0xCFFFFFFFFFFFFFFD st8 +endproc + +proc getchar + 0xCFFFFFFFFFFFFFFE ld8 +endproc + +proc main + while 1 do + :getchar :putchar + endwhile +endproc diff --git a/flagpole/irtests/cat1.fp b/flagpole/irtests/cat1.fp new file mode 100644 index 0000000..176790e --- /dev/null +++ b/flagpole/irtests/cat1.fp @@ -0,0 +1,11 @@ +proc putchar + 0xCFFFFFFFFFFFFFFD st8 +endproc + +proc getchar + 0xCFFFFFFFFFFFFFFE ld8 +endproc + +proc main + :getchar :putchar +endproc diff --git a/flagpole/irtests/divgrow.fp b/flagpole/irtests/divgrow.fp new file mode 100644 index 0000000..39e19af --- /dev/null +++ b/flagpole/irtests/divgrow.fp @@ -0,0 +1,10 @@ +$inc fvmstd.fp + +proc main + 1 @divisor + while &divisor 100 u< do + 0x31 :putchar + &divisor 10 u* @divisor + endwhile + 0x32 :putchar +endproc \ No newline at end of file diff --git a/flagpole/irtests/dumbstring.fp b/flagpole/irtests/dumbstring.fp new file mode 100644 index 0000000..0b4bd55 --- /dev/null +++ b/flagpole/irtests/dumbstring.fp @@ -0,0 +1,3 @@ +proc main + "String" 1 u+ +endproc diff --git a/flagpole/irtests/eq.fp b/flagpole/irtests/eq.fp new file mode 100644 index 0000000..a7fc8e8 --- /dev/null +++ b/flagpole/irtests/eq.fp @@ -0,0 +1,5 @@ +proc main + 1 + 2 1 u- + == +endproc diff --git a/flagpole/irtests/gt.fp b/flagpole/irtests/gt.fp new file mode 100644 index 0000000..af7daac --- /dev/null +++ b/flagpole/irtests/gt.fp @@ -0,0 +1,6 @@ +proc main + 5 + if 5 3 u> then + drop 3 + endif +endproc diff --git a/flagpole/irtests/hex.fp b/flagpole/irtests/hex.fp new file mode 100644 index 0000000..f0aae2d --- /dev/null +++ b/flagpole/irtests/hex.fp @@ -0,0 +1,7 @@ +proc putchar + 0xCFFFFFFFFFFFFFFD st8 +endproc + +proc main + 0x48 :putchar +endproc diff --git a/flagpole/irtests/loop.fp b/flagpole/irtests/loop.fp new file mode 100644 index 0000000..f03c402 --- /dev/null +++ b/flagpole/irtests/loop.fp @@ -0,0 +1,10 @@ +$inc fvmstd.fp + +proc main + 1 @i + 0x30 :putchar + while &i 10 u< do + 0x30 :putchar + &i 1 u+ @i + endwhile +endproc diff --git a/flagpole/irtests/num.fp b/flagpole/irtests/num.fp new file mode 100644 index 0000000..e069b50 --- /dev/null +++ b/flagpole/irtests/num.fp @@ -0,0 +1,5 @@ +$inc fvmstd.fp + +proc main + 4 :putuint +endproc diff --git a/flagpole/irtests/putuint.fp b/flagpole/irtests/putuint.fp new file mode 100644 index 0000000..07a17bd --- /dev/null +++ b/flagpole/irtests/putuint.fp @@ -0,0 +1,5 @@ +$inc fvmstd.fp + +proc main + 23 :putuint +endproc diff --git a/flagpole/irtests/uadd.fp b/flagpole/irtests/uadd.fp new file mode 100644 index 0000000..b55cc7c --- /dev/null +++ b/flagpole/irtests/uadd.fp @@ -0,0 +1,3 @@ +proc main + 34 35 u+ +endproc diff --git a/flagpole/irtests/usub.fp b/flagpole/irtests/usub.fp new file mode 100644 index 0000000..9870932 --- /dev/null +++ b/flagpole/irtests/usub.fp @@ -0,0 +1,3 @@ +proc main + 500 80 u- +endproc diff --git a/flagpole/irtests/var.fp b/flagpole/irtests/var.fp new file mode 100644 index 0000000..06e0b4f --- /dev/null +++ b/flagpole/irtests/var.fp @@ -0,0 +1,4 @@ +proc main + 0x40 @a + &a 2 u+ +endproc diff --git a/flagpole/irtests/varmover.fp b/flagpole/irtests/varmover.fp new file mode 100644 index 0000000..c45d4a6 --- /dev/null +++ b/flagpole/irtests/varmover.fp @@ -0,0 +1,14 @@ +$inc fvmstd.fp + +proc main + 2 @a + 4 @b + 3 @a + 8 @c + &b @a + &c @a + + &a 0x30 u+ :putchar + &b 0x30 u+ :putchar + &c 0x30 u+ :putchar +endproc diff --git a/flagpole/src/ir.c b/flagpole/src/ir.c new file mode 100644 index 0000000..d8e44f7 --- /dev/null +++ b/flagpole/src/ir.c @@ -0,0 +1,285 @@ +#include "lazy.h" +#include "ir.h" + +void IRLoadValue(IRValue v, int reg, IRValue *registers) { + if (v.typ == IRVAL_VIRTUAL) { + for (int i = 1; i < 96; ++i) { + if (registers[i].typ == IRVAL_VIRTUAL && registers[i].val == v.val) { + printf(" Mov64 %d, %d\n", reg, i); + return; + } + } + } + + if (v.typ == IRVAL_STACK) { + for (int i = 1; i < 96; ++i) { + if (registers[i].typ == IRVAL_STACK && registers[i].val == v.val) { + printf(" Mov64 %d, %d\n", reg, i); + return; + } + } + } + + if (v.typ == IRVAL_MEMORY) { + printf(" MovI64 103, 0x%016lX\n", v.val); + printf(" Ld64 %d, 103\n", reg); + return; + } + + if (v.typ == IRVAL_CONSTANT) { + printf(" MovI64 %d, 0x%016lX\n", reg, v.val); + } +} + +void IRStoreValue(IRValue v, int reg, int *regalloc, IRValue *registers) { + if (v.typ == IRVAL_VIRTUAL) { + int r = (*regalloc)++; + registers[r] = v; + printf(" Mov64 %d, %d\n", r, reg); + } + + if (v.typ == IRVAL_STACK) { + assert(0 && "Don't write directly to the stack pooks <3"); + } + + if (v.typ == IRVAL_MEMORY) { + printf(" MovI64 123, 0x%016lX\n", v.val); + printf(" St64 %d, 123\n", reg); + return; + } + + if (v.typ == IRVAL_CONSTANT) { + // Escape for non returning operations + } +} + +void IRComplete(void *statements_v, void *vstack_v) { + Lz_DA(IRStatement) *statements = statements_v; + Lz_DA(IRValue) *vstack = vstack_v; + int regalloc = 1; // Current register for allocating things + // If you manage to hit 95 registers + // You deserve for your compiler to fail + IRValue registers[96]; + int deepestStack = 0; + for (int i = 0; i < statements->cnt; ++i) { + if (statements->data[i].arg1.typ == IRVAL_STACK) { + if (statements->data[i].arg1.val > deepestStack) { + deepestStack = statements->data[i].arg1.val; + } + } + if (statements->data[i].arg2.typ == IRVAL_STACK) { + if (statements->data[i].arg2.val > deepestStack) { + deepestStack = statements->data[i].arg2.val; + } + } + } + + for (int i = 0; i < deepestStack; ++i) { + int reg = regalloc++; + printf(" popstack %d\n", reg); + registers[reg] = (IRValue) { + .typ = IRVAL_STACK, + .val = i+1 + }; + } + + int count; + lz_da_foreach(IRStatement, s, *statements) { + ++count; + printf("; Using ir-operation %d\n", s->op); + switch (s->op) { + case IR_UADD: { + IRLoadValue(s->arg1, 101, registers); + IRLoadValue(s->arg2, 100, registers); + printf(" AddR64 100, 101\n"); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_USUB: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" SubR64 100, 101\n"); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_UMUL: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" MulR64 100, 101\n"); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_UDIV: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" DivR64 100, 101\n"); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_UMOD: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" ModR64 100, 101\n"); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_AND: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" AndR64 100, 101\n"); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_XOR: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" XorR64 100, 101\n"); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_OR: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" OrR64 100, 101\n"); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_NOT: { + IRLoadValue(s->arg1, 101, registers); + printf(" Not64 101\n"); + IRStoreValue(s->dst, 101, ®alloc, registers); + break; + } + case IR_IMUL: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" IMulR64 100, 101\n"); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_IDIV: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" IDivR64 100, 101\n"); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_IMOD: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" IModR64 100, 101\n"); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_ST8: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" St8 100, 101\n"); + break; + } + case IR_SWAP: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + IRStoreValue(s->arg1, 100, ®alloc, registers); + IRStoreValue(s->arg2, 101, ®alloc, registers); + break; + } + case IR_NOP: { + IRLoadValue(s->arg1, 100, registers); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_LD8: { + IRLoadValue(s->arg1, 101, registers); + printf(" Ld8 100, 101\n"); + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + case IR_EQ: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" Cmp64 100, 101\n"); + printf(" JmpIZ eq_%d\n", count); + printf(" MovI64 99, 0\n"); + printf(" Jmp cmpdone_%d\n", count); + printf("eq_%d:\n", count); + printf(" MovI64 99, 1\n"); + printf("cmpdone_%d:\n",count); + IRStoreValue(s->dst, 99, ®alloc, registers); + break; + } + case IR_ULT: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" Cmp64 100, 101\n"); + printf(" JmpIN eq_%d\n", count); + printf(" MovI64 99, 0\n"); + printf(" Jmp cmpdone_%d\n", count); + printf("eq_%d:\n", count); + printf(" MovI64 99, 1\n"); + printf("cmpdone_%d:\n", count); + IRStoreValue(s->dst, 99, ®alloc, registers); + break; + } + case IR_UGT: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" Cmp64 100, 101\n"); + printf(" JmpIP eq_%d\n", count); + printf(" MovI64 99, 0\n"); + printf(" Jmp cmpdone_%d\n", count); + printf("eq_%d:\n", count); + printf(" MovI64 99, 1\n"); + printf("cmpdone_%d:\n",count); + IRStoreValue(s->dst, 99, ®alloc, registers); + break; + } + case IR_ILT: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" ICmp64 100, 101\n"); + printf(" JmpIN eq_%d\n", count); + printf(" MovI64 99, 0\n"); + printf(" Jmp cmpdone_%d\n", count); + printf("eq_%d:\n", count); + printf(" MovI64 99, 1\n"); + printf("cmpdone_%d:\n",count); + IRStoreValue(s->dst, 99, ®alloc, registers); + break; + } + case IR_IGT: { + IRLoadValue(s->arg2, 100, registers); + IRLoadValue(s->arg1, 101, registers); + printf(" ICmp64 100, 101\n"); + printf(" JmpIP eq_%d\n", count); + printf(" MovI64 99, 0\n"); + printf(" Jmp cmpdone_%d\n", count); + printf("eq_%d:\n", count); + printf(" MovI64 99, 1\n"); + printf("cmpdone_%d:\n",count); + IRStoreValue(s->dst, 99, ®alloc, registers); + break; + } + case IR_STR: { + IRStoreValue(s->dst, 100, ®alloc, registers); + break; + } + } + } + + lz_da_foreach(IRValue, v, *vstack) { + if (v->typ == IRVAL_CONSTANT) { + printf(" MovI64 123, 0x%016lX\n", v->val); + printf(" pushstack 123\n"); + continue; + } + for (int i = 0; i < 96; ++i) { + if (registers[i].typ == v->typ && registers[i].val == v->val) { + printf(" pushstack %d\n",i); + break; + } + } + } + vstack->cnt = 0; + statements->cnt = 0; +} diff --git a/flagpole/src/ir.h b/flagpole/src/ir.h new file mode 100644 index 0000000..9e1a31b --- /dev/null +++ b/flagpole/src/ir.h @@ -0,0 +1,51 @@ + +typedef enum { + IRVAL_VIRTUAL, + IRVAL_STACK, + IRVAL_MEMORY, + IRVAL_ARG, + IRVAL_CONSTANT +} IRValKind; + +typedef struct { + IRValKind typ; + uint64_t val; +} IRValue; + +typedef enum { + IR_NOP, + IR_SWAP, + IR_UADD, + IR_USUB, + IR_UMUL, + IR_UDIV, + IR_UMOD, + IR_IADD, + IR_ISUB, + IR_IMUL, + IR_IDIV, + IR_IMOD, + IR_UGT, + IR_ULT, + IR_IGT, + IR_ILT, + IR_EQ, + IR_NOT, + IR_AND, + IR_OR, + IR_XOR, + IR_LD8, + IR_LD64, + IR_ST8, + IR_ST64, + IR_STR, +} IROperation; + +typedef struct { + IRValue dst; + IROperation op; + IRValue arg1; + IRValue arg2; +} IRStatement; + +void IRComplete(void *statements_v, void *vstack_v); diff --git a/flagpole/src/main.c b/flagpole/src/main.c index e687bea..9ab525a 100644 --- a/flagpole/src/main.c +++ b/flagpole/src/main.c @@ -5,6 +5,7 @@ #include "lazy.h" #include "token.h" #include "var.h" +#include "ir.h" bool is_int_literal(Lz_SB *sb) { for (int i = 0; i < sb->cnt; ++i) { @@ -78,6 +79,24 @@ void commentStack(void *stack) { printf("\n"); } +static inline uint64_t lz_sb_readhex(Lz_SB *sb) { + Lz_SB clone = *sb; + clone.data += 2; + clone.cnt -= 2; + uint64_t val = 0; + lz_da_foreach(char, c, clone) { + val *= 0x10; + if (*c >= '0' && *c <= '9') { + val += *c - '0'; + } else if (*c >= 'A' && *c <= 'F') { + val += *c - 'A' + 10; + } else if (*c >= 'a' && *c <= 'f') { + val += *c - 'a' + 10; + } + } + return val; +} + static inline bool isKW(Lz_SB *sb) { return SBeq(sb, "proc") @@ -117,6 +136,28 @@ static inline bool isKW(Lz_SB *sb) { ; } +#define IR_GET_2_ARGS \ + IRValue x1, x2; \ + if (irVStack.cnt >= 2) { \ + x1 = lz_da_pop(irVStack); \ + x2 = lz_da_pop(irVStack); \ + } else if (irVStack.cnt == 1) { \ + x1 = lz_da_pop(irVStack); \ + x2 = (IRValue) { \ + .typ = IRVAL_STACK, \ + .val = ++vstackUnderflows \ + }; \ + } else if (irVStack.cnt == 0) { \ + x1 = (IRValue) { \ + .typ = IRVAL_STACK, \ + .val = ++vstackUnderflows \ + }; \ + x2 = (IRValue) { \ + .typ = IRVAL_STACK, \ + .val = ++vstackUnderflows \ + }; \ + } + int main(uint argc, char **argv) { int opt; Lz_DA(FILE *) inpfiles = {}; @@ -152,24 +193,28 @@ int main(uint argc, char **argv) { Lz_DA(int) labelStack = {0}; uint64_t allocHead = 0x7000000000000000; char funcName[128]; - Lz_DA(Variable) vars; + Lz_DA(Variable) vars = {0}; char newchar; + Lz_DA(IRStatement) irStatements = {0}; + Lz_DA(IRValue) irVStack = {0}; + int irVCount = 0; + int vstackUnderflows = 0; printf("include 'fvm.inc'\n"); printf("define STACK_START 0x6000000000000000\n"); printf("define STACK_SP 125\n"); + printf("define STACK_INC 126\n"); printf("org 0x4000000000000000\n"); printf(" MovI64 STACK_SP, STACK_START\n"); + printf(" MovI64 STACK_INC, 8\n"); printf(" Call __fp_user_main\n"); printf(" Halt\n"); printf("macro pushstack reg\n"); - printf(" MovI64 124, 8\n"); - printf(" SubR64 STACK_SP, 124\n"); + printf(" SubR64 STACK_SP, STACK_INC\n"); printf(" St64 reg, STACK_SP\n"); printf("end macro\n\n"); printf("macro popstack reg\n"); - printf(" MovI64 124, 8\n"); printf(" Ld64 reg, STACK_SP\n"); - printf(" AddR64 STACK_SP, 124\n"); + printf(" AddR64 STACK_SP, STACK_INC\n"); printf("end macro\n\n"); // Genuinely idk why goto is possessing me today compileStart: @@ -182,32 +227,32 @@ compileStart: if (tokenAccumulator.cnt == 0) continue; if (is_int_literal(&tokenAccumulator)) { currTokenKind = TOKEN_INTLIT; - goto codegen; + goto codegenIR; } else if (is_float_literal(&tokenAccumulator)) { currTokenKind = TOKEN_FLOATLIT; - goto codegen; + goto codegenIR; } else if (is_double_literal(&tokenAccumulator)) { currTokenKind = TOKEN_DOUBLELIT; - goto codegen; + goto codegenIR; } else if (is_hex_literal(&tokenAccumulator)) { currTokenKind = TOKEN_HEXLIT; - goto codegen; + goto codegenIR; } else if (is_bin_literal(&tokenAccumulator)) { currTokenKind = TOKEN_BINLIT; - goto codegen; + goto codegenIR; } else { currTokenKind = TOKEN_IDENTIFIER; if (isKW(&tokenAccumulator)) { currTokenKind = TOKEN_KEYWORD; } - goto codegen; + goto codegenIR; } } if (newchar == '"') { if (isQuote) { currTokenKind = TOKEN_STRINGLIT; isQuote = false; - goto codegen; + goto codegenIR; } else { if (tokenAccumulator.cnt != 0) { fprintf(stderr, "error %d\n", __LINE__); @@ -220,7 +265,8 @@ compileStart: } lz_da_append(tokenAccumulator, newchar); continue; -codegen: + // Names suck but this also generates some asm for blocks +codegenIR: //printf("I must gen code i am now Amista Azozin\n"); //fprintf(stderr,"Token type: %d\n", currTokenKind); //fprintf(stderr,"Tok: "LZ_STR_FMT"\n", LZ_STR_PRINTF(tokenAccumulator)); @@ -232,6 +278,8 @@ codegen: break; } if (SBeq(&tokenAccumulator, "endproc")) { + IRComplete(&irStatements, &irVStack); + vstackUnderflows = 0; printf(" Ret\n"); printf("\n\n"); if (labelStack.cnt != 0) { @@ -243,53 +291,113 @@ codegen: break; } if (SBeq(&tokenAccumulator, "return")) { + IRComplete(&irStatements, &irVStack); + vstackUnderflows = 0; printf(" Ret\n"); break; } if (SBeq(&tokenAccumulator, "ld8")) { - printf(" popstack 101\n"); - printf(" Ld8 102, 101\n"); - printf(" pushstack 102\n"); + IRValue x1; + if (irVStack.cnt >= 1) { + x1 = lz_da_pop(irVStack); + } else if (irVStack.cnt == 0) { + x1 = (IRValue) { + .typ = IRVAL_STACK, + .val = 1 + }; + } + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_LD8, + .arg1 = x1 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "st8")) { - printf(" popstack 101\n"); - printf(" popstack 102\n"); - printf(" St8 102, 101\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_CONSTANT, + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_ST8, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "dup")) { - printf(" popstack 106\n"); - printf(" pushstack 106\n"); - printf(" pushstack 106\n"); + if (irVStack.cnt != 0) { + IRValue v = lz_da_pop(irVStack); + lz_da_append(irVStack, v); + lz_da_append(irVStack, v); + } else { + printf(" popstack 106\n"); + printf(" pushstack 106\n"); + printf(" pushstack 106\n"); + } break; } if (SBeq(&tokenAccumulator, "swap")) { - printf(" popstack 118\n"); - printf(" popstack 119\n"); - printf(" pushstack 118\n"); - printf(" pushstack 119\n"); + IRValue x1, x2; + if (irVStack.cnt >= 2) { + x1 = lz_da_pop(irVStack); + x2 = lz_da_pop(irVStack); + } else if (irVStack.cnt == 1) { + x1 = lz_da_pop(irVStack); + x2 = (IRValue) { + .typ = IRVAL_STACK, + .val = ++vstackUnderflows + }; + } else if (irVStack.cnt == 0) { + x1 = (IRValue) { + .typ = IRVAL_STACK, + .val = ++vstackUnderflows + }; + x2 = (IRValue) { + .typ = IRVAL_STACK, + .val = ++vstackUnderflows + }; + } + lz_da_append(irVStack, x1); + lz_da_append(irVStack, x2); break; } if (SBeq(&tokenAccumulator, "drop")) { - printf(" popstack 118\n"); + if (irVStack.cnt != 0) + lz_da_pop(irVStack); + else + printf(" popstack 118\n"); break; } if (SBeq(&tokenAccumulator, "while")) { + IRComplete(&irStatements, &irVStack); lz_da_append(labelStack, counter); commentStack(&labelStack); printf("__whilehead_%d:\n", counter); break; } if (SBeq(&tokenAccumulator, "do")) { + IRComplete(&irStatements, &irVStack); + vstackUnderflows = 0; int lbl = lz_da_pop(labelStack); lz_da_append(labelStack, lbl); + // TODO: Change flag setting to IR's job printf(" popstack 108\n"); printf(" RSetF 108\n"); printf(" JmpIE __whiletail_%d\n", lbl); break; } if (SBeq(&tokenAccumulator, "endwhile")) { + IRComplete(&irStatements, &irVStack); + vstackUnderflows = 0; int lbl = lz_da_pop(labelStack); commentStack(&labelStack); printf(" Jmp __whilehead_%d\n", lbl); @@ -302,6 +410,8 @@ codegen: break; } if (SBeq(&tokenAccumulator, "then")) { + IRComplete(&irStatements, &irVStack); + vstackUnderflows = 0; commentStack(&labelStack); int lbl = lz_da_pop(labelStack); lz_da_append(labelStack, lbl); @@ -312,177 +422,322 @@ codegen: } if (SBeq(&tokenAccumulator, "endif")) { + IRComplete(&irStatements, &irVStack); + vstackUnderflows = 0; commentStack(&labelStack); int lbl = lz_da_pop(labelStack); printf("__iftail_%d:\n", lbl); break; } if (SBeq(&tokenAccumulator, "==")) { - // Hacked like crazy... - printf(" popstack 110\n"); - printf(" popstack 111\n"); - printf(" Cmp64 110, 111\n"); - printf(" JmpIZ __Eq%d\n", counter); - printf(" MovI64 112, 0\n"); - printf(" Jmp __DoneEqCheck%d\n", counter); - printf("__Eq%d:\n", counter); - printf(" MovI64 112, 1\n"); - printf("__DoneEqCheck%d:\n", counter); - printf(" pushstack 112\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_EQ, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "not")) { - printf(" popstack 96\n"); - printf(" Not64 96\n"); - printf(" pushstack 96\n"); + IRValue x1; + if (irVStack.cnt >= 1) { + x1 = lz_da_pop(irVStack); + } else if (irVStack.cnt == 0) { + x1 = (IRValue) { + .typ = IRVAL_STACK, + .val = 1 + }; + } + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_NOT, + .arg1 = x1 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "band")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" AndR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_AND, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "bor")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" OrR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_OR, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "xor")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" xorR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_XOR, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "u+")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" AddR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_UADD, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "u-")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" SubR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_USUB, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "u*")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" MulR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_UMUL, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "u/")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" DivR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_UDIV, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "u%")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" ModR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_UMOD, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "u>")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" Cmp64 98, 97\n"); - printf(" JmpIP __Cmp%d\n", counter); - printf(" MovI64 112, 0\n"); - printf(" Jmp __DoneCmp%d\n", counter); - printf("__Cmp%d:\n", counter); - printf(" MovI64 112, 1\n"); - printf("__DoneCmp%d:\n", counter); - printf(" pushstack 112\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_UGT, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "u<")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" Cmp64 98, 97\n"); - printf(" JmpIN __Cmp%d\n", counter); - printf(" MovI64 112, 0\n"); - printf(" Jmp __DoneCmp%d\n", counter); - printf("__Cmp%d:\n", counter); - printf(" MovI64 112, 1\n"); - printf("__DoneCmp%d:\n", counter); - printf(" pushstack 112\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_ULT, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "i+")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" AddR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_UADD, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "i-")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" SubR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_USUB, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "i*")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" IMulR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_IMUL, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "i/")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" IDivR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_IDIV, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "i%")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" IModR64 98, 97\n"); - printf(" pushstack 98\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_IMOD, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "i>")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" ICmp64 98, 97\n"); - printf(" JmpIP __Cmp%d\n", counter); - printf(" MovI64 112, 0\n"); - printf(" Jmp __DoneCmp%d\n", counter); - printf("__Cmp%d:\n", counter); - printf(" MovI64 112, 1\n"); - printf("__DoneCmp%d:\n", counter); - printf(" pushstack 112\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_ILT, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "i<")) { - printf(" popstack 97\n"); - printf(" popstack 98\n"); - printf(" ICmp64 98, 97\n"); - printf(" JmpIN __Cmp%d\n", counter); - printf(" MovI64 112, 0\n"); - printf(" Jmp __DoneCmp%d\n", counter); - printf("__Cmp%d:\n", counter); - printf(" MovI64 112, 1\n"); - printf("__DoneCmp%d:\n", counter); - printf(" pushstack 112\n"); - break; - } - - if (SBeq(&tokenAccumulator, "pop")) { - printf(" popstack 113\n"); + IR_GET_2_ARGS + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_IGT, + .arg1 = x1, + .arg2 = x2 + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); break; } if (SBeq(&tokenAccumulator, "$inc")) { @@ -511,6 +766,11 @@ codegen: printf("__fp_user_"LZ_STR_FMT":\n", LZ_STR_PRINTF(tokenAccumulator)); isProc = false; + IRValue arg = (IRValue) { + .typ = IRVAL_ARG, + .val = 0 + }; + if (tokenAccumulator.cnt < 127) { memcpy(funcName, tokenAccumulator.data, tokenAccumulator.cnt); funcName[tokenAccumulator.cnt] = 0; @@ -521,6 +781,8 @@ codegen: break; } if (tokenAccumulator.data[0] == ':') { + IRComplete(&irStatements, &irVStack); + vstackUnderflows = 0; printf(" Call __fp_user_"LZ_STR_FMT"\n", tokenAccumulator.cnt-1, tokenAccumulator.data+1); @@ -553,10 +815,26 @@ codegen: lz_da_append(vars, v); allocHead += 8; } - printf(" popstack 120\n"); - printf(" ; %s:%s\n", funcName, varName); - printf(" MovI64 121, 0x%16lX\n", addr); - printf(" St64 120, 121\n"); + IRValue x1; + if (irVStack.cnt >= 1) { + x1 = lz_da_pop(irVStack); + } else if (irVStack.cnt == 0) { + x1 = (IRValue) { + .typ = IRVAL_STACK, + .val = ++vstackUnderflows + }; + } + + IRValue dstReg = (IRValue) { + .typ = IRVAL_MEMORY, + .val = addr + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_NOP, + .arg1 = x1 + }; + lz_da_append(irStatements, s); break; } if (tokenAccumulator.data[0] == '&') { @@ -581,9 +859,23 @@ codegen: varName, funcName); exit(1); } - printf(" MovI64 121, 0x%16lX\n", addr); - printf(" Ld64 120, 121\n"); - printf(" pushstack 120\n"); + + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + + IRValue x1 = (IRValue) { + .typ = IRVAL_MEMORY, + .val = addr + }; + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_NOP, + .arg1 = x1 + }; + lz_da_append(irStatements, s); + lz_da_append(irVStack, dstReg); break; } // Iirc there's not a general thing for identifiers so just fail? @@ -592,25 +884,58 @@ codegen: exit(0); } case TOKEN_INTLIT: { - printf(" MovI64 103, "LZ_STR_FMT"\n", - LZ_STR_PRINTF(tokenAccumulator)); - printf(" pushstack 103\n"); + uint64_t x = lz_sb_atoll(&tokenAccumulator); + IRValue v = (IRValue) { + .typ = IRVAL_CONSTANT, + .val = x + }; + lz_da_append(irVStack, v); break; } case TOKEN_HEXLIT: { - printf(" MovI64 103, "LZ_STR_FMT"\n", - LZ_STR_PRINTF(tokenAccumulator)); - printf(" pushstack 103\n"); + uint64_t x = lz_sb_readhex(&tokenAccumulator); + IRValue v = (IRValue) { + .typ = IRVAL_CONSTANT, + .val = x + }; + lz_da_append(irVStack, v); break; } case TOKEN_STRINGLIT: { + IRValue dstReg = (IRValue) { + .typ = IRVAL_VIRTUAL, + .val = ++irVCount + }; + // This is a bad way of doing strings tbh printf(" Jmp endstring%d\n", counter); printf("string%d db \""LZ_STR_FMT"\", 0\n", counter, LZ_STR_PRINTF(tokenAccumulator)); printf("endstring%d:\n", counter); printf(" MovI64 100, string%d\n", counter); - printf(" pushstack 100\n", counter); + IRStatement s = (IRStatement) { + .dst = dstReg, + .op = IR_NOP, + .arg1 = IR_STR + }; + lz_da_append(irVStack, dstReg); + lz_da_append(irStatements, s); + break; + + //IRComplete(&irStatements, &irVStack); + //vstackUnderflows = 0; + //printf(" Jmp endstring%d\n", counter); + //printf("string%d db \""LZ_STR_FMT"\", 0\n", + // counter, + // LZ_STR_PRINTF(tokenAccumulator)); + //printf("endstring%d:\n", counter); + //printf(" MovI64 100, string%d\n", counter); + //printf(" pushstack 100\n", counter); + // IRValue v = (IRValue) { + // .typ = IRVAL_STACK, + // .val = 1 + // }; + // lz_da_append(irVStack, v); break; } default: { diff --git a/flagpole/tests/fibloop.fp b/flagpole/tests/fibloop.fp new file mode 100644 index 0000000..e10887b --- /dev/null +++ b/flagpole/tests/fibloop.fp @@ -0,0 +1,14 @@ +$inc fvmstd.fp + +proc main + 92 @N + 0 @a + 1 @b + while &N 0 u> do + &a &b u+ @c + &b @a + &c @b + &N 1 u- @N + endwhile + &b :putuint :newline +endproc diff --git a/src/interp.c b/src/interp.c index 8707474..c2a9cdd 100644 --- a/src/interp.c +++ b/src/interp.c @@ -5,9 +5,11 @@ #include #define LAZY_IMPL #include "lazy.h" +#include #define PAGE_SIZE 4096 -#define DEBUG false +//#define DEBUG +//#define TIME // MMIO is defined between 0xC000000000000000 and 0xD000000000000000 // Some of that is still normal memory though #define UART_TX 0xCFFFFFFFFFFFFFFD @@ -122,27 +124,47 @@ int main(int argc, char **argv) { bool positiveFlag = false; bool negativeFlag = false; bool parityFlag = false; +#ifdef TIME + Lz_HM(unsigned char, uint) instrTimes; + Lz_HM(unsigned char, uint) instrCounts; + lz_hm_init(instrTimes); + lz_hm_init(instrCounts); +#endif while (1) { unsigned char inst = memory_get8(xPc); - if (DEBUG) printf("INST: %02X\n", inst); - if (DEBUG) printf("IP: %16lX\n", xPc); + #ifdef DEBUG + printf("INST: %02X\n", inst); + printf("IP: %16lX\n", xPc); + #endif size_t inpflag = (inst & 0xE0) >> 5; size_t inpcnt = flag_bytecnt[inpflag]; - if (DEBUG) printf("Cnt: %zu\n", inpcnt); + #ifdef DEBUG + printf("Cnt: %zu\n", inpcnt); + #endif unsigned char inputs[9]; for (size_t i = 0; i < inpcnt; ++i) { inputs[i] = memory_get8(xPc+i+1); - if (DEBUG) { + #ifdef DEBUG printf("X%d: 0x%8X\n", i, inputs[i]); - } + #endif } + #ifdef TIME + if (lz_hm_exists(instrCounts, inst)) { + uint x = lz_hm_get(instrCounts, inst); + lz_hm_remove(instrCounts, inst); + lz_hm_add(instrCounts, inst, x+1); + } else { + lz_hm_add(instrCounts, inst, 1); + } + clock_t startTime = clock(); + #endif xPc += 1; xPc += inpcnt; switch (inst) { case 0x00: { // Halt printf("\nHALT\n"); - exit(0); + goto halt; break; } case 0xE9: { // MovI64 @@ -156,13 +178,13 @@ int main(int argc, char **argv) { unsigned char x7 = inputs[7]; unsigned char x8 = inputs[8]; uint64_t val = - ((uint64_t)x1 << 56) + - ((uint64_t)x2 << 48) + - ((uint64_t)x3 << 40) + - ((uint64_t)x4 << 32) + - ((uint64_t)x5 << 24) + - ((uint64_t)x6 << 16) + - ((uint64_t)x7 << 8) + + ((uint64_t)x1 << 56) | + ((uint64_t)x2 << 48) | + ((uint64_t)x3 << 40) | + ((uint64_t)x4 << 32) | + ((uint64_t)x5 << 24) | + ((uint64_t)x6 << 16) | + ((uint64_t)x7 << 8) | ((uint64_t)x8 << 0); registers[reg] = val; registers[0] = 0; @@ -183,11 +205,11 @@ int main(int argc, char **argv) { case 0x93: { // Ld8 unsigned char dst = inputs[0]; unsigned char addr = inputs[1]; - if (DEBUG) { + #ifdef DEBUG printf("Ld8\n"); printf("Dst val: %8X\n", registers[dst]); printf("Addr val: %8X\n", registers[addr]); - } + #endif registers[dst] = memory_get8(registers[addr]); break; } @@ -324,7 +346,9 @@ int main(int argc, char **argv) { case 0xC1: { // JmpIZ unsigned char addr = inputs[0]; if (zeroFlag) { - if (DEBUG) printf("Jump!\n"); + #ifdef DEBUG + printf("Jump!\n"); + #endif xPc = registers[addr]; } break; @@ -332,7 +356,9 @@ int main(int argc, char **argv) { case 0xC3: { // JmpIP unsigned char addr = inputs[0]; if (positiveFlag) { - if (DEBUG) printf("Jump!\n"); + #ifdef DEBUG + printf("Jump!\n"); + #endif xPc = registers[addr]; } break; @@ -340,7 +366,9 @@ int main(int argc, char **argv) { case 0xC2: { // JmpIN unsigned char addr = inputs[0]; if (negativeFlag) { - if (DEBUG) printf("Jump!\n"); + #ifdef DEBUG + printf("Jump!\n"); + #endif xPc = registers[addr]; } break; @@ -348,7 +376,9 @@ int main(int argc, char **argv) { case 0xC8: { // JmpIE unsigned char addr = inputs[0]; if (!parityFlag) { - if (DEBUG) printf("Jump!\n"); + #ifdef DEBUG + printf("Jump!\n"); + #endif xPc = registers[addr]; } break; @@ -377,7 +407,39 @@ int main(int argc, char **argv) { exit(1); } } + #ifdef TIME + clock_t endTime = clock(); + clock_t diff = endTime - startTime ; + uint usec = diff * 1000000 / CLOCKS_PER_SEC; + + if (lz_hm_exists(instrTimes, inst)) { + uint x = lz_hm_get(instrTimes, inst); + lz_hm_remove(instrTimes, inst); + lz_hm_add(instrTimes, inst, x+usec); + } else { + lz_hm_add(instrTimes, inst, usec); + } + #endif } +halt: +#ifdef TIME + // TODO: Fix this shit + for (int i = 0; i < instrTimes.cap; ++i) { + if (instrTimes.exists[i]) { + printf("Instr: %2x used %dus\n", + instrTimes.keys[i], + instrTimes.vals[i]); + } + } + for (int i = 0; i < instrCounts.cap; ++i) { + if (instrCounts.exists[i]) { + printf("Instr: %2x used %d times\n", + instrCounts.keys[i], + instrCounts.vals[i]); + } + } +#endif + return 0; }