aboutsummaryrefslogtreecommitdiff
path: root/pu2
diff options
context:
space:
mode:
authorGravatar Moon Flower <moon@coffin.ir> 2025-08-14 12:02:50 +0330
committerGravatar Moon Flower <moon@coffin.ir> 2025-08-14 12:02:50 +0330
commit9e7d03382cfcf6cc10fdb6b4a16b7056a9ce6a25 (patch)
treec16e4085a2132590068cdc06bb3d5d0e74529e9d /pu2
parentarithmetics unit in emu (diff)
benchmark + operations + extra stufferinos
Diffstat (limited to 'pu2')
-rw-r--r--pu2/code.i219
-rw-r--r--pu2/pu2.c165
-rw-r--r--pu2/pu2.out.c34
3 files changed, 188 insertions, 30 deletions
diff --git a/pu2/code.i2 b/pu2/code.i2
index 14a065f..2086d42 100644
--- a/pu2/code.i2
+++ b/pu2/code.i2
@@ -5,7 +5,22 @@ macro puts() {
system();
}
-puts(["hello world
-"], [12]);
+macro putchar() {
+ @1 = 0; // write
+ @2 = 10; // ptr
+ @3 = 1; // size
+ @10 = /1/; // value
+ system();
+}
+
+// putchar([10]);
+// puts([" hello world"], [15]);
+// putchar([10]);
+// putchar([10]);
+
+@10 = 3;
+@4 = 0;
+
+@10 != @4;
exit(0); \ No newline at end of file
diff --git a/pu2/pu2.c b/pu2/pu2.c
index a20d4ff..ac09efa 100644
--- a/pu2/pu2.c
+++ b/pu2/pu2.c
@@ -1,5 +1,6 @@
#include "pu2.out.c"
#include <stdio.h>
+#include <time.h>
typedef char *string;
@@ -66,6 +67,17 @@ error_debug(string fail_point, string code, int sz) {
fprintf(stderr, "\x1b[1m\x1b[31m^\x1b[0m \x1b[90mparsing stopped here\x1b[0m\n");
}
+long powi(long x, unsigned n) {
+ long p = x, r = 1;
+
+ while (n > 0) {
+ if (n & 1) r *= p;
+ p *= p, n /= 2;
+ }
+
+ return r;
+}
+
emu() {
while (1) {
pu2();
@@ -112,6 +124,10 @@ emu() {
} else if (op == 4) {
// right shift
m[ 3 ] = val1 >> val2;
+ } else if (op == 5) {
+ // pow
+ if (val1 == 2) m[ 3 ] = val1 << val2;
+ else { m[ 3 ] = powi(val1, val2); }
}
else {
@@ -135,9 +151,9 @@ skip_space(string *I) {
// IR parser for pu2's as2
// clang-format off
struct {
- int hlt; int imm; int lod; int str; int swp; int add; int sub; int and; int not; int acc;
+ int hlt, imm, lod, str, swp, add, sub, and, not, acc, a2u, u2a, b2u, u2b;
} opcode = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8,9
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
};
// clang-format on
@@ -235,6 +251,45 @@ clean_slice_ref(slice *val) { free(val->ref); }
value; \
})
+#define op(mode) emit(opcode.mode, 0)
+#define swap() emit(opcode.swp, 0)
+#define imm(value) emit(opcode.imm, value)
+#define load() emit(opcode.lod, 0)
+#define imm_in_mem(__mem, __imm) \
+ ({ \
+ imm(__imm); \
+ swap(); \
+ imm(__mem); \
+ store(); \
+ })
+#define mov_mem_mem(__mem1, __mem2) \
+ ({ \
+ imm(__mem2); \
+ swap(); \
+ load(); \
+ swap(); \
+ imm(__mem1); \
+ store(); \
+ })
+#define mem_in_a(__mem) \
+ ({ \
+ op(b2u); \
+ imm(__mem); \
+ swap(); \
+ load(); \
+ op(u2b); \
+ })
+#define perform_op(operation) \
+ ({ \
+ mem_in_a(mem2_index); \
+ swap(); \
+ mem_in_a(mem_index); \
+ emit(opcode.operation, 0); \
+ swap(); \
+ imm(mem_index); \
+ store(); \
+ })
+
char T;
string ERR;
string ERR_code;
@@ -257,7 +312,9 @@ _ir2(string I, entry macros[ 1 << 9 ]) {
I++;
int mem_index = strtol(I, &I, 10);
skip_space(&I);
- checkskip('=', "expected assigment after memory blob");
+ char extra_op = '=';
+ if (*I == '+' || *I == '-' || *I == '&' || *I == '!') extra_op = *I++;
+ checkskip('=', "expected assigment after memory blob (hint: only +-&! are supported)");
skip_space(&I);
if (*I == '@') {
@@ -269,19 +326,53 @@ _ir2(string I, entry macros[ 1 << 9 ]) {
int mem2_index = strtol(I, &I, 10);
- emit(opcode.imm, mem2_index);
- emit(opcode.swp, 0);
- emit(opcode.lod, 0);
- emit(opcode.swp, 0);
- emit(opcode.imm, mem_index);
- store();
+ if (extra_op == '=') {
+ mov_mem_mem(mem_index, mem2_index);
+ } else if (extra_op == '+') {
+ perform_op(add);
+ } else if (extra_op == '-') {
+ perform_op(sub);
+ } else if (extra_op == '&') {
+ perform_op(and);
+ } else if (extra_op == '!') {
+ // @1 != @2;
+ mem_in_a(mem2_index);
+ emit(opcode.not, 0);
+ swap();
+ imm(mem_index);
+ store();
+ }
} else {
int imm = scanvalue();
- emit(opcode.imm, imm);
- emit(opcode.swp, 0);
- emit(opcode.imm, mem_index);
- store();
+ if (extra_op == '=') {
+ imm_in_mem(mem_index, imm);
+ } else if (extra_op == '+') {
+ imm(imm);
+ swap();
+ mem_in_a(mem_index);
+ emit(opcode.add, 0);
+ store();
+ } else if (extra_op == '-') {
+ imm(imm);
+ swap();
+ mem_in_a(mem_index);
+ emit(opcode.sub, 0);
+ store();
+ } else if (extra_op == '&') {
+ imm(imm);
+ swap();
+ mem_in_a(mem_index);
+ emit(opcode.and, 0);
+ store();
+ } else if (extra_op == '!') {
+ // @1 != 5;
+ imm(imm);
+ emit(opcode.not, 0);
+ swap();
+ imm(mem_index);
+ store();
+ }
}
skip_space(&I);
@@ -528,6 +619,53 @@ ir2(string I) {
string op_names[] = { "hlt", "imm", "lod", "str", "swp", "add", "sub", "and", "not", "acc" };
+unsigned long long rdtsc(void) {
+ unsigned hi, lo;
+ __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
+ return ((unsigned long long) hi << 32) | lo;
+}
+
+double bench_cycle(int instr) {
+ int i;
+ for (i = 0; i < S - 2; i += 2) {
+ m[ i ] = instr;
+ m[ i + 1 ] = 5;
+ }
+ m[ S - 2 ] = 0;
+ m[ S - 1 ] = 0;
+
+ m[ 7 ] = 0;
+ c = 0;
+
+ clock_t start = clock();
+ pu2();
+ clock_t end = clock();
+
+ double seconds = (double) (end - start) / CLOCKS_PER_SEC;
+ printf("time: %.6f s\n", seconds);
+ return (double) m[ 7 ] / seconds / 1e6;
+}
+
+benchmark() {
+ double results[ 13 ];
+ double sum = 0;
+ for (i = 0; i < 13; i++) {
+ results[ i ] = bench_cycle(i);
+ sum += results[ i ];
+ }
+ sum /= 13;
+
+ unsigned long long start, end;
+ start = rdtsc();
+ sleep(1);
+ end = rdtsc();
+
+ float clock_speed = (end - start) / 1e6;
+ printf("clock speed ~ %.6f MHz\n", clock_speed);
+ printf("results sum: %f\n", sum);
+ printf("instructions per cycle: %f\n", clock_speed / sum);
+}
+
main() {
size_t o_size;
ir2(read_file("code.i2", &o_size));
@@ -552,6 +690,7 @@ main() {
// printf("\n\n");
emu();
+ printf("result: %i\n", m[ 10 ]);
}
main2(int argc, char **argv) {
diff --git a/pu2/pu2.out.c b/pu2/pu2.out.c
index 63c41f1..05d96c3 100644
--- a/pu2/pu2.out.c
+++ b/pu2/pu2.out.c
@@ -18,24 +18,28 @@
// ^ calls my_custom_cpu_error_trap()
// clang-format off
-#define S 1<<20
-#define H !--c
+#define S 1<<25
#define J while
-m[S],c,v,a,b,u;pu2(){J(c=m[m[7]++],v=m[m[7]++],c){H?a=v:H?a=m[b]:H?u?m[a]=b:0:H?v=a,a=b,b=v:H?a+=b:H?a-=b:H?a&=b:H?a=!a:H?u=1:A;u=v;}}
+#define H !--c
+m[S],c,v,a,b,u;pu2(){J(c=m[m[7]++],v=m[m[7]++],c){H?a=v:H?a=m[b]:H?u?m[a]=b:0:H?v=a,a=b,b=v:H?a+=b:H?a-=b:H?a&=b:H?a=!a:H?u=v:H?u=a:H?a=u:H?u=b:H?b=u:A;}}
// clang-format on
// there's just memory. no, really
// ok actually there's two registers called a and b
-// 0 HLT: halt
-// 1 IMM: a = imm
-// 2 LOD: a = m[b]
-// 3 STR: m[a] = b (only happens if acc != 0)
-// 4 SWP: swap a and b
-// 5 ADD: a += b
-// 6 SUB: a -= b
-// 7 AND: a &= b
-// 8 NOT: a = !a
-// 9 ACC: u = imm
+// 0 HLT: halt
+// 1 IMM: a = imm
+// 2 LOD: a = m[b]
+// 3 STR: m[a] = b (only happens if acc != 0)
+// 4 SWP: swap a and b
+// 5 ADD: a += b
+// 6 SUB: a -= b
+// 7 AND: a &= b
+// 8 NOT: a = !a
+// 9 ACC: u = imm
+// 10 A2U: u = a
+// 11 U2A: a = u
+// 12 B2U: u = b
+// 13 U2B: b = u
// NOTE: Memory indexes less than 1024 should be considered as temporary/compute memory, and
// programs should be written at index 1024 and upwards.
@@ -52,10 +56,10 @@ m[S],c,v,a,b,u;pu2(){J(c=m[m[7]++],v=m[m[7]++],c){H?a=v:H?a=m[b]:H?u?m[a]=b:0:H?
// therefore, i recommend you store a copy somewhere!
// clang-format off
-char*C="hltimmlodstrswpaddsubandnotacc",*Y[1<<10],*E,*L,i;*K;as2(char*I){J(c=*I++){if(c==35){J(*++I-10);c=*I++;}L=C;(!isspace(c)?c-39?c-125?c-123?c-64?({i=0,I--;J(i++,*L)strncmp(L,I,3)?L+=3:({I+=3;*K++=i-1;*K++=(i-2&&i-9)?0:strtol(I,&I,10);goto Q;});E=I;return 1;Q:;}):as2(Y[strtol(I,&I,10)]):({Y[strtol(I,&I,10)]=I+1;J(*I++-125);}):({break;}):({*K++=1;*K++=*I++;}):0);}}
+char*C="hltimmlodstrswpaddsubandnotacca2uu2ab2uu2b",*Y[1<<10],*E,*L,i;*K;as2(char*I){J(c=*I++){if(c==35){J(*++I-10);c=*I++;}L=C;(!isspace(c)?c-39?c-125?c-123?c-64?({i=0,I--;J(i++,*L)strncmp(L,I,3)?L+=3:({I+=3;*K++=i-1;*K++=(i-2&&i-9)?0:strtol(I,&I,10);goto Q;});E=I;return 1;Q:;}):as2(Y[strtol(I,&I,10)]):({Y[strtol(I,&I,10)]=I+1;J(*I++-125);}):({break;}):({*K++=1;*K++=*I++;}):0);}}
// clang-format on
-#undef S
+// #undef S
#undef H
#undef J
#undef E \ No newline at end of file