aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar moon <moon@coffin.ir> 2025-08-21 22:42:14 +0330
committerGravatar moon <moon@coffin.ir> 2025-08-21 22:42:14 +0330
commitbfc728476d8ac5edc6249ef2f9fa72ea11c7ffd7 (patch)
treed07ed416cd612f72de0977bf9a1643c17e66a773
parentadded makefile (diff)
added jmp, jnz and jz
-rw-r--r--pu2/Makefile4
-rw-r--r--pu2/code.i211
-rw-r--r--pu2/pu2.c258
-rw-r--r--pu2/pu2.out.c12
4 files changed, 242 insertions, 43 deletions
diff --git a/pu2/Makefile b/pu2/Makefile
index 05d9d3f..a211385 100644
--- a/pu2/Makefile
+++ b/pu2/Makefile
@@ -1,6 +1,10 @@
build:
clang pu2.c -o pu2 -std=c89 -ffunction-sections -Wl,--gc-sections -O3 -march=native -mtune=native -flto -ffast-math -funroll-loops -fno-exceptions -flto
+# i use this for building pu2 on a-Shell
+build_wasi:
+ clang pu2.c -o pu2 -std=c89 -ffunction-sections -Wl,--gc-sections -O3 -ffast-math -funroll-loops -fno-exceptions -DPU2_BAD_CLOCK -DPU2_NO_ASM -DPU2_NO_MMAP -fno-rtti -fno-stack-protector -fomit-frame-pointer -Wno-format -Wno-#warnings
+
run:
./pu2
diff --git a/pu2/code.i2 b/pu2/code.i2
index e6a259c..c42cdd5 100644
--- a/pu2/code.i2
+++ b/pu2/code.i2
@@ -13,9 +13,18 @@ macro putchar(1) {
system();
}
+@10 = 1;
+
+jz(@10, continue); // conditional jump!
+
+puts(["hi"], [2]);
+
+continue:
+
putchar([10]);
puts([" hello world"], [15]);
putchar([10]);
putchar([10]);
-exit(0); \ No newline at end of file
+exit(0);
+
diff --git a/pu2/pu2.c b/pu2/pu2.c
index 85c28f4..2916582 100644
--- a/pu2/pu2.c
+++ b/pu2/pu2.c
@@ -184,19 +184,30 @@ const bool false = 0;
typedef struct {
size_t len;
string ref;
-} slice;
+} slice_t;
typedef struct {
- slice key;
- slice value;
-} entry;
+ slice_t key;
+ slice_t value;
+} entry_t;
typedef struct {
- entry data;
+ slice_t name;
+ size_t location;
+} label_t;
+
+typedef struct {
+ entry_t data;
byte arg_count;
-} macro;
+} macro_t;
+
+typedef struct {
+ slice_t name;
+ int* replace_location; // where to put the resolved address
+ string init_I;
+} label_delegated_t;
-clean_slice_ref(slice *val) { free(val->ref); }
+clean_slice_ref(slice_t *val) { free(val->ref); }
#define static_len(G) (sizeof(G) / sizeof((G)[ 0 ]))
@@ -218,11 +229,11 @@ clean_slice_ref(slice *val) { free(val->ref); }
})
#define scanword() \
({ \
- slice VAR = { 0, I }; \
+ slice_t VAR = { 0, I }; \
while (isalnum(*I) || *I == '_') VAR.len++, I++; \
VAR; \
})
-#define memslice slice __attribute__((cleanup(clean_slice_ref)))
+#define memslice_t slice_t __attribute__((cleanup(clean_slice_ref)))
#define readd() ((used == new.len) ? (new.ref = realloc(new.ref, new.len *= 2)) : 0)
#define scanvalue() \
({ /* value scanner! numbers, characters, strings. */ \
@@ -295,7 +306,7 @@ __attribute__((always_inline)) emit(int op, int val) {
}
bool has_jump_warned = false;
-_ir2(string I, macro macros[ 1 << 9 ]) {
+_ir2(string I, macro_t macros[ 1 << 9 ], label_t labels[ 1 << 10 ], label_delegated_t forward_refs[ 1 << 10 ]) {
string init_I = I;
ERR = "all good";
@@ -394,7 +405,7 @@ _ir2(string I, macro macros[ 1 << 9 ]) {
if (!isalpha(*I) && *I != '_') {
run_err(I - 1, "expected letter or underscore at macro name");
}
- slice name = scanword();
+ slice_t name = scanword();
skip_space(&I);
@@ -422,7 +433,7 @@ _ir2(string I, macro macros[ 1 << 9 ]) {
// find open space in macros
int x;
for (x = 0; x < (1 << 9); x++) {
- macro g = macros[ x ];
+ macro_t g = macros[ x ];
if (g.data.key.ref == NULL) { goto DONE; }
}
@@ -431,7 +442,7 @@ _ir2(string I, macro macros[ 1 << 9 ]) {
DONE:;
skip_space(&I); // might aswell skip whitespace for funsies.
- macro *g = &macros[ x ];
+ macro_t *g = &macros[ x ];
g->data.key = name;
g->data.value.ref = I;
g->data.value.len = 0;
@@ -477,7 +488,7 @@ _ir2(string I, macro macros[ 1 << 9 ]) {
}
// emit system
- if (strncmp("system", I, 6) == 0 && !isalnum(I[ 7 ])) {
+ if (strncmp("system", I, 6) == 0 && !isalnum(I[ 6 ])) {
I += 6;
skip_space(&I);
checkskip('(', "expected open paren on system blob");
@@ -488,24 +499,172 @@ _ir2(string I, macro macros[ 1 << 9 ]) {
skip_space(&I);
checkskip(';', "expected semicolon after system blob");
- emit(opcode.imm, 2);
- emit(opcode.swp, 0);
- emit(opcode.imm, 0);
- store();
+ imm_in_mem(0, 2);
emit(opcode.hlt, 0);
continue;
}
+ if (strncmp("jump", I, 4) == 0 && !isalnum(I[4])) {
+ I += 4;
+ goto PARSE_JUMP_BLOB;
+ }
+
+ if (strncmp("jmp", I, 3) == 0 && !isalnum(I[3])) {
+ I += 3;
+ PARSE_JUMP_BLOB:
+ skip_space(&I);
+ checkskip('(', "expected open paren on jump blob");
+ skip_space(&I);
+ if(!isalpha(*I)) run_err(I, "expected a label name for jump blob argument");
+ slice_t label = { 1, I };
+ while (isalnum(*++I)) label.len++;
+ skip_space(&I);
+ checkskip(')', "expected closing paren after label name in jump blob");
+ skip_space(&I);
+ checkskip(';', "excpected semicolon after jump blob");
+
+ // resolve right now if the label exists
+ label_t *lbdb = labels;
+
+ while (lbdb->name.ref != NULL) {
+ label_t cur = *lbdb++;
+ if (cur.name.len == label.len && strncmp(cur.name.ref, label.ref, label.len) == 0) {
+ imm_in_mem(7, cur.location);
+ goto FINISH_JMP;
+ }
+ }
+
+ // not resolved yet..
+ // find delegations slot
+
+ label_delegated_t *del;
+ int j;
+ for (j = 0; j < 1 << 10; j++) {
+ if (forward_refs[j].name.ref == NULL) {
+ // found one!
+ del = &forward_refs[j];
+ goto WRITE_DEL;
+ }
+ }
+
+ run_err(label.ref, "couldn't reserve a spot for this label as the forward references table is full (how?)");
+
+ WRITE_DEL:
+
+ imm_in_mem(7, 0xDEAD10C4); // DEADLOCK - placeholder for the resolver
+ del->replace_location = Code - 1; // place of imm in code
+ del->name = label;
+ del->init_I = init_I;
+
+ FINISH_JMP:;
+ }
+
+ if ((strncmp("jnz", I, 3) == 0 && !isalnum(I[3])) || (strncmp("jz", I, 2) == 0 && !isalnum(I[2]))) {
+ bool was_jnz = !!strncmp("jz", I, 2);
+ string name = was_jnz ? "jnz" : "jz";
+
+ I += was_jnz ? 3 : 2;
+ skip_space(&I);
+ checkskip('(', "expected open paren on %s blob", name);
+ skip_space(&I);
+ checkskip('@', "expected memory address format as first %s argument (example: `%s(@5, label_name);`)", name, name);
+ int target_mem = strtol(I, &I, 10);
+
+ skip_space(&I);
+ checkskip(',', "expected comma (second argument) in %s blob (example: `%s(@5, label_name);`)", name, name);
+
+ skip_space(&I);
+ if(!isalpha(*I)) run_err(I, "expected a label name for %s blob's second argument (example: `%s(@5, label_name);`)", name, name);
+ slice_t label = { 1, I };
+ while (isalnum(*++I)) label.len++;
+ skip_space(&I);
+
+ checkskip(')', "expected closing paren after label name in %s blob (do i really need to explain this to you again?)", name);
+ skip_space(&I);
+ checkskip(';', "excpected semicolon after %s blob", name);
+
+ // resolve right now if the label exists
+ label_t *lbdb = labels;
+
+ while (lbdb->name.ref != NULL) {
+ label_t cur = *lbdb++;
+ if (cur.name.len == label.len && strncmp(cur.name.ref, label.ref, label.len) == 0) {
+ // emit j(n)z
+ mem_in_a(target_mem);
+ if (!was_jnz) op(not);
+ op(a2u);
+ imm(cur.location);
+ swap();
+ imm(7);
+ op(str);
+
+ goto FINISH_JNZ;
+ }
+ }
+
+ // not resolved yet..
+ // find delegations slot
+
+ label_delegated_t *del;
+ int j;
+ for (j = 0; j < 1 << 10; j++) {
+ if (forward_refs[j].name.ref == NULL) {
+ // found one!
+ del = &forward_refs[j];
+ goto WRITE_DEL_JNZ;
+ }
+ }
+
+ run_err(label.ref, "couldn't reserve a spot for this label as the forward references table is full (how?)");
+
+ WRITE_DEL_JNZ:
+
+ // emit jnz
+ mem_in_a(target_mem);
+ if (!was_jnz) op(not);
+ op(a2u);
+ imm(0xDEAD10C4); // DEADLOCK - placeholder for the resolver
+ del->replace_location = Code - 1; // place of imm in code
+ swap();
+ imm(7);
+ op(str);
+
+ del->name = label;
+ del->init_I = init_I;
+
+ FINISH_JNZ:;
+ }
+
// macro call, maybe?
if (isalpha(*I)) {
- slice name = scanword();
+ slice_t name = scanword();
skip_space(&I);
+ if(*I == ':') {
+ I++;
+ // this is a label!
+ label_t *slot;
+ int j;
+ for (j = 0; j < 1 << 10; j++) {
+ if (labels[j].name.ref != NULL) continue;
+ slot = &labels[j];
+ goto FOUND_SLOT;
+ }
+
+ run_err(I - 1, "registered label count exceeded 1<<10 (how?)");
+
+ FOUND_SLOT:
+ slot->name = name;
+ slot->location = Code - m;
+
+ continue;
+ }
+
checkskip('(', "expected open paren after alphanumeric word (assuming this is a blob)");
skip_space(&I);
- slice arguments[ 1 << 7 ];
+ slice_t arguments[ 1 << 7 ];
size_t arg_count = 0;
string fail_I = I;
@@ -556,7 +715,7 @@ _ir2(string I, macro macros[ 1 << 9 ]) {
// find index
size_t i;
for (i = 0; i < (1 << 9); i++) {
- macro cur = macros[ i ];
+ macro_t cur = macros[ i ];
if (cur.data.key.len != name.len) continue;
if (strncmp(name.ref, cur.data.key.ref, name.len) == 0) goto FOUND;
}
@@ -571,10 +730,10 @@ _ir2(string I, macro macros[ 1 << 9 ]) {
macros[ i ].arg_count,
arg_count);
}
- slice target = macros[ i ].data.value;
+ slice_t target = macros[ i ].data.value;
string N = target.ref;
string oldN = N;
- memslice new = { target.len, malloc(target.len) };
+ memslice_t new = { target.len, malloc(target.len) };
size_t used = 0;
bool needs_scan = true;
@@ -604,7 +763,7 @@ _ir2(string I, macro macros[ 1 << 9 ]) {
}
needs_scan = true;
- slice rep = arguments[ index - 1 ];
+ slice_t rep = arguments[ index - 1 ];
string val = rep.ref;
for (i = 0; i < rep.len; i++) {
new.ref[ used++ ] = *val++;
@@ -622,7 +781,7 @@ _ir2(string I, macro macros[ 1 << 9 ]) {
new.ref[ used ] = 0;
- _ir2(new.ref, macros);
+ _ir2(new.ref, macros, labels, forward_refs);
continue;
}
@@ -630,8 +789,32 @@ _ir2(string I, macro macros[ 1 << 9 ]) {
}
ir2(string I) {
- macro macros[ 1 << 9 ] = { 0 };
- _ir2(I, macros);
+ macro_t macros[ 1 << 9 ] = { 0 };
+ label_t labels[ 1 << 10 ] = { 0 };
+ label_delegated_t forward_refs[ 1 << 10 ] = { 0 };
+ _ir2(I, macros, labels, forward_refs);
+
+ label_delegated_t *_forward_refs = forward_refs;
+ // handle forward references!
+ while (_forward_refs->name.ref != NULL) {
+ label_delegated_t cur = *_forward_refs++;
+
+ // find label
+ int j;
+ for (j = 0; j < static_len(labels); j++) {
+ label_t clab = labels[j];
+ if (clab.name.len == cur.name.len && strncmp(clab.name.ref, cur.name.ref, cur.name.len) == 0) {
+ // found it!
+ *cur.replace_location = clab.location;
+ goto REP_DONE;
+ }
+ }
+
+ string init_I = cur.init_I;
+ run_err(cur.name.ref, "could not find label %i %s", cur.name.len, cur.name.ref);
+
+ REP_DONE:;
+ }
}
string op_names[] = { "hlt", "imm", "lod", "str", "swp", "add", "sub", "and", "not", "acc",
@@ -790,22 +973,17 @@ benchmark(double (*target)(int), const char *mode_label) {
printf("=== end benchmark ===\n\n");
}
-nstime() {
- struct timespec ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return ts.tv_nsec;
-}
-
volatile long out;
main(int argc, char **argv) {
if (argc == 1) {
- return printf(
+ printf(
"\nusage:\n"
" %s <file_name> open and compile ir2-compliant code\n"
" %s benchmark benchmark pu2 (two modes: time and rdtsc)\n\n",
argv[ 0 ],
argv[ 0 ]);
+ return 1;
}
init_pu2();
@@ -843,13 +1021,21 @@ main(int argc, char **argv) {
}
size_t o_size;
- long before = nstime();
+ long before = ntime();
long cycles_bef = rdtsc();
ir2(contents);
long cycles_aft = rdtsc();
- long after = nstime();
+ long after = ntime();
m[ 7 ] = 4000;
+ /*int j = 0;
+ for(j = 0; j < 64; j++) {
+ printf("%i: %i %i\n", j, m[4000+j], m[4001+j]);
+ j++;
+ }*/
+
+ //printf("assembly took %i milliseconds\n", (after - before)/1000);
+
free(contents);
size_t res_size = Code - &m[ 4000 ];
diff --git a/pu2/pu2.out.c b/pu2/pu2.out.c
index 347e6f4..f35a7ab 100644
--- a/pu2/pu2.out.c
+++ b/pu2/pu2.out.c
@@ -232,8 +232,8 @@ void __attribute__((hot, aligned(64))) pu2() {
M += inst.v;
goto PU2_START;
CB_FIFTEEN:
- // if (unlikely(inst.v == 7)) pc = m[ a ] >> 1;
- if (unlikely(inst.v == a)) goto PU2_START;
+ //if (unlikely(inst.v == 7)) M = M2 + (m[a] >> 1);
+ //if (unlikely(inst.v == a)) goto PU2_START;
m[ inst.v ] = m[ a ];
// asm("mov %1, %0" : "=r"(m[inst.v]) : "r"(m[a]));
goto PU2_START;
@@ -241,14 +241,14 @@ void __attribute__((hot, aligned(64))) pu2() {
// asm("mov %1, %0" : "=r"(a) : "r"(m[inst.v]));
a = m[ inst.v ];
goto PU2_START;
- CB_SEVENTEEN:
- // if (unlikely(a == 7)) pc = inst.v >> 1;
+ CB_SEVENTEEN: // beware, only instruction 17 (cb3) actually updates pc on an assignment to m[7]!
+ if (unlikely(a == 7)) M = M2 + (inst.v >> 1);
// asm("mov %1, %0" : "=r"(m[a]) : "r"(inst.v));
m[ a ] = inst.v;
goto PU2_START;
CB_EIGHTEEN:
- // if (unlikely(a == 7)) pc = m[ inst.v ] >> 1;
- if (unlikely(inst.v == a)) goto PU2_START;
+ //if (unlikely(a == 7)) M = M2 + (m[inst.v] >> 1);
+ //if (unlikely(inst.v == a)) goto PU2_START;
m[ a ] = m[ inst.v ];
// asm("mov %1, %0" : "=r"(m[a]) : "r"(m[inst.v]));
goto PU2_START;