aboutsummaryrefslogtreecommitdiff
path: root/pu2/pu2.c
diff options
context:
space:
mode:
Diffstat (limited to 'pu2/pu2.c')
-rw-r--r--pu2/pu2.c254
1 files changed, 157 insertions, 97 deletions
diff --git a/pu2/pu2.c b/pu2/pu2.c
index ac09efa..6121d8b 100644
--- a/pu2/pu2.c
+++ b/pu2/pu2.c
@@ -1,3 +1,4 @@
+#define _POSIX_C_SOURCE 200809L
#include "pu2.out.c"
#include <stdio.h>
#include <time.h>
@@ -42,27 +43,38 @@ error_debug(string fail_point, string code, int sz) {
}
}
+ 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++; }
+
+ int tmp = line;
+ int lineno_width = 1;
+ while (tmp >= 10) {
+ lineno_width++;
+ tmp /= 10;
+ }
+
fprintf(
stderr,
- "\x1b[1m\x1b[31merror:\x1b[0m "
- "\x1b[1massembly failed\x1b[0m "
+ "\x1b[1m\x1b[31merror:\x1b[0m \x1b[1massembly failed\x1b[0m "
"at \x1b[36mline %d\x1b[0m, \x1b[36mcolumn %d\x1b[0m "
"(\x1b[33mposition %d\x1b[0m):\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, " \x1b[1m");
- for (i = line_start; i < line_end; i++) { fputc(code[ i ], stderr); }
- fprintf(stderr, "\x1b[0m\n");
+ fprintf(
+ stderr,
+ " %*d | \x1b[1m%.*s\x1b[0m\n",
+ lineno_width,
+ line,
+ line_end - line_start,
+ code + line_start);
- fprintf(stderr, " ");
+ /* print caret line aligned under the column */
+ fprintf(stderr, " %*s | ", lineno_width, "");
for (i = line_start; i < error_pos; i++) { fputc((code[ i ] == '\t') ? '\t' : ' ', stderr); }
fprintf(stderr, "\x1b[1m\x1b[31m^\x1b[0m \x1b[90mparsing stopped here\x1b[0m\n");
}
@@ -173,6 +185,11 @@ typedef struct {
slice value;
} entry;
+typedef struct {
+ entry data;
+ byte arg_count;
+} macro;
+
clean_slice_ref(slice *val) { free(val->ref); }
#define static_len(G) (sizeof(G) / sizeof((G)[ 0 ]))
@@ -187,26 +204,21 @@ clean_slice_ref(slice *val) { free(val->ref); }
emit(opcode.acc, 1); \
emit(opcode.str, 0); \
})
-#define run_err(result) \
+#define run_err(result, ...) \
({ \
- printf("\n"); \
+ ERR_code = init_I; \
+ fprintf(stderr, "\n"); \
error_debug((result), ERR_code, strlen(ERR_code)); \
- printf("\nir2 error message: %s\n", ERR); \
- printf("\n"); \
+ fprintf(stderr, "\n\x1b[1m\x1b[31mir2 error:\x1b[0m "); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n\n"); \
exit(1); \
})
-#define checkskip(char, message) \
+#define checkskip(char, ...) \
({ \
- if (!*I) { \
- ERR = (message); \
- run_err(I); \
- } \
- if (*I++ != (char) ) { \
- ERR = (message); \
- ERR_code = init_I; \
- run_err(I - 1); \
- } \
+ if (!*I) { run_err(I, __VA_ARGS__); } \
+ if (*I++ != (char) ) { run_err(I - 1, __VA_ARGS__); } \
})
#define scanword() \
({ \
@@ -245,8 +257,7 @@ clean_slice_ref(slice *val) { free(val->ref); }
Data[ -1 ] = 0; \
value = Data - m; \
} else { \
- ERR = "expected value (number, character, string)"; \
- run_err(I); \
+ run_err(I, "expected value (number, character, string)"); \
} \
value; \
})
@@ -295,7 +306,7 @@ string ERR;
string ERR_code;
int *Code = &m[ 4000 ];
int *Data = &m[ static_len(m) - 1 ]; // grows downwards
-_ir2(string I, entry macros[ 1 << 9 ]) {
+_ir2(string I, macro macros[ 1 << 9 ]) {
string init_I = I;
ERR = "all good";
@@ -319,10 +330,7 @@ _ir2(string I, entry macros[ 1 << 9 ]) {
if (*I == '@') {
I++;
- if (!isdigit(*I)) {
- ERR = "expected a digit after @";
- run_err(I);
- }
+ if (!isdigit(*I)) { run_err(I, "expected a digit after @"); }
int mem2_index = strtol(I, &I, 10);
@@ -387,8 +395,7 @@ _ir2(string I, entry macros[ 1 << 9 ]) {
// parse macro stuff
if (!isalpha(*I) && *I != '_') {
- ERR = "expected letter at macro name";
- run_err(I - 1);
+ run_err(I - 1, "expected letter or underscore at macro name");
}
slice name = scanword();
@@ -398,10 +405,18 @@ _ir2(string I, entry macros[ 1 << 9 ]) {
skip_space(&I);
+ string before = I;
+ int arg_count = strtol(I, &I, 10);
+ if (I == before) {
+ run_err(I, "expected number (argument count) in macro definition parens");
+ }
+
+ skip_space(&I);
+
checkskip(
')',
- "expected close paren in macro definition (hint: macros do not take named "
- "arguments)");
+ "expected close paren in macro definition (hint: macro defintions only take an "
+ "argument count)");
skip_space(&I);
@@ -410,26 +425,26 @@ _ir2(string I, entry macros[ 1 << 9 ]) {
// find open space in macros
int x;
for (x = 0; x < (1 << 9); x++) {
- entry g = macros[ x ];
- if (g.key.ref == NULL) { goto DONE; }
+ macro g = macros[ x ];
+ if (g.data.key.ref == NULL) { goto DONE; }
}
- ERR = "macro count exceeded 1<<9";
- run_err(I - 1);
+ run_err(I - 1, "registered macro count exceeded 1<<9 (how?)");
DONE:;
skip_space(&I); // might aswell skip whitespace for funsies.
- entry *g = &macros[ x ];
- g->key = name;
- g->value.ref = I;
- g->value.len = 0;
+ macro *g = &macros[ x ];
+ g->data.key = name;
+ g->data.value.ref = I;
+ g->data.value.len = 0;
+ g->arg_count = arg_count;
int dep = 0;
while (dep != 0 || *I != '}') {
if (*I == '{') dep++;
if (*I == '}') dep--;
- g->value.len++;
+ g->data.value.len++;
I++;
if (*I == 0) {
@@ -449,8 +464,7 @@ _ir2(string I, entry macros[ 1 << 9 ]) {
string old = I;
int value = strtol(I, &I, 10);
if (old == I && *I != ')') {
- ERR = "invalid input to exit blob, expected number";
- run_err(I - 1);
+ run_err(I - 1, "invalid input to exit blob, expected number");
}
skip_space(&I);
@@ -497,11 +511,10 @@ _ir2(string I, entry macros[ 1 << 9 ]) {
slice arguments[ 1 << 7 ];
size_t arg_count = 0;
+ string fail_I = I;
+
while (*I != ')') {
- if (!*I) {
- ERR = "reached EOF whilst looking for closing paren on blob";
- run_err(I);
- }
+ if (!*I) run_err(fail_I, "reached EOF whilst looking for closing paren on blob");
checkskip('[', "expected bracket in blob argument (macro-type)");
arguments[ arg_count ].len = 0;
@@ -525,8 +538,7 @@ _ir2(string I, entry macros[ 1 << 9 ]) {
skip_space(&I);
if (*I != ',' && *I != ')') {
- ERR = "expected comma or closing paren in blob";
- run_err(I);
+ run_err(I, "expected comma or closing paren in blob");
}
if (*I == ',') {
@@ -537,6 +549,8 @@ _ir2(string I, entry macros[ 1 << 9 ]) {
arg_count++;
}
+ fail_I = I;
+
checkskip(')', "expected closing paren after blob arguments");
skip_space(&I);
checkskip(';', "expected semicolon after blob");
@@ -545,16 +559,22 @@ _ir2(string I, entry macros[ 1 << 9 ]) {
// find index
size_t i;
for (i = 0; i < (1 << 9); i++) {
- entry cur = macros[ i ];
- if (cur.key.len != name.len) continue;
- if (strncmp(name.ref, cur.key.ref, name.len) == 0) goto FOUND;
+ macro cur = macros[ i ];
+ if (cur.data.key.len != name.len) continue;
+ if (strncmp(name.ref, cur.data.key.ref, name.len) == 0) goto FOUND;
}
- ERR = "could not find a macro by that name";
- run_err(I);
+ run_err(I, "could not find a macro by that name");
FOUND:;
- slice target = macros[ i ].value;
+ if (arg_count != macros[ i ].arg_count) {
+ run_err(
+ fail_I,
+ "macro argument count mismatch (expected %i, got %li)",
+ macros[ i ].arg_count,
+ arg_count);
+ }
+ slice target = macros[ i ].data.value;
string N = target.ref;
string oldN = N;
memslice new = { target.len, malloc(target.len) };
@@ -613,11 +633,12 @@ _ir2(string I, entry macros[ 1 << 9 ]) {
}
ir2(string I) {
- entry macros[ 1 << 9 ];
+ macro macros[ 1 << 9 ] = {0};
_ir2(I, macros);
}
-string op_names[] = { "hlt", "imm", "lod", "str", "swp", "add", "sub", "and", "not", "acc" };
+string op_names[] = { "hlt", "imm", "lod", "str", "swp", "add", "sub",
+ "and", "not", "acc", "a2u", "u2a", "b2u", "u2b" };
unsigned long long rdtsc(void) {
unsigned hi, lo;
@@ -646,14 +667,39 @@ double bench_cycle(int instr) {
return (double) m[ 7 ] / seconds / 1e6;
}
-benchmark() {
+double bench2_cycle(int instr) {
+ unsigned long long start, end;
+ double vminst_count, cpu_cycles;
+ 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;
+ start = rdtsc();
+ pu2();
+ end = rdtsc();
+ cpu_cycles = (double) (end - start);
+ vminst_count = (double) m[ 7 ];
+ printf("pu2/real: %f\n", cpu_cycles / vminst_count);
+ return cpu_cycles / vminst_count;
+}
+
+benchmark(double (*target)(int)) {
double results[ 13 ];
- double sum = 0;
- for (i = 0; i < 13; i++) {
- results[ i ] = bench_cycle(i);
+ double sum = 0;
+ int count = 0;
+ int i;
+ for (i = 1; i < 14; i++) {
+ printf("running: %s\n", op_names[ i ]);
+ results[ i ] = target(i);
sum += results[ i ];
+ count++;
}
- sum /= 13;
+ sum /= count;
unsigned long long start, end;
start = rdtsc();
@@ -661,18 +707,57 @@ benchmark() {
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);
+ if (target == bench_cycle) {
+ printf("clock speed ~ %.6f MHz\n", clock_speed);
+ printf("instructions per cycle: %f\n", clock_speed / sum);
+ }
}
-main() {
+long nstime() {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts.tv_nsec;
+}
+
+main(int argc, char **argv) {
+ if (argc == 1) {
+ return printf(
+ "\nusage:\n"
+ " %s <file_name> open and compile ir2-compliant code\n"
+ " %s --bench benchmark pu2\n\n",
+ argv[ 0 ],
+ argv[ 0 ]);
+ }
+
+ if (strcmp(argv[ 1 ], "--bench") == 0) {
+ benchmark(bench_cycle);
+ benchmark(bench2_cycle);
+ exit(0);
+ }
+
+ char *filename = argv[ 1 ];
+ size_t file_size;
+ string contents = read_file(filename, &file_size);
+ if (contents == NULL) {
+ perror("unable to open file");
+ exit(1);
+ }
+
size_t o_size;
- ir2(read_file("code.i2", &o_size));
+ long before = nstime();
+ long cycles_bef = rdtsc();
+ ir2(contents);
+ long cycles_aft = rdtsc();
+ long after = nstime();
m[ 7 ] = 4000;
+ // fprintf(stderr, "assembly took %li nanoseconds (%li cycles)\n", (after - before), (cycles_aft - cycles_bef));
+ free(contents);
+
size_t res_size = Code - &m[ 4000 ];
// --- BYTES PRINTING ---
+
// for(i = 0; i < res_size; i++) {
// printf("%X%X ", m[4000+i]>>4, m[4000+i]&0b1111);
// if(i % 8 == 7) printf("\n");
@@ -681,6 +766,7 @@ main() {
// printf("\n\n");
// --- OPCODES PRINTING ---
+
// for (i = 0; i < res_size; i++) {
// int op = m[ 4000 + i++ ];
// int data = m[ 4000 + i ];
@@ -690,30 +776,4 @@ main() {
// printf("\n\n");
emu();
- printf("result: %i\n", m[ 10 ]);
-}
-
-main2(int argc, char **argv) {
- if (argc == 1) {
- return printf(
- "\nusage:\n"
- " %s <file_name>\n\n",
- argv[ 0 ]);
- }
-
- char *filename = argv[ 1 ];
- size_t file_size;
- char *contents = read_file(filename, &file_size);
-
- E = 0;
- K = &m[ 1024 ];
- as2(contents);
-
- if (E != 0) {
- error_debug(E, contents, file_size);
- exit(1);
- }
-
- m[ 7 ] = 1024;
- emu();
}