aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Moon Flower <moon@coffin.ir> 2025-08-12 20:27:34 +0330
committerGravatar Moon Flower <moon@coffin.ir> 2025-08-12 20:27:34 +0330
commit15914727d83a6f46ad724e126179713d935e5e6f (patch)
tree2f601872b7575e4f3c0ca8c366fb2a1e1ea1b4fb
parentir2 initial release! (diff)
ir2 prototype! includes strings and DATA segment and other stuffs :3
-rw-r--r--.gitignore3
-rw-r--r--pu1/pasm-syntax/pasm-syntax-0.0.1.vsixbin2163 -> 0 bytes
-rw-r--r--pu2/code.i211
-rw-r--r--pu2/i2-syntax/syntaxes/i2.tmLanguage.json21
-rw-r--r--pu2/p2m-syntax/p2m-asm-syntax-0.0.1.vsixbin3130 -> 0 bytes
-rwxr-xr-xpu2/pu2bin0 -> 30104 bytes
-rw-r--r--pu2/pu2.c216
-rw-r--r--pu2/pu2.out.c57
-rwxr-xr-xpu2/pu2.sobin0 -> 15776 bytes
-rw-r--r--pu2/pu2test.c21
-rw-r--r--pu2/testing.i25
11 files changed, 212 insertions, 122 deletions
diff --git a/.gitignore b/.gitignore
index d56a83a..dfacd4d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1 @@
-pu
-putest \ No newline at end of file
+*.vsix \ No newline at end of file
diff --git a/pu1/pasm-syntax/pasm-syntax-0.0.1.vsix b/pu1/pasm-syntax/pasm-syntax-0.0.1.vsix
deleted file mode 100644
index e94bb8b..0000000
--- a/pu1/pasm-syntax/pasm-syntax-0.0.1.vsix
+++ /dev/null
Binary files differ
diff --git a/pu2/code.i2 b/pu2/code.i2
index 772fd85..216cd54 100644
--- a/pu2/code.i2
+++ b/pu2/code.i2
@@ -1,11 +1,16 @@
-macro putchar() {
+macro setup_io() {
@1 = 0; // write
@2 = 10; // ptr
@3 = 1; // size
- @10 = /1/; // value
- system(); // interrupt (@0 = 2; halt;)
}
+macro putchar() {
+ @10 = /1/;
+ system();
+}
+
+setup_io();
+
putchar(['h']);
putchar(['e']);
putchar(['l']);
diff --git a/pu2/i2-syntax/syntaxes/i2.tmLanguage.json b/pu2/i2-syntax/syntaxes/i2.tmLanguage.json
index d740a7d..4dc6ee9 100644
--- a/pu2/i2-syntax/syntaxes/i2.tmLanguage.json
+++ b/pu2/i2-syntax/syntaxes/i2.tmLanguage.json
@@ -14,6 +14,7 @@
{ "include": "#variables" },
{ "include": "#hex" },
{ "include": "#decimal" },
+ { "include": "#string" },
{ "include": "#char" },
{ "include": "#blob" },
{
@@ -35,6 +36,7 @@
{ "include": "#variables" },
{ "include": "#hex" },
{ "include": "#decimal" },
+ { "include": "#string" },
{ "include": "#char" },
{ "include": "#blob" }
]
@@ -85,6 +87,23 @@
"name": "constant.numeric.decimal.i2",
"match": "\\b\\d+\\b"
},
+ "string": {
+ "begin": "\"",
+ "beginCaptures": {
+ "0": { "name": "punctuation.definition.string.begin.i2" }
+ },
+ "end": "\"",
+ "endCaptures": {
+ "0": { "name": "punctuation.definition.string.end.i2" }
+ },
+ "name": "string.quoted.double.i2",
+ "patterns": [
+ {
+ "name": "constant.character.escape.i2",
+ "match": "\\\\."
+ }
+ ]
+ },
"char": {
"name": "string.quoted.single.char.i2",
"match": "'(\\\\.|[^'\\\\])'"
@@ -103,4 +122,4 @@
]
}
}
-} \ No newline at end of file
+}
diff --git a/pu2/p2m-syntax/p2m-asm-syntax-0.0.1.vsix b/pu2/p2m-syntax/p2m-asm-syntax-0.0.1.vsix
deleted file mode 100644
index 65e5608..0000000
--- a/pu2/p2m-syntax/p2m-asm-syntax-0.0.1.vsix
+++ /dev/null
Binary files differ
diff --git a/pu2/pu2 b/pu2/pu2
new file mode 100755
index 0000000..c9ee9dc
--- /dev/null
+++ b/pu2/pu2
Binary files differ
diff --git a/pu2/pu2.c b/pu2/pu2.c
index 66794bc..66fefbf 100644
--- a/pu2/pu2.c
+++ b/pu2/pu2.c
@@ -1,63 +1,5 @@
-#include <ctype.h>
+#include "pu2.out.c"
#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#pragma clang diagnostic ignored "-Wparentheses"
-#pragma clang diagnostic ignored "-Wreturn-type"
-#pragma clang diagnostic ignored "-Wempty-body"
-
-// pu2!
-// maybe compacter? idk
-// last cpu: 167 chars
-
-// NOTE: if you want the cpu to
-// crash or do something when an invalid opcode is met,
-// replace the `8` in the code with whatever behavior you desire.
-// you can use ({...}) to insert normal code, or use __builtin_trap() for a SIGTRAP
-
-// clang-format off
-#define S 1<<20
-#define H !--c
-#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=a&&b:H?a=!a:H?u=1:8;u=v;}}
-// 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
-
-// NOTE: Memory indexes less than 1024 should be considered as temporary/compute memory, and
-// programs should be written at index 1024 and upwards.
-//
-// NOTE: Memory index 7 is the program
-// counter, in which the current instruction is read from m[m[7]] at each cycle
-
-// -------------------------
-
-// yeehaw baby it's time for as2
-// E is the error code loc. zero it before calling as2
-// Y is macro storage. extend as needed
-// set O for output before running. keep in mind, it gets modified whilst as2 is running.
-// therefore, i recommend you store a copy somewhere!
-
-// clang-format off
-char*C="hltimmlodstrswpaddsubandnotacc",*Y[1<<10],*E,*L,i;*O;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;*O++=i-1;*O++=i-2?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;}):({*O++=1;*O++=*I++;}):0);}}
-// clang-format on
-
-#undef S
-#undef H
-#undef J
-
-#ifndef __WRAPPER
typedef char *string;
@@ -139,7 +81,6 @@ emu() {
int ptr = m[ 2 ];
int size = m[ 3 ], i = 0;
- for (; i < size; i++) putchar(m[ ptr++ ]);
while (size--) putchar(m[ ptr++ ]);
}
@@ -167,30 +108,6 @@ struct {
} opcode = {
0, 1, 2, 3, 4, 5, 6, 7, 8,9
};
-
-#define emit(OP, VAL) ({ *(*O)++ = (OP); *(*O)++ = (VAL); })
-#define store() ({ emit(opcode.acc, 1); emit(opcode.str, 0); })
-#define run_err(result) \
- ({ \
- printf("\n"); \
- error_debug((result), ERR_code, strlen(ERR_code)); \
- printf("\nir2 error message: %s\n", ERR); \
- printf("\n"); \
- exit(1); \
- })
-
-#define checkskip(char, message) \
- ({ \
- if (!*I) { \
- ERR = (message); run_err(I); \
- } \
- if (*I++ != (char) ) { \
- ERR = (message); ERR_code=init_I; run_err(I-1); \
- } \
- })
-#define scanword() ({ slice VAR = { 0, I}; while (isalnum(*I)) VAR.len++, I++; VAR; })
-#define memslice slice __attribute__((cleanup(clean_slice_ref)))
-#define readd() ({ if(used == new.len) new.ref = realloc(new.ref, new.len *= 2); })
// clang-format on
typedef unsigned char byte;
@@ -211,10 +128,88 @@ typedef struct {
clean_slice_ref(slice *val) { free(val->ref); }
+#define static_len(G) (sizeof(G) / sizeof((G)[ 0 ]))
+
+#define emit(OP, VAL) \
+ ({ \
+ *Code++ = (OP); \
+ *Code++ = (VAL); \
+ })
+#define store() \
+ ({ \
+ emit(opcode.acc, 1); \
+ emit(opcode.str, 0); \
+ })
+#define run_err(result) \
+ ({ \
+ printf("\n"); \
+ error_debug((result), ERR_code, strlen(ERR_code)); \
+ printf("\nir2 error message: %s\n", ERR); \
+ printf("\n"); \
+ exit(1); \
+ })
+
+#define checkskip(char, message) \
+ ({ \
+ if (!*I) { \
+ ERR = (message); \
+ run_err(I); \
+ } \
+ if (*I++ != (char) ) { \
+ ERR = (message); \
+ ERR_code = init_I; \
+ run_err(I - 1); \
+ } \
+ })
+#define scanword() \
+ ({ \
+ slice VAR = { 0, I }; \
+ while (isalnum(*I) || *I == '_') VAR.len++, I++; \
+ VAR; \
+ })
+#define memslice slice __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. */ \
+ int value; \
+ if (isdigit(*I)) { \
+ value = strtol(I, &I, 10); \
+ } else if (*I == '\'') { \
+ I++; \
+ value = *I++; \
+ checkskip('\'', "couldn't find closing quote on character"); \
+ } else if (*I == '"') { \
+ string str_start = ++I; \
+ bool T = false; \
+ size_t str_len = 0; \
+ while (*I != '"' || T) { \
+ if (*I == '\\') { \
+ T = !T; \
+ if (!T && I[ 1 ] == '"') str_len--; \
+ } \
+ str_len++; \
+ I++; \
+ } \
+ I++; \
+ str_len++; \
+ int *dest_start = Data -= str_len; \
+ int y; \
+ for (y = 0; y < str_len-1; y++) { dest_start[ y ] = str_start[ y ]; } \
+ Data[ -1 ] = 0; \
+ value = Data - m; \
+ } else { \
+ ERR = "expected value (number, character, string)"; \
+ run_err(I); \
+ } \
+ value; \
+ })
+
T;
string ERR;
string ERR_code;
-_ir2(string I, int **O, entry macros[ 1 << 9 ]) {
+int *Code = &m[ 4000 ];
+int *Data = &m[ static_len(m) - 1 ]; // grows downwards
+_ir2(string I, entry macros[ 1 << 9 ]) {
string init_I = I;
ERR = "all good";
@@ -249,15 +244,8 @@ _ir2(string I, int **O, entry macros[ 1 << 9 ]) {
emit(opcode.swp, 0);
emit(opcode.imm, mem_index);
store();
- } else if (isdigit(*I) || *I == '\'') {
- int imm;
- if (*I == '\'') {
- I++;
- imm = *I++;
- checkskip('\'', "couldn't find closing quote on character");
- } else {
- imm = strtol(I, &I, 10);
- }
+ } else {
+ int imm = scanvalue();
emit(opcode.imm, imm);
emit(opcode.swp, 0);
@@ -276,7 +264,7 @@ _ir2(string I, int **O, entry macros[ 1 << 9 ]) {
skip_space(&I);
// parse macro stuff
- if (!isalpha(*I)) {
+ if (!isalpha(*I) && *I != '_') {
ERR = "expected letter at macro name";
run_err(I - 1);
}
@@ -367,7 +355,11 @@ _ir2(string I, int **O, entry macros[ 1 << 9 ]) {
skip_space(&I);
checkskip(';', "expected semicolon after system blob");
- _ir2("@0 = 2; exit();", O, macros);
+ emit(opcode.imm, 2);
+ emit(opcode.swp, 0);
+ emit(opcode.imm, 0);
+ store();
+ emit(opcode.hlt, 0);
continue;
}
@@ -491,31 +483,43 @@ _ir2(string I, int **O, entry macros[ 1 << 9 ]) {
new.ref[ used ] = 0;
- _ir2(new.ref, O, macros);
+ _ir2(new.ref, macros);
continue;
}
}
}
-ir2(string I, int **O) {
+ir2(string I) {
entry macros[ 1 << 9 ];
- _ir2(I, O, macros);
+ _ir2(I, macros);
}
+string op_names[] = { "hlt", "imm", "lod", "str", "swp", "add", "sub", "and", "not", "acc" };
+
main() {
- int *out = &m[ 1024 ];
size_t o_size;
- ir2(read_file("code.i2", &o_size), &out);
- m[ 7 ] = 1024;
+ ir2(read_file("testing.i2", &o_size));
+ m[ 7 ] = 4000;
- // size_t res_size = out - &m[ 1024 ];
+ size_t res_size = Code - &m[ 4000 ];
+ // --- BYTES PRINTING ---
// for(i = 0; i < res_size; i++) {
- // printf("%i ", m[1024+i]);
+ // printf("%X%X ", m[4000+i]>>4, m[4000+i]&0b1111);
+ // if(i % 8 == 7) printf("\n");
// }
// fflush(stdout);
// printf("\n\n");
+ // --- OPCODES PRINTING ---
+ // for (i = 0; i < res_size; i++) {
+ // int op = m[ 4000 + i++ ];
+ // int data = m[ 4000 + i ];
+
+ // printf("%s(%i);\n", op_names[ op ], data);
+ // }
+ // printf("\n\n");
+
emu();
}
@@ -532,7 +536,7 @@ main2(int argc, char **argv) {
char *contents = read_file(filename, &file_size);
E = 0;
- O = &m[ 1024 ];
+ K = &m[ 1024 ];
as2(contents);
if (E != 0) {
@@ -543,5 +547,3 @@ main2(int argc, char **argv) {
m[ 7 ] = 1024;
emu();
}
-
-#endif \ No newline at end of file
diff --git a/pu2/pu2.out.c b/pu2/pu2.out.c
new file mode 100644
index 0000000..e13c983
--- /dev/null
+++ b/pu2/pu2.out.c
@@ -0,0 +1,57 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#pragma clang diagnostic ignored "-Wparentheses"
+#pragma clang diagnostic ignored "-Wreturn-type"
+#pragma clang diagnostic ignored "-Wempty-body"
+
+// pu2!
+// maybe compacter? idk
+// last cpu: 167 chars
+
+// NOTE: if you want the cpu to
+// crash or do something when an invalid opcode is met,
+// replace the `8` in the code with whatever behavior you desire.
+// you can use ({...}) to insert normal code, or use __builtin_trap() for a SIGTRAP
+
+// clang-format off
+#define S 1<<20
+#define H !--c
+#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:8;u=v;}}
+// 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
+
+// NOTE: Memory indexes less than 1024 should be considered as temporary/compute memory, and
+// programs should be written at index 1024 and upwards.
+//
+// NOTE: Memory index 7 is the program
+// counter, in which the current instruction is read from m[m[7]] at each cycle
+
+// -------------------------
+
+// yeehaw baby it's time for as2
+// E is the error code loc. zero it before calling as2
+// Y is macro storage. extend as needed
+// set O for output before running. keep in mind, it gets modified whilst as2 is running.
+// 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);}}
+// clang-format on
+
+#undef S
+#undef H
+#undef J \ No newline at end of file
diff --git a/pu2/pu2.so b/pu2/pu2.so
new file mode 100755
index 0000000..41889b2
--- /dev/null
+++ b/pu2/pu2.so
Binary files differ
diff --git a/pu2/pu2test.c b/pu2/pu2test.c
index 93d76aa..8b94cad 100644
--- a/pu2/pu2test.c
+++ b/pu2/pu2test.c
@@ -1,5 +1,4 @@
-#define __WRAPPER
-#include "pu2.c"
+#include "pu2.out.c"
#include <stdio.h>
#include <string.h>
@@ -13,11 +12,15 @@
static int total_tests = 0;
static int passed_tests = 0;
+#define static_len(G) (sizeof(G) / sizeof((G)[ 0 ]))
+
/* helper: load program at pc and set PC (m[7]) */
void load_prog(int pc, int *prog, int len) {
int i;
+ a = b = 0;
+ u = 1;
/* clear memory (keeps tests isolated) */
- for (i = 0; i < S; ++i) m[ i ] = 0;
+ for (i = 0; i < static_len(m); ++i) m[ i ] = 0;
for (i = 0; i < len; ++i) m[ pc + i ] = prog[ i ];
m[ 7 ] = pc;
}
@@ -33,7 +36,7 @@ void expect_int(const char *name, int got, int want) {
}
}
-unsigned char outbuf[ 512 ];
+int outbuf[ 512 ];
void zero_Y(void) {
int ii;
@@ -42,7 +45,7 @@ void zero_Y(void) {
void set_outbuf(void) {
memset(outbuf, 0, sizeof outbuf);
- O = (char *) outbuf;
+ O = outbuf;
zero_Y();
}
@@ -165,7 +168,7 @@ int main(void) {
/* Assembler (as2) tests: use outbuf */
{
- unsigned char *o;
+ int *o;
set_outbuf();
as2("hlt");
@@ -188,19 +191,19 @@ int main(void) {
expect_int("sub:imm", o[ 3 ], 0);
set_outbuf();
- as2("(0 hlt) @0");
+ as2("{0 hlt} @0");
o = outbuf;
expect_int("macro-hlt:opcode", o[ 0 ], 0);
expect_int("macro-hlt:imm", o[ 1 ], 0);
set_outbuf();
- as2("(0 imm 7) @0");
+ as2("{0 imm 7} @0");
o = outbuf;
expect_int("macro-imm:opcode", o[ 0 ], 1);
expect_int("macro-imm:imm", o[ 1 ], 7);
set_outbuf();
- as2("(0 imm 3 add) @0");
+ as2("{0 imm 3 add} @0");
o = outbuf;
expect_int("macro-mix:imm-op", o[ 0 ], 1);
expect_int("macro-mix:imm-val", o[ 1 ], 3);
diff --git a/pu2/testing.i2 b/pu2/testing.i2
new file mode 100644
index 0000000..f7ca192
--- /dev/null
+++ b/pu2/testing.i2
@@ -0,0 +1,5 @@
+@1 = 0; // write
+@2 = "hello"; // ptr
+@3 = 5; // size
+system(); // interrupt
+