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)
This commit is contained in:
parent
f738034ce4
commit
ca1ee83377
24 changed files with 1018 additions and 176 deletions
|
|
@ -34,7 +34,7 @@ targets = {
|
||||||
for f in p:lines() do
|
for f in p:lines() do
|
||||||
base = f:match("([^/]+)%.c$")
|
base = f:match("([^/]+)%.c$")
|
||||||
obj = "build/"..base..".o"
|
obj = "build/"..base..".o"
|
||||||
cc = "cc -c '"..f.."' -o '"..obj.."' "..includes
|
cc = "cc -c -O3 '"..f.."' -o '"..obj.."' "..includes
|
||||||
e,h,c = execute(cc)
|
e,h,c = execute(cc)
|
||||||
if c ~= 0 and c ~= nil then
|
if c ~= 0 and c ~= nil then
|
||||||
print("Compilation Error")
|
print("Compilation Error")
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ targets = {
|
||||||
for f in p:lines() do
|
for f in p:lines() do
|
||||||
base = f:match("([^/]+)%.c$")
|
base = f:match("([^/]+)%.c$")
|
||||||
obj = "build/"..base..".o"
|
obj = "build/"..base..".o"
|
||||||
cc = "cc -c '"..f.."' -o '"..obj.."' "..includes
|
cc = "cc -c -ggdb '"..f.."' -o '"..obj.."' "..includes
|
||||||
e,h,c = execute(cc)
|
e,h,c = execute(cc)
|
||||||
if c ~= 0 and c ~= nil then
|
if c ~= 0 and c ~= nil then
|
||||||
print("Compilation Error")
|
print("Compilation Error")
|
||||||
|
|
|
||||||
1
flagpole/fvm.inc
Symbolic link
1
flagpole/fvm.inc
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../tests/fvm.inc
|
||||||
|
|
@ -64,7 +64,7 @@ proc putuint
|
||||||
1 @divisor
|
1 @divisor
|
||||||
|
|
||||||
while &val &divisor u/ 9 u> do
|
while &val &divisor u/ 9 u> do
|
||||||
10 &divisor u* @divisor
|
&divisor 10 u* @divisor
|
||||||
endwhile
|
endwhile
|
||||||
|
|
||||||
while &divisor 0 u> do
|
while &divisor 0 u> do
|
||||||
|
|
@ -90,7 +90,7 @@ proc puts
|
||||||
dup ld8 :putchar
|
dup ld8 :putchar
|
||||||
1 u+
|
1 u+
|
||||||
endwhile
|
endwhile
|
||||||
pop
|
drop
|
||||||
endproc
|
endproc
|
||||||
|
|
||||||
proc newline
|
proc newline
|
||||||
|
|
|
||||||
5
flagpole/irtests/2vars.fp
Normal file
5
flagpole/irtests/2vars.fp
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
proc main
|
||||||
|
2 @a
|
||||||
|
3 @b
|
||||||
|
&a &b u+
|
||||||
|
endproc
|
||||||
13
flagpole/irtests/cat.fp
Normal file
13
flagpole/irtests/cat.fp
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
proc putchar
|
||||||
|
0xCFFFFFFFFFFFFFFD st8
|
||||||
|
endproc
|
||||||
|
|
||||||
|
proc getchar
|
||||||
|
0xCFFFFFFFFFFFFFFE ld8
|
||||||
|
endproc
|
||||||
|
|
||||||
|
proc main
|
||||||
|
while 1 do
|
||||||
|
:getchar :putchar
|
||||||
|
endwhile
|
||||||
|
endproc
|
||||||
11
flagpole/irtests/cat1.fp
Normal file
11
flagpole/irtests/cat1.fp
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
proc putchar
|
||||||
|
0xCFFFFFFFFFFFFFFD st8
|
||||||
|
endproc
|
||||||
|
|
||||||
|
proc getchar
|
||||||
|
0xCFFFFFFFFFFFFFFE ld8
|
||||||
|
endproc
|
||||||
|
|
||||||
|
proc main
|
||||||
|
:getchar :putchar
|
||||||
|
endproc
|
||||||
10
flagpole/irtests/divgrow.fp
Normal file
10
flagpole/irtests/divgrow.fp
Normal file
|
|
@ -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
|
||||||
3
flagpole/irtests/dumbstring.fp
Normal file
3
flagpole/irtests/dumbstring.fp
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
proc main
|
||||||
|
"String" 1 u+
|
||||||
|
endproc
|
||||||
5
flagpole/irtests/eq.fp
Normal file
5
flagpole/irtests/eq.fp
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
proc main
|
||||||
|
1
|
||||||
|
2 1 u-
|
||||||
|
==
|
||||||
|
endproc
|
||||||
6
flagpole/irtests/gt.fp
Normal file
6
flagpole/irtests/gt.fp
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
proc main
|
||||||
|
5
|
||||||
|
if 5 3 u> then
|
||||||
|
drop 3
|
||||||
|
endif
|
||||||
|
endproc
|
||||||
7
flagpole/irtests/hex.fp
Normal file
7
flagpole/irtests/hex.fp
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
proc putchar
|
||||||
|
0xCFFFFFFFFFFFFFFD st8
|
||||||
|
endproc
|
||||||
|
|
||||||
|
proc main
|
||||||
|
0x48 :putchar
|
||||||
|
endproc
|
||||||
10
flagpole/irtests/loop.fp
Normal file
10
flagpole/irtests/loop.fp
Normal file
|
|
@ -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
|
||||||
5
flagpole/irtests/num.fp
Normal file
5
flagpole/irtests/num.fp
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
$inc fvmstd.fp
|
||||||
|
|
||||||
|
proc main
|
||||||
|
4 :putuint
|
||||||
|
endproc
|
||||||
5
flagpole/irtests/putuint.fp
Normal file
5
flagpole/irtests/putuint.fp
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
$inc fvmstd.fp
|
||||||
|
|
||||||
|
proc main
|
||||||
|
23 :putuint
|
||||||
|
endproc
|
||||||
3
flagpole/irtests/uadd.fp
Normal file
3
flagpole/irtests/uadd.fp
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
proc main
|
||||||
|
34 35 u+
|
||||||
|
endproc
|
||||||
3
flagpole/irtests/usub.fp
Normal file
3
flagpole/irtests/usub.fp
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
proc main
|
||||||
|
500 80 u-
|
||||||
|
endproc
|
||||||
4
flagpole/irtests/var.fp
Normal file
4
flagpole/irtests/var.fp
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
proc main
|
||||||
|
0x40 @a
|
||||||
|
&a 2 u+
|
||||||
|
endproc
|
||||||
14
flagpole/irtests/varmover.fp
Normal file
14
flagpole/irtests/varmover.fp
Normal file
|
|
@ -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
|
||||||
285
flagpole/src/ir.c
Normal file
285
flagpole/src/ir.c
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
51
flagpole/src/ir.h
Normal file
51
flagpole/src/ir.h
Normal file
|
|
@ -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);
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "lazy.h"
|
#include "lazy.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
#include "var.h"
|
#include "var.h"
|
||||||
|
#include "ir.h"
|
||||||
|
|
||||||
bool is_int_literal(Lz_SB *sb) {
|
bool is_int_literal(Lz_SB *sb) {
|
||||||
for (int i = 0; i < sb->cnt; ++i) {
|
for (int i = 0; i < sb->cnt; ++i) {
|
||||||
|
|
@ -78,6 +79,24 @@ void commentStack(void *stack) {
|
||||||
printf("\n");
|
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) {
|
static inline bool isKW(Lz_SB *sb) {
|
||||||
return
|
return
|
||||||
SBeq(sb, "proc")
|
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 main(uint argc, char **argv) {
|
||||||
int opt;
|
int opt;
|
||||||
Lz_DA(FILE *) inpfiles = {};
|
Lz_DA(FILE *) inpfiles = {};
|
||||||
|
|
@ -152,24 +193,28 @@ int main(uint argc, char **argv) {
|
||||||
Lz_DA(int) labelStack = {0};
|
Lz_DA(int) labelStack = {0};
|
||||||
uint64_t allocHead = 0x7000000000000000;
|
uint64_t allocHead = 0x7000000000000000;
|
||||||
char funcName[128];
|
char funcName[128];
|
||||||
Lz_DA(Variable) vars;
|
Lz_DA(Variable) vars = {0};
|
||||||
char newchar;
|
char newchar;
|
||||||
|
Lz_DA(IRStatement) irStatements = {0};
|
||||||
|
Lz_DA(IRValue) irVStack = {0};
|
||||||
|
int irVCount = 0;
|
||||||
|
int vstackUnderflows = 0;
|
||||||
printf("include 'fvm.inc'\n");
|
printf("include 'fvm.inc'\n");
|
||||||
printf("define STACK_START 0x6000000000000000\n");
|
printf("define STACK_START 0x6000000000000000\n");
|
||||||
printf("define STACK_SP 125\n");
|
printf("define STACK_SP 125\n");
|
||||||
|
printf("define STACK_INC 126\n");
|
||||||
printf("org 0x4000000000000000\n");
|
printf("org 0x4000000000000000\n");
|
||||||
printf(" MovI64 STACK_SP, STACK_START\n");
|
printf(" MovI64 STACK_SP, STACK_START\n");
|
||||||
|
printf(" MovI64 STACK_INC, 8\n");
|
||||||
printf(" Call __fp_user_main\n");
|
printf(" Call __fp_user_main\n");
|
||||||
printf(" Halt\n");
|
printf(" Halt\n");
|
||||||
printf("macro pushstack reg\n");
|
printf("macro pushstack reg\n");
|
||||||
printf(" MovI64 124, 8\n");
|
printf(" SubR64 STACK_SP, STACK_INC\n");
|
||||||
printf(" SubR64 STACK_SP, 124\n");
|
|
||||||
printf(" St64 reg, STACK_SP\n");
|
printf(" St64 reg, STACK_SP\n");
|
||||||
printf("end macro\n\n");
|
printf("end macro\n\n");
|
||||||
printf("macro popstack reg\n");
|
printf("macro popstack reg\n");
|
||||||
printf(" MovI64 124, 8\n");
|
|
||||||
printf(" Ld64 reg, STACK_SP\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");
|
printf("end macro\n\n");
|
||||||
// Genuinely idk why goto is possessing me today
|
// Genuinely idk why goto is possessing me today
|
||||||
compileStart:
|
compileStart:
|
||||||
|
|
@ -182,32 +227,32 @@ compileStart:
|
||||||
if (tokenAccumulator.cnt == 0) continue;
|
if (tokenAccumulator.cnt == 0) continue;
|
||||||
if (is_int_literal(&tokenAccumulator)) {
|
if (is_int_literal(&tokenAccumulator)) {
|
||||||
currTokenKind = TOKEN_INTLIT;
|
currTokenKind = TOKEN_INTLIT;
|
||||||
goto codegen;
|
goto codegenIR;
|
||||||
} else if (is_float_literal(&tokenAccumulator)) {
|
} else if (is_float_literal(&tokenAccumulator)) {
|
||||||
currTokenKind = TOKEN_FLOATLIT;
|
currTokenKind = TOKEN_FLOATLIT;
|
||||||
goto codegen;
|
goto codegenIR;
|
||||||
} else if (is_double_literal(&tokenAccumulator)) {
|
} else if (is_double_literal(&tokenAccumulator)) {
|
||||||
currTokenKind = TOKEN_DOUBLELIT;
|
currTokenKind = TOKEN_DOUBLELIT;
|
||||||
goto codegen;
|
goto codegenIR;
|
||||||
} else if (is_hex_literal(&tokenAccumulator)) {
|
} else if (is_hex_literal(&tokenAccumulator)) {
|
||||||
currTokenKind = TOKEN_HEXLIT;
|
currTokenKind = TOKEN_HEXLIT;
|
||||||
goto codegen;
|
goto codegenIR;
|
||||||
} else if (is_bin_literal(&tokenAccumulator)) {
|
} else if (is_bin_literal(&tokenAccumulator)) {
|
||||||
currTokenKind = TOKEN_BINLIT;
|
currTokenKind = TOKEN_BINLIT;
|
||||||
goto codegen;
|
goto codegenIR;
|
||||||
} else {
|
} else {
|
||||||
currTokenKind = TOKEN_IDENTIFIER;
|
currTokenKind = TOKEN_IDENTIFIER;
|
||||||
if (isKW(&tokenAccumulator)) {
|
if (isKW(&tokenAccumulator)) {
|
||||||
currTokenKind = TOKEN_KEYWORD;
|
currTokenKind = TOKEN_KEYWORD;
|
||||||
}
|
}
|
||||||
goto codegen;
|
goto codegenIR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (newchar == '"') {
|
if (newchar == '"') {
|
||||||
if (isQuote) {
|
if (isQuote) {
|
||||||
currTokenKind = TOKEN_STRINGLIT;
|
currTokenKind = TOKEN_STRINGLIT;
|
||||||
isQuote = false;
|
isQuote = false;
|
||||||
goto codegen;
|
goto codegenIR;
|
||||||
} else {
|
} else {
|
||||||
if (tokenAccumulator.cnt != 0) {
|
if (tokenAccumulator.cnt != 0) {
|
||||||
fprintf(stderr, "error %d\n", __LINE__);
|
fprintf(stderr, "error %d\n", __LINE__);
|
||||||
|
|
@ -220,7 +265,8 @@ compileStart:
|
||||||
}
|
}
|
||||||
lz_da_append(tokenAccumulator, newchar);
|
lz_da_append(tokenAccumulator, newchar);
|
||||||
continue;
|
continue;
|
||||||
codegen:
|
// Names suck but this also generates some asm for blocks
|
||||||
|
codegenIR:
|
||||||
//printf("I must gen code i am now Amista Azozin\n");
|
//printf("I must gen code i am now Amista Azozin\n");
|
||||||
//fprintf(stderr,"Token type: %d\n", currTokenKind);
|
//fprintf(stderr,"Token type: %d\n", currTokenKind);
|
||||||
//fprintf(stderr,"Tok: "LZ_STR_FMT"\n", LZ_STR_PRINTF(tokenAccumulator));
|
//fprintf(stderr,"Tok: "LZ_STR_FMT"\n", LZ_STR_PRINTF(tokenAccumulator));
|
||||||
|
|
@ -232,6 +278,8 @@ codegen:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "endproc")) {
|
if (SBeq(&tokenAccumulator, "endproc")) {
|
||||||
|
IRComplete(&irStatements, &irVStack);
|
||||||
|
vstackUnderflows = 0;
|
||||||
printf(" Ret\n");
|
printf(" Ret\n");
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
if (labelStack.cnt != 0) {
|
if (labelStack.cnt != 0) {
|
||||||
|
|
@ -243,53 +291,113 @@ codegen:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "return")) {
|
if (SBeq(&tokenAccumulator, "return")) {
|
||||||
|
IRComplete(&irStatements, &irVStack);
|
||||||
|
vstackUnderflows = 0;
|
||||||
printf(" Ret\n");
|
printf(" Ret\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "ld8")) {
|
if (SBeq(&tokenAccumulator, "ld8")) {
|
||||||
printf(" popstack 101\n");
|
IRValue x1;
|
||||||
printf(" Ld8 102, 101\n");
|
if (irVStack.cnt >= 1) {
|
||||||
printf(" pushstack 102\n");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "st8")) {
|
if (SBeq(&tokenAccumulator, "st8")) {
|
||||||
printf(" popstack 101\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 102\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" St8 102, 101\n");
|
.typ = IRVAL_CONSTANT,
|
||||||
|
};
|
||||||
|
IRStatement s = (IRStatement) {
|
||||||
|
.dst = dstReg,
|
||||||
|
.op = IR_ST8,
|
||||||
|
.arg1 = x1,
|
||||||
|
.arg2 = x2
|
||||||
|
};
|
||||||
|
lz_da_append(irStatements, s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "dup")) {
|
if (SBeq(&tokenAccumulator, "dup")) {
|
||||||
|
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(" popstack 106\n");
|
||||||
printf(" pushstack 106\n");
|
printf(" pushstack 106\n");
|
||||||
printf(" pushstack 106\n");
|
printf(" pushstack 106\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "swap")) {
|
if (SBeq(&tokenAccumulator, "swap")) {
|
||||||
printf(" popstack 118\n");
|
IRValue x1, x2;
|
||||||
printf(" popstack 119\n");
|
if (irVStack.cnt >= 2) {
|
||||||
printf(" pushstack 118\n");
|
x1 = lz_da_pop(irVStack);
|
||||||
printf(" pushstack 119\n");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "drop")) {
|
if (SBeq(&tokenAccumulator, "drop")) {
|
||||||
|
if (irVStack.cnt != 0)
|
||||||
|
lz_da_pop(irVStack);
|
||||||
|
else
|
||||||
printf(" popstack 118\n");
|
printf(" popstack 118\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "while")) {
|
if (SBeq(&tokenAccumulator, "while")) {
|
||||||
|
IRComplete(&irStatements, &irVStack);
|
||||||
lz_da_append(labelStack, counter);
|
lz_da_append(labelStack, counter);
|
||||||
commentStack(&labelStack);
|
commentStack(&labelStack);
|
||||||
printf("__whilehead_%d:\n", counter);
|
printf("__whilehead_%d:\n", counter);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "do")) {
|
if (SBeq(&tokenAccumulator, "do")) {
|
||||||
|
IRComplete(&irStatements, &irVStack);
|
||||||
|
vstackUnderflows = 0;
|
||||||
int lbl = lz_da_pop(labelStack);
|
int lbl = lz_da_pop(labelStack);
|
||||||
lz_da_append(labelStack, lbl);
|
lz_da_append(labelStack, lbl);
|
||||||
|
// TODO: Change flag setting to IR's job
|
||||||
printf(" popstack 108\n");
|
printf(" popstack 108\n");
|
||||||
printf(" RSetF 108\n");
|
printf(" RSetF 108\n");
|
||||||
printf(" JmpIE __whiletail_%d\n", lbl);
|
printf(" JmpIE __whiletail_%d\n", lbl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "endwhile")) {
|
if (SBeq(&tokenAccumulator, "endwhile")) {
|
||||||
|
IRComplete(&irStatements, &irVStack);
|
||||||
|
vstackUnderflows = 0;
|
||||||
int lbl = lz_da_pop(labelStack);
|
int lbl = lz_da_pop(labelStack);
|
||||||
commentStack(&labelStack);
|
commentStack(&labelStack);
|
||||||
printf(" Jmp __whilehead_%d\n", lbl);
|
printf(" Jmp __whilehead_%d\n", lbl);
|
||||||
|
|
@ -302,6 +410,8 @@ codegen:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "then")) {
|
if (SBeq(&tokenAccumulator, "then")) {
|
||||||
|
IRComplete(&irStatements, &irVStack);
|
||||||
|
vstackUnderflows = 0;
|
||||||
commentStack(&labelStack);
|
commentStack(&labelStack);
|
||||||
int lbl = lz_da_pop(labelStack);
|
int lbl = lz_da_pop(labelStack);
|
||||||
lz_da_append(labelStack, lbl);
|
lz_da_append(labelStack, lbl);
|
||||||
|
|
@ -312,177 +422,322 @@ codegen:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SBeq(&tokenAccumulator, "endif")) {
|
if (SBeq(&tokenAccumulator, "endif")) {
|
||||||
|
IRComplete(&irStatements, &irVStack);
|
||||||
|
vstackUnderflows = 0;
|
||||||
commentStack(&labelStack);
|
commentStack(&labelStack);
|
||||||
int lbl = lz_da_pop(labelStack);
|
int lbl = lz_da_pop(labelStack);
|
||||||
printf("__iftail_%d:\n", lbl);
|
printf("__iftail_%d:\n", lbl);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "==")) {
|
if (SBeq(&tokenAccumulator, "==")) {
|
||||||
// Hacked like crazy...
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 110\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" popstack 111\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" Cmp64 110, 111\n");
|
.val = ++irVCount
|
||||||
printf(" JmpIZ __Eq%d\n", counter);
|
};
|
||||||
printf(" MovI64 112, 0\n");
|
IRStatement s = (IRStatement) {
|
||||||
printf(" Jmp __DoneEqCheck%d\n", counter);
|
.dst = dstReg,
|
||||||
printf("__Eq%d:\n", counter);
|
.op = IR_EQ,
|
||||||
printf(" MovI64 112, 1\n");
|
.arg1 = x1,
|
||||||
printf("__DoneEqCheck%d:\n", counter);
|
.arg2 = x2
|
||||||
printf(" pushstack 112\n");
|
};
|
||||||
|
lz_da_append(irVStack, dstReg);
|
||||||
|
lz_da_append(irStatements, s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "not")) {
|
if (SBeq(&tokenAccumulator, "not")) {
|
||||||
printf(" popstack 96\n");
|
IRValue x1;
|
||||||
printf(" Not64 96\n");
|
if (irVStack.cnt >= 1) {
|
||||||
printf(" pushstack 96\n");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "band")) {
|
if (SBeq(&tokenAccumulator, "band")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" AndR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "bor")) {
|
if (SBeq(&tokenAccumulator, "bor")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" OrR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "xor")) {
|
if (SBeq(&tokenAccumulator, "xor")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" xorR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "u+")) {
|
if (SBeq(&tokenAccumulator, "u+")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" AddR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "u-")) {
|
if (SBeq(&tokenAccumulator, "u-")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" SubR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "u*")) {
|
if (SBeq(&tokenAccumulator, "u*")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" MulR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "u/")) {
|
if (SBeq(&tokenAccumulator, "u/")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" DivR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "u%")) {
|
if (SBeq(&tokenAccumulator, "u%")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" ModR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "u>")) {
|
if (SBeq(&tokenAccumulator, "u>")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" Cmp64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" JmpIP __Cmp%d\n", counter);
|
.val = ++irVCount
|
||||||
printf(" MovI64 112, 0\n");
|
};
|
||||||
printf(" Jmp __DoneCmp%d\n", counter);
|
IRStatement s = (IRStatement) {
|
||||||
printf("__Cmp%d:\n", counter);
|
.dst = dstReg,
|
||||||
printf(" MovI64 112, 1\n");
|
.op = IR_UGT,
|
||||||
printf("__DoneCmp%d:\n", counter);
|
.arg1 = x1,
|
||||||
printf(" pushstack 112\n");
|
.arg2 = x2
|
||||||
|
};
|
||||||
|
lz_da_append(irVStack, dstReg);
|
||||||
|
lz_da_append(irStatements, s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "u<")) {
|
if (SBeq(&tokenAccumulator, "u<")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" Cmp64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" JmpIN __Cmp%d\n", counter);
|
.val = ++irVCount
|
||||||
printf(" MovI64 112, 0\n");
|
};
|
||||||
printf(" Jmp __DoneCmp%d\n", counter);
|
IRStatement s = (IRStatement) {
|
||||||
printf("__Cmp%d:\n", counter);
|
.dst = dstReg,
|
||||||
printf(" MovI64 112, 1\n");
|
.op = IR_ULT,
|
||||||
printf("__DoneCmp%d:\n", counter);
|
.arg1 = x1,
|
||||||
printf(" pushstack 112\n");
|
.arg2 = x2
|
||||||
|
};
|
||||||
|
lz_da_append(irVStack, dstReg);
|
||||||
|
lz_da_append(irStatements, s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "i+")) {
|
if (SBeq(&tokenAccumulator, "i+")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" AddR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "i-")) {
|
if (SBeq(&tokenAccumulator, "i-")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" SubR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "i*")) {
|
if (SBeq(&tokenAccumulator, "i*")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" IMulR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "i/")) {
|
if (SBeq(&tokenAccumulator, "i/")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" IDivR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "i%")) {
|
if (SBeq(&tokenAccumulator, "i%")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" IModR64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" pushstack 98\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "i>")) {
|
if (SBeq(&tokenAccumulator, "i>")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" ICmp64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" JmpIP __Cmp%d\n", counter);
|
.val = ++irVCount
|
||||||
printf(" MovI64 112, 0\n");
|
};
|
||||||
printf(" Jmp __DoneCmp%d\n", counter);
|
IRStatement s = (IRStatement) {
|
||||||
printf("__Cmp%d:\n", counter);
|
.dst = dstReg,
|
||||||
printf(" MovI64 112, 1\n");
|
.op = IR_ILT,
|
||||||
printf("__DoneCmp%d:\n", counter);
|
.arg1 = x1,
|
||||||
printf(" pushstack 112\n");
|
.arg2 = x2
|
||||||
|
};
|
||||||
|
lz_da_append(irVStack, dstReg);
|
||||||
|
lz_da_append(irStatements, s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "i<")) {
|
if (SBeq(&tokenAccumulator, "i<")) {
|
||||||
printf(" popstack 97\n");
|
IR_GET_2_ARGS
|
||||||
printf(" popstack 98\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" ICmp64 98, 97\n");
|
.typ = IRVAL_VIRTUAL,
|
||||||
printf(" JmpIN __Cmp%d\n", counter);
|
.val = ++irVCount
|
||||||
printf(" MovI64 112, 0\n");
|
};
|
||||||
printf(" Jmp __DoneCmp%d\n", counter);
|
IRStatement s = (IRStatement) {
|
||||||
printf("__Cmp%d:\n", counter);
|
.dst = dstReg,
|
||||||
printf(" MovI64 112, 1\n");
|
.op = IR_IGT,
|
||||||
printf("__DoneCmp%d:\n", counter);
|
.arg1 = x1,
|
||||||
printf(" pushstack 112\n");
|
.arg2 = x2
|
||||||
break;
|
};
|
||||||
}
|
lz_da_append(irVStack, dstReg);
|
||||||
|
lz_da_append(irStatements, s);
|
||||||
if (SBeq(&tokenAccumulator, "pop")) {
|
|
||||||
printf(" popstack 113\n");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (SBeq(&tokenAccumulator, "$inc")) {
|
if (SBeq(&tokenAccumulator, "$inc")) {
|
||||||
|
|
@ -511,6 +766,11 @@ codegen:
|
||||||
printf("__fp_user_"LZ_STR_FMT":\n",
|
printf("__fp_user_"LZ_STR_FMT":\n",
|
||||||
LZ_STR_PRINTF(tokenAccumulator));
|
LZ_STR_PRINTF(tokenAccumulator));
|
||||||
isProc = false;
|
isProc = false;
|
||||||
|
IRValue arg = (IRValue) {
|
||||||
|
.typ = IRVAL_ARG,
|
||||||
|
.val = 0
|
||||||
|
};
|
||||||
|
|
||||||
if (tokenAccumulator.cnt < 127) {
|
if (tokenAccumulator.cnt < 127) {
|
||||||
memcpy(funcName, tokenAccumulator.data, tokenAccumulator.cnt);
|
memcpy(funcName, tokenAccumulator.data, tokenAccumulator.cnt);
|
||||||
funcName[tokenAccumulator.cnt] = 0;
|
funcName[tokenAccumulator.cnt] = 0;
|
||||||
|
|
@ -521,6 +781,8 @@ codegen:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (tokenAccumulator.data[0] == ':') {
|
if (tokenAccumulator.data[0] == ':') {
|
||||||
|
IRComplete(&irStatements, &irVStack);
|
||||||
|
vstackUnderflows = 0;
|
||||||
printf(" Call __fp_user_"LZ_STR_FMT"\n",
|
printf(" Call __fp_user_"LZ_STR_FMT"\n",
|
||||||
tokenAccumulator.cnt-1,
|
tokenAccumulator.cnt-1,
|
||||||
tokenAccumulator.data+1);
|
tokenAccumulator.data+1);
|
||||||
|
|
@ -553,10 +815,26 @@ codegen:
|
||||||
lz_da_append(vars, v);
|
lz_da_append(vars, v);
|
||||||
allocHead += 8;
|
allocHead += 8;
|
||||||
}
|
}
|
||||||
printf(" popstack 120\n");
|
IRValue x1;
|
||||||
printf(" ; %s:%s\n", funcName, varName);
|
if (irVStack.cnt >= 1) {
|
||||||
printf(" MovI64 121, 0x%16lX\n", addr);
|
x1 = lz_da_pop(irVStack);
|
||||||
printf(" St64 120, 121\n");
|
} 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;
|
break;
|
||||||
}
|
}
|
||||||
if (tokenAccumulator.data[0] == '&') {
|
if (tokenAccumulator.data[0] == '&') {
|
||||||
|
|
@ -581,9 +859,23 @@ codegen:
|
||||||
varName, funcName);
|
varName, funcName);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
printf(" MovI64 121, 0x%16lX\n", addr);
|
|
||||||
printf(" Ld64 120, 121\n");
|
IRValue dstReg = (IRValue) {
|
||||||
printf(" pushstack 120\n");
|
.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;
|
break;
|
||||||
}
|
}
|
||||||
// Iirc there's not a general thing for identifiers so just fail?
|
// Iirc there's not a general thing for identifiers so just fail?
|
||||||
|
|
@ -592,25 +884,58 @@ codegen:
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
case TOKEN_INTLIT: {
|
case TOKEN_INTLIT: {
|
||||||
printf(" MovI64 103, "LZ_STR_FMT"\n",
|
uint64_t x = lz_sb_atoll(&tokenAccumulator);
|
||||||
LZ_STR_PRINTF(tokenAccumulator));
|
IRValue v = (IRValue) {
|
||||||
printf(" pushstack 103\n");
|
.typ = IRVAL_CONSTANT,
|
||||||
|
.val = x
|
||||||
|
};
|
||||||
|
lz_da_append(irVStack, v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOKEN_HEXLIT: {
|
case TOKEN_HEXLIT: {
|
||||||
printf(" MovI64 103, "LZ_STR_FMT"\n",
|
uint64_t x = lz_sb_readhex(&tokenAccumulator);
|
||||||
LZ_STR_PRINTF(tokenAccumulator));
|
IRValue v = (IRValue) {
|
||||||
printf(" pushstack 103\n");
|
.typ = IRVAL_CONSTANT,
|
||||||
|
.val = x
|
||||||
|
};
|
||||||
|
lz_da_append(irVStack, v);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TOKEN_STRINGLIT: {
|
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(" Jmp endstring%d\n", counter);
|
||||||
printf("string%d db \""LZ_STR_FMT"\", 0\n",
|
printf("string%d db \""LZ_STR_FMT"\", 0\n",
|
||||||
counter,
|
counter,
|
||||||
LZ_STR_PRINTF(tokenAccumulator));
|
LZ_STR_PRINTF(tokenAccumulator));
|
||||||
printf("endstring%d:\n", counter);
|
printf("endstring%d:\n", counter);
|
||||||
printf(" MovI64 100, string%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;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|
|
||||||
14
flagpole/tests/fibloop.fp
Normal file
14
flagpole/tests/fibloop.fp
Normal file
|
|
@ -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
|
||||||
100
src/interp.c
100
src/interp.c
|
|
@ -5,9 +5,11 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#define LAZY_IMPL
|
#define LAZY_IMPL
|
||||||
#include "lazy.h"
|
#include "lazy.h"
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
#define DEBUG false
|
//#define DEBUG
|
||||||
|
//#define TIME
|
||||||
// MMIO is defined between 0xC000000000000000 and 0xD000000000000000
|
// MMIO is defined between 0xC000000000000000 and 0xD000000000000000
|
||||||
// Some of that is still normal memory though
|
// Some of that is still normal memory though
|
||||||
#define UART_TX 0xCFFFFFFFFFFFFFFD
|
#define UART_TX 0xCFFFFFFFFFFFFFFD
|
||||||
|
|
@ -122,27 +124,47 @@ int main(int argc, char **argv) {
|
||||||
bool positiveFlag = false;
|
bool positiveFlag = false;
|
||||||
bool negativeFlag = false;
|
bool negativeFlag = false;
|
||||||
bool parityFlag = 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) {
|
while (1) {
|
||||||
unsigned char inst = memory_get8(xPc);
|
unsigned char inst = memory_get8(xPc);
|
||||||
if (DEBUG) printf("INST: %02X\n", inst);
|
#ifdef DEBUG
|
||||||
if (DEBUG) printf("IP: %16lX\n", xPc);
|
printf("INST: %02X\n", inst);
|
||||||
|
printf("IP: %16lX\n", xPc);
|
||||||
|
#endif
|
||||||
size_t inpflag = (inst & 0xE0) >> 5;
|
size_t inpflag = (inst & 0xE0) >> 5;
|
||||||
size_t inpcnt = flag_bytecnt[inpflag];
|
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];
|
unsigned char inputs[9];
|
||||||
for (size_t i = 0; i < inpcnt; ++i) {
|
for (size_t i = 0; i < inpcnt; ++i) {
|
||||||
inputs[i] = memory_get8(xPc+i+1);
|
inputs[i] = memory_get8(xPc+i+1);
|
||||||
if (DEBUG) {
|
#ifdef DEBUG
|
||||||
printf("X%d: 0x%8X\n", i, inputs[i]);
|
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 += 1;
|
||||||
xPc += inpcnt;
|
xPc += inpcnt;
|
||||||
switch (inst) {
|
switch (inst) {
|
||||||
case 0x00: { // Halt
|
case 0x00: { // Halt
|
||||||
printf("\nHALT\n");
|
printf("\nHALT\n");
|
||||||
exit(0);
|
goto halt;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xE9: { // MovI64
|
case 0xE9: { // MovI64
|
||||||
|
|
@ -156,13 +178,13 @@ int main(int argc, char **argv) {
|
||||||
unsigned char x7 = inputs[7];
|
unsigned char x7 = inputs[7];
|
||||||
unsigned char x8 = inputs[8];
|
unsigned char x8 = inputs[8];
|
||||||
uint64_t val =
|
uint64_t val =
|
||||||
((uint64_t)x1 << 56) +
|
((uint64_t)x1 << 56) |
|
||||||
((uint64_t)x2 << 48) +
|
((uint64_t)x2 << 48) |
|
||||||
((uint64_t)x3 << 40) +
|
((uint64_t)x3 << 40) |
|
||||||
((uint64_t)x4 << 32) +
|
((uint64_t)x4 << 32) |
|
||||||
((uint64_t)x5 << 24) +
|
((uint64_t)x5 << 24) |
|
||||||
((uint64_t)x6 << 16) +
|
((uint64_t)x6 << 16) |
|
||||||
((uint64_t)x7 << 8) +
|
((uint64_t)x7 << 8) |
|
||||||
((uint64_t)x8 << 0);
|
((uint64_t)x8 << 0);
|
||||||
registers[reg] = val;
|
registers[reg] = val;
|
||||||
registers[0] = 0;
|
registers[0] = 0;
|
||||||
|
|
@ -183,11 +205,11 @@ int main(int argc, char **argv) {
|
||||||
case 0x93: { // Ld8
|
case 0x93: { // Ld8
|
||||||
unsigned char dst = inputs[0];
|
unsigned char dst = inputs[0];
|
||||||
unsigned char addr = inputs[1];
|
unsigned char addr = inputs[1];
|
||||||
if (DEBUG) {
|
#ifdef DEBUG
|
||||||
printf("Ld8\n");
|
printf("Ld8\n");
|
||||||
printf("Dst val: %8X\n", registers[dst]);
|
printf("Dst val: %8X\n", registers[dst]);
|
||||||
printf("Addr val: %8X\n", registers[addr]);
|
printf("Addr val: %8X\n", registers[addr]);
|
||||||
}
|
#endif
|
||||||
registers[dst] = memory_get8(registers[addr]);
|
registers[dst] = memory_get8(registers[addr]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -324,7 +346,9 @@ int main(int argc, char **argv) {
|
||||||
case 0xC1: { // JmpIZ
|
case 0xC1: { // JmpIZ
|
||||||
unsigned char addr = inputs[0];
|
unsigned char addr = inputs[0];
|
||||||
if (zeroFlag) {
|
if (zeroFlag) {
|
||||||
if (DEBUG) printf("Jump!\n");
|
#ifdef DEBUG
|
||||||
|
printf("Jump!\n");
|
||||||
|
#endif
|
||||||
xPc = registers[addr];
|
xPc = registers[addr];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -332,7 +356,9 @@ int main(int argc, char **argv) {
|
||||||
case 0xC3: { // JmpIP
|
case 0xC3: { // JmpIP
|
||||||
unsigned char addr = inputs[0];
|
unsigned char addr = inputs[0];
|
||||||
if (positiveFlag) {
|
if (positiveFlag) {
|
||||||
if (DEBUG) printf("Jump!\n");
|
#ifdef DEBUG
|
||||||
|
printf("Jump!\n");
|
||||||
|
#endif
|
||||||
xPc = registers[addr];
|
xPc = registers[addr];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -340,7 +366,9 @@ int main(int argc, char **argv) {
|
||||||
case 0xC2: { // JmpIN
|
case 0xC2: { // JmpIN
|
||||||
unsigned char addr = inputs[0];
|
unsigned char addr = inputs[0];
|
||||||
if (negativeFlag) {
|
if (negativeFlag) {
|
||||||
if (DEBUG) printf("Jump!\n");
|
#ifdef DEBUG
|
||||||
|
printf("Jump!\n");
|
||||||
|
#endif
|
||||||
xPc = registers[addr];
|
xPc = registers[addr];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -348,7 +376,9 @@ int main(int argc, char **argv) {
|
||||||
case 0xC8: { // JmpIE
|
case 0xC8: { // JmpIE
|
||||||
unsigned char addr = inputs[0];
|
unsigned char addr = inputs[0];
|
||||||
if (!parityFlag) {
|
if (!parityFlag) {
|
||||||
if (DEBUG) printf("Jump!\n");
|
#ifdef DEBUG
|
||||||
|
printf("Jump!\n");
|
||||||
|
#endif
|
||||||
xPc = registers[addr];
|
xPc = registers[addr];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -377,7 +407,39 @@ int main(int argc, char **argv) {
|
||||||
exit(1);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue