aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Moon Flower <moon@coffin.ir> 2025-08-07 12:19:32 +0330
committerGravatar Moon Flower <moon@coffin.ir> 2025-08-07 12:19:32 +0330
commit47b04ca2778cbce41deae6331472c25822e7a29a (patch)
treec6b4f555e2f890dfd2e8dfc75f61ff11e0ade3a4
parentchar fix (diff)
bwahh changes!!
-rw-r--r--.gitignore2
-rw-r--r--README.md9
-rw-r--r--code.pasm6
-rw-r--r--pu.c137
-rw-r--r--pu.out.c9
-rw-r--r--tbin0 -> 115 bytes
6 files changed, 143 insertions, 20 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d56a83a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+pu
+putest \ No newline at end of file
diff --git a/README.md b/README.md
index 5a8b117..dcc0fbf 100644
--- a/README.md
+++ b/README.md
@@ -13,4 +13,11 @@ ikr,,,
## instruction set?
check the comments in pu.c
-i still haven't added docs for the assembler, but ehh it's pretty self explanatory. ask ai to explain it to you if you can't be assed to read. \ No newline at end of file
+i still haven't added docs for the assembler, but ehh it's pretty self explanatory. ask ai to explain it to you if you can't be assed to read.
+
+## t?
+that file is the instruction encoding table for the assembler. you can add shit to it if you wanna. this is the original:
+```c
+char *R="hlt\0 ar1\2 ar2\3 ar3\4 ar4\5 ar5\6 ar6\7 ar7\x8 ar8\x9 r1a\xA r2a\xB r3a\xC r4a\xD r5a\xE r6a\xF r7a\20 r8a\21 mem\22 aca\23 add\24 sub\25 not\26 clr\27";
+```
+removing it means you can't assemble stuff anymore. though the pu.c wrapper does write it for you if it doesn't exist. \ No newline at end of file
diff --git a/code.pasm b/code.pasm
new file mode 100644
index 0000000..969f96b
--- /dev/null
+++ b/code.pasm
@@ -0,0 +1,6 @@
+# charcode for c
+con 99
+
+ar4 con 60 ar2 r4a mem con 1 ar4 con 60 ar3 con 0 ar2 con 2 hlt
+
+hlt
diff --git a/pu.c b/pu.c
index a6941fe..4e93a31 100644
--- a/pu.c
+++ b/pu.c
@@ -1,12 +1,16 @@
+#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <string.h>
-#include <stdio.h>
#pragma clang diagnostic ignored "-Wreturn-type"
#pragma clang diagnostic ignored "-Wc23-extensions"
+// clang-format off
#define S 65536
#define H !--c?
-m[S],c,a;pu(){while((c=m[m[7]++]))H*m=m[m[7]++]:c--<9?a?m[c]=*m:0:8>(c-=8)?*m=m[c]:!(c-=8)?m[m[1]]=*m:H*m=a:H a+=*m:H a-=*m:H a=!a:H a=0:0;}
+#define J while
+m[S],c,a;pu(){J((c=m[m[7]++]))H*m=m[m[7]++]:c--<9?!a?m[c]=*m:0:8>(c-=8)?*m=m[c]:!(c-=8)?m[m[1]]=*m:H*m=a:H a+=*m:H a-=*m:H a=!a:H a=0:0;}
+// clang-format on
// a is acc
// first 8 memory bytes are registers actually
@@ -15,7 +19,7 @@ m[S],c,a;pu(){while((c=m[m[7]++]))H*m=m[m[7]++]:c--<9?a?m[c]=*m:0:8>(c-=8)?*m=m[
// --- opcodes ---
// 0 = halt DONE
// 1 = const in r0 DONE
-// 2...9 = r0 in rX (only if acc is non-zero) DONE
+// 2...9 = r0 in rX (only if acc is zero) DONE
// 10...17 = rX in r0 DONE
// 18 = r0 in m[r1] DONE
// 19 = acc in r0 DONE
@@ -29,28 +33,127 @@ m[S],c,a;pu(){while((c=m[m[7]++]))H*m=m[m[7]++]:c--<9?a?m[c]=*m:0:8>(c-=8)?*m=m[
// compiler!
// the switch skips whitespace. then, the beautiful loop thingymajigy emits bytecode.
+// clang-format off
#define W case
#define Q goto M;
-char *R="hlt\0 ar1\2 ar2\3 ar3\4 ar4\5 ar5\6 ar6\7 ar7\x8 ar8\x9 r1a\xA r2a\xB r3a\xC r4a\xD r5a\xE r6a\xF r7a\20 r8a\21 mem\22 aca\23 add\24 sub\25 not\26 clr\27";K;as(char*I,int*O){char*V=R;while((K=*I)){V=R;switch(K){case 32:case 10:case 9:I++;Q}while(*V)V+=3,(strncmp(V-3,I,3)?:({*O++=*V;I+=3;Q})),V+=2;strncmp("con ",I,4)?:({*O++=1,*O++=atoi(I+=4);while(*I>47&*I<58)I++;Q});return 1;M:}return 0;}
+char R[]={
+#embed"t"
+};K;char*as(char*I,int*O){char*V=R;J((K=*I)){V=R;switch(K){W 32:W 10:W 9:I++;Q;W 35:J(*++I!=10);Q}strncmp("con ",I,4)?:({*O++=1,*O++=atoi(I+=4);J(*I>47&*I<58)I++;Q});J(*V)V+=3,(strncmp(V-3,I,3)?:({*O++=*V;I+=3;Q})),V+=2;return I;M:}return 0;}
+// clang-format on
#undef Q
#undef H
#undef W
#undef S
-
-// ----------
+#undef J
#ifndef __WRAPPER
-int main() {
- // __asm__("int $3");
- m[ 7 ] = 1024;
- m[ 1024 ] = 1;
- m[ 1025 ] = 9;
- m[ 1026 ] = 1;
- m[ 1027 ] = 5;
-
- printf("before: %i\n", m[ 0 ]);
- pu();
- printf("after: %i\n", m[ 0 ]);
+
+// runs pu until exit code != 2,
+// that exit code is an interrupt for talking to the emulated hardware
+int emu() {
+ while (1) {
+ pu();
+ int e_code = m[ 0 ];
+
+ if (e_code != 2) return e_code;
+
+ // handle hardware interrupts
+ int int_code = m[ 1 ];
+
+ // 0: output string
+ if (int_code == 0) {
+ int ptr = m[ 2 ];
+ int size = m[ 3 ], i = 0;
+
+ for (; i < size; i++) putchar(m[ ptr++ ]);
+ write(STDOUT_FILENO, &m[ ptr ], size);
+ }
+
+ // 1: input character
+ else if (int_code == 1) {
+ m[ 2 ] = getchar();
+ }
+
+ else {
+ // unknown interrupt. what to do?
+ }
+
+ m[ 0 ] = 0;
+ m[ 7 ]++;
+ }
+}
+
+char R_backup[] = "hlt\0 ar1\2 ar2\3 ar3\4 ar4\5 ar5\6 ar6\7 ar7\x8 ar8\x9 r1a\xA r2a\xB r3a\xC "
+ "r4a\xD r5a\xE r6a\xF r7a\20 r8a\21 mem\22 aca\23 add\24 sub\25 not\26 clr\27";
+
+int main(int argc, char **argv) {
+ if (access("t", F_OK)) {
+ // patch the instruction table incase you removed it.
+ printf("you've deleted t! i'll write it again for you.\n\n");
+ FILE *fp = fopen("t", "w+");
+ fwrite(R_backup, 1, sizeof(R_backup), fp);
+ fclose(fp);
+ memcpy(R, R_backup, sizeof(R_backup));
+ }
+
+ if (argc == 1) {
+ printf("Usage:\n %s <filename>", argv[ 0 ]);
+ exit(1);
+ }
+
+ // read code
+ FILE *fp = fopen(argv[ 1 ], "r");
+ fseek(fp, 0, SEEK_END);
+ int sz = ftell(fp);
+ rewind(fp);
+ char code[ sz + 1 ];
+ fread(code, 1, sz, fp);
+ code[ sz ] = 0;
+ fclose(fp);
+
+ // set pc
+ m[ 7 ] = 1024;
+ // assemble
+ char *fail_point = as(code, &m[ 1024 ]);
+
+ if (fail_point != 0) {
+ int error_pos = (int) (fail_point - code);
+ int i;
+
+ int line = 1, col = 1;
+ for (i = 0; i < error_pos && i < sz; i++) {
+ if (code[ i ] == '\n') {
+ line++;
+ col = 1;
+ } else {
+ col++;
+ }
+ }
+
+ fprintf(
+ stderr, "Assembly failed at line %d, column %d (position %d):\n", line, col, error_pos);
+
+ int line_start = error_pos;
+ while (line_start > 0 && code[ line_start - 1 ] != '\n') { line_start--; }
+
+ int line_end = error_pos;
+ while (line_end < sz && code[ line_end ] != '\n' && code[ line_end ] != '\0') {
+ line_end++;
+ }
+
+ fprintf(stderr, " ");
+ for (i = line_start; i < line_end; i++) { fputc(code[ i ], stderr); }
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " ");
+ for (i = line_start; i < error_pos; i++) { fputc(' ', stderr); }
+ fprintf(stderr, "^ parsing stopped here\n");
+
+ exit(1);
+ }
+
+ // run emulation
+ emu();
}
#endif \ No newline at end of file
diff --git a/pu.out.c b/pu.out.c
index 330e6f0..4d0c9af 100644
--- a/pu.out.c
+++ b/pu.out.c
@@ -3,14 +3,19 @@
#pragma clang diagnostic ignored "-Wreturn-type"
#pragma clang diagnostic ignored "-Wc23-extensions"
+// clang-format off
#define S 65536
#define H !--c?
#define W case
#define Q goto M;
-m[S],c,a;pu(){while((c=m[m[7]++]))H*m=m[m[7]++]:c--<9?a?m[c]=*m:0:8>(c-=8)?*m=m[c]:!(c-=8)?m[m[1]]=*m:H*m=a:H a+=*m:H a-=*m:H a=!a:H a=0:0;}
-char *R="hlt\0 ar1\2 ar2\3 ar3\4 ar4\5 ar5\6 ar6\7 ar7\x8 ar8\x9 r1a\xA r2a\xB r3a\xC r4a\xD r5a\xE r6a\xF r7a\20 r8a\21 mem\22 aca\23 add\24 sub\25 not\26 clr\27";K;as(char*I,int*O){char*V=R;while((K=*I)){V=R;switch(K){case 32:case 10:case 9:I++;Q}while(*V)V+=3,(strncmp(V-3,I,3)?:({*O++=*V;I+=3;Q})),V+=2;strncmp("con ",I,4)?:({*O++=1,*O++=atoi(I+=4);while(*I>47&*I<58)I++;Q});return 1;M:}return 0;}
+#define J while
+m[S],c,a;pu(){J((c=m[m[7]++]))H*m=m[m[7]++]:c--<9?!a?m[c]=*m:0:8>(c-=8)?*m=m[c]:!(c-=8)?m[m[1]]=*m:H*m=a:H a+=*m:H a-=*m:H a=!a:H a=0:0;}char R[]={
+#embed"t"
+};K;as(char*I,int*O){char*V=R;J((K=*I)){V=R;switch(K){W 32:W 10:W 9:I++;Q;W 35:J(*++I!=10);Q}strncmp("con ",I,4)?:({*O++=1,*O++=atoi(I+=4);J(*I>47&*I<58)I++;Q});J(*V)V+=3,(strncmp(V-3,I,3)?:({*O++=*V;I+=3;Q})),V+=2;return 1;M:}return 0;}
+// clang-format on
#undef S
#undef H
+#undef J
#undef Q
#undef W \ No newline at end of file
diff --git a/t b/t
new file mode 100644
index 0000000..7b992ff
--- /dev/null
+++ b/t
Binary files differ