summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-09-18 14:49:07 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2020-09-18 14:49:07 -0400
commiteea04e3327972f052dcfb8ae0854b77f87d3d52f (patch)
treee6c65aad43cb65eb152dc55fba1eb13efffdf7f2
parent385a621b9487456c3167f204b02cb0ea0752191d (diff)
- Added support for structs, and unions to the
emulator's assembler. - Make the symbol table a doublely linked list, in both ways. - Optimized the memcopy() function. - Changed the benchmark timing, to now use a timer, and stops once the timer reaches zero. When the timer hits zero, it sends SIGALRM to the main function, which tells the emulator that the benchmark is done.
-rw-r--r--asmmon.c6
-rw-r--r--asmmon.h46
-rw-r--r--assemble.c154
-rw-r--r--lexer.c148
-rw-r--r--sux.c118
-rw-r--r--sux.h159
-rw-r--r--test/popcnt2.s4
-rw-r--r--test/struct.s31
8 files changed, 493 insertions, 173 deletions
diff --git a/asmmon.c b/asmmon.c
index 6b71ac3..eac72d5 100644
--- a/asmmon.c
+++ b/asmmon.c
@@ -203,10 +203,16 @@ void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, u
break;
case TOK_SYM:
case TOK_LABEL:
+ case TOK_STRUCT:
+ case TOK_UNION:
+ case TOK_MEMBER:
if (t->type == 1) {
putchar('@');
}
printf("%s", (t->sym) ? t->sym->name : "unknown");
+ if (t->sym && t->sym->isstruct && t->next && t->next->id == TOK_SYM) {
+ putchar('.');
+ }
if (t->id == TOK_LABEL) {
putchar(':');
}
diff --git a/asmmon.h b/asmmon.h
index 633ed38..7db9b4c 100644
--- a/asmmon.h
+++ b/asmmon.h
@@ -55,9 +55,12 @@ struct fix {
struct sym {
symbol *next;
- symbol *local;
+ symbol *prev;
+ symbol *down;
+ symbol *up;
uint16_t count;
uint64_t val;
+ uint8_t isstruct;
uint8_t def;
char *name;
uint16_t id;
@@ -93,7 +96,11 @@ enum dir {
DIR_DWORD,
DIR_QWORD,
DIR_INCLUDE,
- DIR_RES
+ DIR_RES,
+ DIR_STRUCT,
+ DIR_UNION,
+ DIR_ENDSTRUCT,
+ DIR_ENDUNION
};
enum token {
@@ -115,7 +122,11 @@ enum token {
TOK_HEX,
TOK_DEC,
TOK_BIN,
- TOK_INCLUDE
+ TOK_INCLUDE,
+ TOK_STRUCT,
+ TOK_UNION,
+ TOK_MEMBER
+
};
enum pre_token {
@@ -297,14 +308,18 @@ static const instruction inst[OPNUM] = {
[XOR] = {(AM_IMM|AM_ZM|AM_ABS|AM_BREG), 0x81}
};
-static const char *dir_t[7] = {
- [0] = "org",
- [1] = "byte",
- [2] = "word",
- [3] = "dword",
- [4] = "qword",
- [5] = "include",
- [6] = "res"
+static const char *dir_t[11] = {
+ [ 0] = "org",
+ [ 1] = "byte",
+ [ 2] = "word",
+ [ 3] = "dword",
+ [ 4] = "qword",
+ [ 5] = "include",
+ [ 6] = "res",
+ [ 7] = "struct",
+ [ 8] = "union",
+ [ 9] = "endstruct",
+ [10] = "endunion"
};
static const char *rs_t[4] = {
@@ -314,7 +329,7 @@ static const char *rs_t[4] = {
[3] = ".q"
};
-static const char *lex_tok[19] = {
+static const char *lex_tok[22] = {
[TOK_DIR ] = "TOK_DIR",
[TOK_LOCAL ] = "TOK_LOCAL",
[TOK_LABEL ] = "TOK_LABEL",
@@ -333,7 +348,10 @@ static const char *lex_tok[19] = {
[TOK_HEX ] = "TOK_HEX",
[TOK_DEC ] = "TOK_DEC",
[TOK_BIN ] = "TOK_BIN",
- [TOK_INCLUDE] = "TOK_INCLUDE"
+ [TOK_INCLUDE] = "TOK_INCLUDE",
+ [TOK_STRUCT ] = "TOK_STRUCT",
+ [TOK_UNION ] = "TOK_UNION",
+ [TOK_MEMBER ] = "TOK_MEMBER"
};
static const char *adrmode[11] = {
@@ -545,7 +563,7 @@ extern uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg);
extern uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg);
extern token *skip_expr(token *t, uint8_t dbg);
-extern uint64_t parse_tokens(token *tm, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg);
+extern uint64_t parse_tokens(token *tm, line **l, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg);
extern token *make_token(uint8_t id, uint8_t type, uint8_t space, uint8_t tab, uint64_t value, char *str, symbol *s);
extern void assemble(line *ln, bytecount *bc, uint8_t dbg);
extern void cleanup();
diff --git a/assemble.c b/assemble.c
index 0dad97c..2114456 100644
--- a/assemble.c
+++ b/assemble.c
@@ -74,7 +74,11 @@ uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) {
case TOK_BIN:
case TOK_CHAR: tmp_val = t->qword; t = t->next; break;
case TOK_SYM:
- case TOK_LABEL: tmp_val = (t->sym) ? t->sym->val : addr; t = t-> next; break;
+ case TOK_LABEL:
+ for (; t->sym && t->sym->isstruct && t->next && t->next->id == TOK_SYM; t = t->next);
+ tmp_val = (t->sym) ? t->sym->val : addr;
+ t = t->next;
+ break;
}
switch (type) {
case EXPR_PLUS : (isstart) ? (value = tmp_val) : (value += tmp_val); break;
@@ -139,6 +143,79 @@ uint8_t get_directivesize(uint8_t type, uint8_t dbg) {
return 0;
}
+uint16_t handle_struct(line **ln, uint64_t address, uint16_t offset, uint8_t dbg) {
+ uint8_t type = 0;
+ uint8_t done = 0;
+ uint8_t ismember = 0;
+ uint16_t size = 0;
+ uint16_t member_size = 0;
+ line *l = *ln;
+ symbol *strct = NULL;
+ token *tok = l->tok;
+
+ for (uint8_t found = 0; tok && !found; tok = tok->next) {
+ switch (tok->id) {
+ case TOK_DIR:
+ type = (tok->type == DIR_UNION);
+ found = (tok->type == DIR_STRUCT || tok->type == DIR_UNION);
+ break;
+ case TOK_STRUCT:
+ case TOK_UNION : type = (tok->id == TOK_UNION); found = 1; break;
+ }
+ }
+ if (tok != NULL) {
+ strct = tok->sym;
+ }
+
+ if (l && l->next) {
+ l = l->next;
+ }
+
+ for (; l && !done; l = l->next) {
+ token *t = l->tok;
+ token *start = t;
+ symbol *member;
+ for (; t && !done; t = t->next) {
+ switch (t->id) {
+ case TOK_MEMBER: ismember = 1; member = t->sym; break;
+ case TOK_DIR :
+ ismember = (t->type == DIR_STRUCT || t->type == DIR_UNION) ? 1 : ismember;
+ done = ((!type && t->type == DIR_ENDSTRUCT) || (type && t->type == DIR_ENDUNION));
+ if (!done && ismember) {
+ switch (t->type) {
+ case DIR_BYTE : member_size = 1; break;
+ case DIR_WORD : member_size = 2; break;
+ case DIR_DWORD : member_size = 4; break;
+ case DIR_QWORD : member_size = 8; break;
+ case DIR_UNION :
+ case DIR_STRUCT: member_size = handle_struct(&l, address, offset, dbg); break;
+ case DIR_RES : member_size = get_val(t, address, 3, dbg); t = skip_expr(t, dbg); break;
+ }
+ if (member && t->type != DIR_UNION && t->type != DIR_STRUCT) {
+ member->val = offset;
+ }
+ if (size < member_size) {
+ size = member_size;
+ }
+ if (!type) {
+ offset += size;
+ }
+ }
+ ismember = 0;
+ break;
+ }
+ }
+ if (done) {
+ break;
+ }
+ }
+ *ln = l;
+ if (strct != NULL) {
+ strct->val = offset;
+ }
+ return (!type) ? offset : size;
+}
+
uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
union reg val;
uint8_t c = 0;
@@ -464,11 +541,13 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
return address;
}
-uint64_t parse_tokens(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
+uint64_t parse_tokens(token *t, line **l, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
for (; t; t = t->next) {
switch (t->id) {
case TOK_DIR:
switch (t->type) {
+ case DIR_STRUCT:
+ case DIR_UNION : handle_struct(l, address, 0, dbg); break;
case DIR_RES: t = t->next; address += get_val(t, address, 3, dbg); break;
case DIR_ORG: t = t->next; address = get_val(t, address, 3, dbg); break;
case DIR_BYTE:
@@ -519,7 +598,7 @@ void assemble(line *ln, bytecount *bc, uint8_t dbg) {
for (; l; l = l->next) {
l->addr = address;
token *t = l->tok;
- address = parse_tokens(t, bc, 0, address, dbg);
+ address = parse_tokens(t, &l, bc, 0, address, dbg);
}
l = ln;
for (; l; l = l->next) {
@@ -536,67 +615,106 @@ void assemble(line *ln, bytecount *bc, uint8_t dbg) {
bc->progsize = 0;
bc->datasize = 0;
for (; l; l = l->next) {
- address = parse_tokens(l->tok, bc, 1, address, dbg);
+ address = parse_tokens(l->tok, &l, bc, 1, address, dbg);
}
}
static inline void free_tokens(token *t) {
token *tok;
- while (t != NULL) {
+ if (t != NULL) {
tok = t;
t = t->next;
free(tok);
+ free_tokens(t);
}
}
-void free_lines() {
- line *l = lines;
+void free_lines(line *l) {
line *ln;
- while (l != NULL) {
+ if (l != NULL) {
free_tokens(l->tok);
ln = l;
l = l->next;
free(ln);
+ free_lines(l);
+ }
+}
+
+void print_symtree(symbol *s) {
+ int depth = 0;
+ int lol = 0;
+ while (s) {
+ for (int i = depth; i; i--) {
+ putchar('|');
+ if (i > 1) {
+ printf(" ");
+ }
+ }
+ if (depth) {
+ printf("--");
+ }
+ if (s->name != NULL) {
+ if (!strcmp(s->name, "printc")) {
+ lol = 1;
+ }
+ printf("%s\n", s->name);
+ }
+ if (s->down != NULL) {
+ s = s->down;
+ depth++;
+ continue;
+ }
+ if (s->next == NULL) {
+ if (s->up != NULL) {
+ for (; !s->next && s->up; s = s->up, depth--);
+ }
+ }
+ s = s->next;
}
}
void free_symbols(symbol *s) {
symbol *sym;
- while (s != NULL) {
- if (s->local) {
- free_symbols(s->local);
+ sym = s;
+ if (sym != NULL) {
+ if (s->down) {
+ free_symbols(s->down);
}
- sym = s;
- s = s->next;
if (sym->name != NULL) {
free(sym->name);
+ sym->name = NULL;
}
+ s = s->next;
free(sym);
+ sym = NULL;
+ free_symbols(s);
}
}
-static inline void free_fixups() {
- fixup *f = fixups;
+static inline void free_fixups(fixup *f) {
fixup *fix;
- while (f != NULL) {
+ if (f != NULL) {
fix = f;
f = f->next;
free(fix);
+ fix = NULL;
+ free_fixups(f);
}
}
void cleanup() {
uint16_t i;
if (lines) {
- free_lines();
+ free_lines(lines);
lines = NULL;
}
if (symbols) {
+ /*print_symtree(symbols);*/
free_symbols(symbols);
symbols = NULL;
}
if (fixups) {
- free_fixups();
+ free_fixups(fixups);
fixups = NULL;
}
while (i < stridx || i < comidx) {
diff --git a/lexer.c b/lexer.c
index 2b7c8e7..1c9456e 100644
--- a/lexer.c
+++ b/lexer.c
@@ -9,6 +9,8 @@ symbol *locals = NULL;
symbol *last_loc = NULL;
symbol *cur_sym = NULL;
+line *tmp_line = NULL;
+
symbol *mksymbol(const char *name, uint64_t val, uint8_t def, uint8_t islocal, uint8_t useid, uint16_t id, uint8_t dbg) {
uint16_t i = 0;
symbol *s = (!islocal) ? symbols : locals;
@@ -41,22 +43,40 @@ symbol *mksymbol(const char *name, uint64_t val, uint8_t def, uint8_t islocal, u
}
size_t str_size = strlen(name)+1;
s = malloc(sizeof(symbol));
- s->local = NULL;
+ s->down = NULL;
if (!islocal) {
(last_sym) ? (last_sym->next = s) : (symbols = s);
+ if (last_sym) {
+ last_sym->next->prev = last_sym;
+ last_sym->next->up = last_sym->up;
+ last_sym->next->down = NULL;
+ } else {
+ symbols->prev = NULL;
+ symbols->up = NULL;
+ symbols->down = NULL;
+ }
} else {
(last_loc) ? (last_loc->next = s) : (locals = s);
+ if (last_loc) {
+ last_loc->next->prev = last_loc;
+ last_loc->next->up = last_loc->up;
+ last_loc->next->down = NULL;
+ } else {
+ locals->prev = NULL;
+ locals->down = NULL;
+ }
}
s->name = malloc(str_size);
s->def = def;
s->val = val;
s->count = 0;
+ s->isstruct = 0;
memcpy(s->name, name, str_size);
s->next = NULL;
s->id = sym_count++;
(!islocal) ? (last_sym = s) : (last_loc = s);
if (!islocal) {
- s->local = NULL;
+ s->down = NULL;
/*if (def) {
locals = NULL;
last_loc = NULL;
@@ -95,6 +115,26 @@ symbol *get_sym(const char *name, uint64_t val, token *t, uint8_t islocal, uint8
}
}
+symbol *find_member(char *name, symbol* root, uint8_t dbg) {
+ /*for (; root->up; root = root->up);*/
+ symbol *s = root;
+ if (s->down == NULL && s->up != NULL) {
+ s = s->up;
+ }
+ do {
+ s = s->down;
+ for (symbol *m = s; m; m = m->next) {
+ size_t len1 = strlen(name);
+ size_t len2 = strlen(m->name);
+ if (len1 == len2 && name[0] == m->name[0] && !strcmp(name, m->name)) {
+ return m;
+ }
+ }
+ for (; s->next && !s->down; s = s->next);
+ } while (s->down);
+ return NULL;
+}
+
uint16_t reslv_fixups(uint8_t dbg) {
fixup *f = fixups;
symbol *ls;
@@ -187,6 +227,8 @@ line *find_line(uint32_t ln, uint8_t dbg) {
return l;
}
+uint8_t is_struct = 0;
+
uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
char sym[0x100];
uint16_t i = 0;
@@ -227,6 +269,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
token *st = NULL;
token *t = NULL;
token *lt = NULL;
+ symbol *tmp_sym = NULL;
while (isdigit(str[i]) && isdelm(str[i], dbg) != 16) {
lnum[j++] = str[i++];
@@ -292,19 +335,48 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
switch (ptok) {
case PTOK_DOT:
i++;
- for (; isdelm(str[i+j], dbg) != 16; j++);
+ for (; !(isdelm(str[i+j], dbg) & 17); j++);
memcpy(lexeme, str+i, j);
lexeme[j] = '\0';
i += j;
if (!isop) {
- for (k = 0; k < 7; k++) {
+ for (k = 0; k < 11; k++) {
if (tolower(lexeme[0]) == dir_t[k][0] && !strcasecmp(lexeme, dir_t[k])) {
lex_type = TOK_DIR;
+ is_struct += (k == DIR_STRUCT || k == DIR_UNION);
+ is_struct -= (k == DIR_ENDSTRUCT || k == DIR_ENDUNION);
+ if ((k == DIR_ENDSTRUCT || k == DIR_ENDUNION)) {
+ if (is_struct) {
+ symbol *s = cur_sym;
+ for (; s->prev; s = s->prev) {
+ if (s->up == NULL) {
+ s->up = cur_sym->up;
+ }
+ printf("s: %p, last_loc: %p\n", s, last_loc);
+ }
+ for (s = locals; s; s = s->next) {
+ if (s->up == NULL) {
+ s->up = cur_sym;
+ }
+ }
+ if (cur_sym->down == NULL) {
+ cur_sym->down = locals;
+ }
+ cur_sym = cur_sym->up;
+ for (locals = cur_sym->down; locals->prev; locals = locals->prev);
+ for (last_loc = locals; last_loc->next; last_loc = last_loc->next);
+ }
+ }
break;
}
}
l->count++;
- t = make_token(lex_type, k, space, tab, 0, "", NULL);
+ if (lex_type != TOK_DIR && lt && lt->id == TOK_SYM) {
+ lex_type = TOK_MEMBER;
+ i -= j;
+ } else {
+ t = make_token(lex_type, k, space, tab, 0, "", NULL);
+ }
} else {
lex_type = TOK_RS;
switch (tolower(lexeme[j-1])) {
@@ -535,11 +607,11 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
}
if (!islocal) {
cur_sym = last_sym;
- cur_sym->local = NULL;
locals = NULL;
last_loc = NULL;
- } else if (cur_sym->local == NULL) {
- cur_sym->local = locals;
+ } else if (cur_sym->down == NULL && cur_sym == last_sym) {
+ cur_sym->down = locals;
+ cur_sym->down->up = cur_sym;
}
islocal = 0;
if (dbg) {
@@ -590,7 +662,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
i += j;
isch = 0;
isop = 0;
- if (j == 3 && str[i] != ':') {
+ if (j == 3 && str[i] != ':' && !is_struct) {
for (k = 0; k < OPNUM; k++) {
if (toupper(lexeme[0]) == mne[k][0]) {
if (!strcasecmp(lexeme, mne[k])) {
@@ -616,14 +688,56 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
if (dbg) {
printf("lex(): spaces: %u\n", spaces);
}
- if (str[i+spaces] != ':' && str[i+spaces] != '=') {
- t->sym = get_sym(lexeme, address, t, islocal, dbg);
- islocal = 0;
+ if (is_struct) {
+ islocal = !(is_struct == 1 && lt && lt->id == TOK_DIR);
+ mksymbol(sym, 0, 1, islocal, 0, 0, dbg);
+ if (isfixup) {
+ isfixup = reslv_fixups(dbg);
+ }
+ t->sym = get_sym(sym, 0, t, islocal, dbg);
+ if (lt && lt->id == TOK_DIR) {
+ t->sym->isstruct = 1;
+ t->id = (lt->type == DIR_STRUCT) ? TOK_STRUCT : TOK_UNION;
+ tmp_line = l;
+ } else {
+ t->id = TOK_MEMBER;
+ }
isfixup += (t->sym == NULL);
+ cur_sym = (!islocal && !cur_sym) ? last_sym : cur_sym;
+ if (!islocal) {
+ cur_sym->down = locals;
+ } else {
+ if (lt && lt->id == TOK_DIR) {
+ if (lt->type == DIR_UNION || lt->type == DIR_STRUCT) {
+ cur_sym->down = locals;
+ cur_sym->down->up = cur_sym;
+ last_loc->up = cur_sym;
+ cur_sym = last_loc;
+ locals = NULL;
+ last_loc = NULL;
+ }
+ }
+ }
+ islocal = 0;
+ } else if ((str[i+spaces] != ':' && str[i+spaces] != '=')) {
+ uint8_t sym_struct = 0;
+ symbol *s;
+ /*tmp_sym = (s && s->isstruct) ? NULL : tmp_sym;*/
+ if (tmp_sym) {
+ t->sym = find_member(lexeme, tmp_sym, dbg);
+ tmp_sym = NULL;
+ } else {
+ t->sym = get_sym(lexeme, address, t, islocal, dbg);
+ }
+ isfixup += (t && t->sym == NULL);
+ islocal = 0;
if (dbg) {
printf("lex(): isfixup: %u\n", isfixup);
}
}
+ if (!is_struct && t && t->sym && t->sym->isstruct) {
+ tmp_sym = t->sym;
+ }
}
break;
}
@@ -636,7 +750,7 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
j = 0;
if (lex_type == TOK_OPCODE && !isop) {
j = 0;
- } else if (lex_type == TOK_EXPR || !isdelm2(str[i], dbg)) {
+ } else if (lex_type == TOK_EXPR || (lex_type != TOK_MEMBER && !isdelm2(str[i], dbg))) {
i++;
}
switch (lex_type) {
@@ -675,7 +789,13 @@ uint64_t lex(char *str, uint64_t address, uint16_t bline, uint8_t dbg) {
tokens = NULL;
last_tok = NULL;
bytecount dummy;
- address = parse_tokens(l->tok, &dummy, 0, address, dbg);
+ if (!is_struct) {
+ l = (tmp_line) ? tmp_line : l;
+ address = parse_tokens(l->tok, &l, &dummy, 0, address, dbg);
+ if (tmp_line) {
+ tmp_line = NULL;
+ }
+ }
if (dbg) {
printf("lex(): Next address: $%"PRIX64"\n", address);
}
diff --git a/sux.c b/sux.c
index c53e7b8..1131210 100644
--- a/sux.c
+++ b/sux.c
@@ -14,6 +14,7 @@ uint64_t inst[THREADS];
#if bench
uint64_t inss;
+uint8_t time_done = 0;
#endif
#if debug
@@ -43,7 +44,6 @@ struct suxthr {
#if bench
double ipc;
-struct timeval str[THREADS], en[THREADS];
#endif
inline uint8_t get_addrsize(uint8_t prefix, uint8_t addrmode) {
@@ -138,6 +138,28 @@ static inline uint8_t isread(uint8_t opcode) {
}
}
+void stop_timer() {
+ time_done = 1;
+}
+
+void start_timer(int sec, int usec) {
+ struct itimerval it_val;
+ for (; usec > 1000000; sec++, usec -= 1000000);
+ it_val.it_value.tv_sec = sec;
+ it_val.it_value.tv_usec = usec;
+ it_val.it_interval.tv_sec = 0;
+ it_val.it_interval.tv_usec = 0;
+
+ if (signal(SIGALRM, stop_timer) == SIG_ERR) {
+ perror("Unable to catch SIGALRM.");
+ exit(1);
+ }
+ if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) {
+ perror("Error calling setitimer().");
+ exit(1);
+ }
+}
+
void *run(void *args) {
struct suxthr *thr = (void *)args;
struct sux *cpu = &thr->sx;
@@ -147,6 +169,7 @@ void *run(void *args) {
union reg address;
union reg value;
cpu->clk = 0;
+ uint64_t *rem = NULL;
#if !IO
uint64_t ins = 0;
#endif
@@ -167,9 +190,9 @@ void *run(void *args) {
#endif
#endif
uint64_t tmpaddr = 0;
-#if bench
- gettimeofday(&str[thread], 0);
-#endif
+ #if bench
+ start_timer(1, 0);
+ #endif
for (;;) {
#if !bench
if (end) {
@@ -221,6 +244,7 @@ void *run(void *args) {
uint8_t rs = (prefix >> 4) & 3;
uint8_t size = (/***/1 << rs) - 1;
uint8_t check_io = (am != IMM);
+ uint64_t sp = (cpu->sp & 0xFFFF) | (cpu->stk_st << 16);
#if debug && !bench
#if keypoll
pthread_mutex_lock(&mutex);
@@ -250,25 +274,23 @@ void *run(void *args) {
case ADC_IMM: /* ADC Immediate. */
case ADC_AB: /* ADC Absolute. */
case ADC_Z: /* ADC Zero Matrix. */
- adc(cpu, value.u64, thread);
+ cpu->a = adc(cpu, cpu->a, value.u64, thread);
break;
case PHP_IMP: push(cpu, cpu->ps.u8[thread], 0, thread); break; /* PusH Processor status to stack. */
case PHA_IMP: push(cpu, cpu->a , size, thread); break; /* PusH Accumulator to stack. */
case PHB_IMP: push(cpu, cpu->b , size, thread); break; /* PusH B register to stack. */
case PHY_IMP: push(cpu, cpu->y , size, thread); break; /* PusH Y register to stack. */
case PHX_IMP: push(cpu, cpu->x , size, thread); break; /* PusH X register to stack. */
- case TAY_IMP: /* Transfer Accumulator to Y. */
- case TAX_IMP: /* Transfer Accumulator to Y. */
- case TYX_IMP: /* Transfer Y to X. */
- case TYA_IMP: /* Transfer Y to Accumulator. */
- case TXA_IMP: /* Transfer X to Accumulator. */
- case TXY_IMP: /* Transfer X to Y. */
- case TAB_IMP: /* Transfer Accumulator to B. */
- case TSX_IMP: /* Transfer Stack pointer to X. */
- case TBA_IMP: /* Transfer B to Accumulator. */
- case TXS_IMM: /* Transfer X to Stack pointer. */
- transfer(cpu, value.u64, opcode, prefix, thread);
- break;
+ case TAY_IMP: cpu->y = transfer(cpu, cpu->a, value.u64, opcode, prefix, thread); break; /* Transfer Accumulator to Y. */
+ case TAX_IMP: cpu->x = transfer(cpu, cpu->a, value.u64, opcode, prefix, thread); break; /* Transfer Accumulator to Y. */
+ case TYX_IMP: cpu->x = transfer(cpu, cpu->y, value.u64, opcode, prefix, thread); break; /* Transfer Y to X. */
+ case TYA_IMP: cpu->a = transfer(cpu, cpu->y, value.u64, opcode, prefix, thread); break; /* Transfer Y to Accumulator. */
+ case TXA_IMP: cpu->a = transfer(cpu, cpu->x, value.u64, opcode, prefix, thread); break; /* Transfer X to Accumulator. */
+ case TXY_IMP: cpu->y = transfer(cpu, cpu->x, value.u64, opcode, prefix, thread); break; /* Transfer X to Y. */
+ case TAB_IMP: cpu->b = transfer(cpu, cpu->a, value.u64, opcode, prefix, thread); break; /* Transfer Accumulator to B. */
+ case TSX_IMP: cpu->x = transfer(cpu, sp, value.u64, opcode, prefix, thread); break; /* Transfer Stack pointer to X. */
+ case TBA_IMP: cpu->a = transfer(cpu, cpu->b, value.u64, opcode, prefix, thread); break; /* Transfer B to Accumulator. */
+ case TXS_IMM: cpu->sp = transfer(cpu, cpu->x, value.u64, opcode, prefix, thread); break; /* Transfer X to Stack pointer. */
case BRA_REL: /* BRA Relative. */
case JMP_AB: /* JMP Absolute. */
case JMP_Z: /* JMP Zero Matrix. */
@@ -280,7 +302,7 @@ void *run(void *args) {
case SBC_IMM: /* SBC Immediate. */
case SBC_AB: /* SBC Absolute. */
case SBC_Z: /* SBC Zero Matrix. */
- sbc(cpu, value.u64, thread);
+ cpu->a = sbc(cpu, cpu->a, value.u64, thread);
break;
case PLP_IMP: cpu->ps.u8[thread] = pull(cpu, 0, thread); break; /* PuLl Processor status from stack. */
case PLA_IMP: cpu->a = pull(cpu, size, thread); break; /* PuLl Accumulator from stack. */
@@ -293,7 +315,7 @@ void *run(void *args) {
case AND_IMM: /* AND Immediate. */
case AND_AB: /* AND Absolute. */
case AND_Z: /* AND Zero Matrix. */
- and(cpu, value.u64, thread);
+ cpu->a = and(cpu, cpu->a, value.u64, thread);
break;
case BPO_REL: /* BPO Relative. */
if (!getflag(N)) {
@@ -305,7 +327,7 @@ void *run(void *args) {
case ORA_IMM: /* ORA Immediate. */
case ORA_AB: /* ORA Absolute. */
case ORA_Z: /* ORA Zero Matrix. */
- or(cpu, value.u64, thread);
+ cpu->a = or(cpu, cpu->a, value.u64, thread);
break;
case SEI_IMP: /* SEt Interrupt. */
setflag(1, I);
@@ -320,7 +342,7 @@ void *run(void *args) {
case XOR_IMM: /* XOR Immediate. */
case XOR_AB: /* XOR Absolute. */
case XOR_Z: /* XOR Zero Matrix. */
- xor(cpu, value.u64, thread);
+ cpu->a = xor(cpu, cpu->a, value.u64, thread);
break;
case CLI_IMP: /* CLear Interrupt. */
setflag(0, I);
@@ -335,7 +357,7 @@ void *run(void *args) {
case LSL_IMM: /* LSL Immediate. */
case LSL_AB: /* LSL Absolute. */
case LSL_Z: /* LSL Zero Matrix. */
- lsl(cpu, value.u64, thread);
+ cpu->a = lsl(cpu, cpu->a, value.u64, thread);
break;
case SEC_IMP: /* SEt Carry flag.*/
setflag(1, C);
@@ -378,14 +400,14 @@ void *run(void *args) {
case LSR_IMM: /* LSR Immediate. */
case LSR_AB: /* LSR Absolute. */
case LSR_Z: /* LSR Zero Matrix. */
- lsr(cpu, value.u64, thread);
+ cpu->a = lsr(cpu, cpu->a, value.u64, thread);
break;
case ASR_B: /* ASR B register. */
value.u64 = cpu->b; /* Falls Through. */
case ASR_IMM: /* ASR Immediate. */
case ASR_AB: /* ASR Absolute. */
case ASR_Z: /* ASR Zero Matrix. */
- asr(cpu, value.u64, thread);
+ cpu->a = asr(cpu, cpu->a, value.u64, thread);
break;
case CLC_IMP: /* CLear Carry flag. */
setflag(0, C);
@@ -432,7 +454,7 @@ void *run(void *args) {
case ROL_IMM: /* ROL Immediate. */
case ROL_AB: /* ROL Absolute. */
case ROL_Z: /* ROL Zero Matrix. */
- rol(cpu, value.u64, thread);
+ cpu->a = rol(cpu, cpu->a, value.u64, thread);
break;
case BNE_REL: /* BNE Relative. */
if (!getflag(Z)) {
@@ -444,7 +466,7 @@ void *run(void *args) {
case ROR_IMM: /* ROR Immediate. */
case ROR_AB: /* ROR Absolute. */
case ROR_Z: /* ROR Zero Matrix. */
- ror(cpu, value.u64, thread);
+ cpu->a = ror(cpu, cpu->a, value.u64, thread);
break;
case BVS_REL: /* BVS Relative. */
if (getflag(V)) {
@@ -456,18 +478,19 @@ void *run(void *args) {
case MUL_IMM: /* MUL Immediate. */
case MUL_AB: /* MUL Absolute. */
case MUL_Z: /* MUL Zero Matrix. */
- mul(cpu, value.u64, thread);
+ cpu->a = mul(cpu, cpu->a, value.u64, thread);
break;
case BVC_REL: /* BVC Relative. */
if (!getflag(V)) {
cpu->pc = address.u64;
}
break;
- case DIV_IMM: /* DIV Immediate. */
case DIV_B: /* DIV B register. */
+ case DIV_IMM: /* DIV Immediate. */
case DIV_AB: /* DIV Absolute. */
case DIV_Z: /* DIV Zero Matrix. */
- divd(cpu, value.u64, opcode, thread);
+ rem = (opcode != DIV_B) ? &cpu->b : &cpu->x;
+ cpu->a = divd(cpu, cpu->a, value.u64, rem, thread);
break;
case CLV_IMP: /* CLear oVerflow flag. */
setflag(0, V);
@@ -583,7 +606,7 @@ void *run(void *args) {
pthread_mutex_unlock(&mutex);
#endif
#elif bench
- if (ins >= BENCH_INST) {
+ if (time_done) {
pthread_mutex_lock(&main_mutex);
threads_done++;
inst[thread] = ins;
@@ -592,7 +615,6 @@ void *run(void *args) {
#endif
pthread_cond_signal(&main_cond);
pthread_mutex_unlock(&main_mutex);
- gettimeofday(&en[thread], 0);
break;
}
#endif
@@ -617,15 +639,13 @@ void init_scr() {
attron(COLOR_PAIR(1) | A_BOLD);
}
-
-
-
int main(int argc, char **argv) {
struct suxthr thr[THREADS];
char *tmp = malloc(2048);
addr = malloc(mem_size);
#if bench
inss = 0;
+ struct timeval str, en;
#endif
int v = 0;
@@ -678,6 +698,13 @@ int main(int argc, char **argv) {
assert(!result);
}
werase(scr);
+ #if bench
+ endwin();
+ gettimeofday(&str, 0);
+ double t = 0;
+ double dt = 0;
+ double t2 = 0;
+ #endif
while (threads_done < THREADS && !end) {
#if !bench
pthread_mutex_lock(&main_mutex);
@@ -695,52 +722,53 @@ int main(int argc, char **argv) {
pthread_mutex_unlock(&main_mutex);
#endif
}
+ #if !bench
endwin();
+ #endif
#if bench
+ gettimeofday(&en, 0);
if (threads_done == THREADS) {
- double tm_sec, tm_usec, tm[THREADS], ttm;
+ double tm_sec, tm_usec, tm;
#if getclk
double clkspd;
double mhz;
#endif
double ips[THREADS];
double ipst;
+ tm_sec = (en.tv_sec - str.tv_sec);
+ tm_usec = (en.tv_usec-str.tv_usec);
+ tm = (tm_sec*1000000)+(tm_usec);
for (int i = 0; i < THREADS; i++) {
- tm_sec = (en[i].tv_sec - str[i].tv_sec);
- tm_usec = (en[i].tv_usec-str[i].tv_usec);
- tm[i] = (tm_sec*1000000)+(tm_usec);
- ips[i] = inst[i]/tm[i];
+ ips[i] = inst[i]/tm;
if (i) {
inss += inst[i];
- ttm += tm[i];
ipst += ips[i];
#if getclk
tclk += clk[i];
#endif
} else {
inss = inst[i];
- ttm = tm[i];
ipst = ips[i];
#if getclk
tclk = clk[i];
#endif
}
#if getclk
- clkspd = (tm[i]/1000000)*1000000/clk[i];
+ clkspd = (tm/1000000)*1000000/clk[i];
mhz = 1000000.0/clkspd/1000000;
#endif
- sprintf(tmp, "Instructions executed for thread %i: %"PRIu64", Instructions per Second for thread %i in MIPS: %f, tm: %f\n", i, inst[i], i, ips[i], tm[i]/1000000);
+ sprintf(tmp, "Instructions executed for thread %i: %"PRIu64", Instructions per Second for thread %i in MIPS: %f\n", i, inst[i], i, ips[i]);
fwrite(tmp, sizeof(char), strlen(tmp), stdout);
}
sprintf(tmp, "Total Instructions executed: %"PRIu64", Total Instructions per Second in MIPS: %f", inss, ipst);
fwrite(tmp, sizeof(char), strlen(tmp), stdout);
#if getclk
- clkspd = (ttm/1000000)*1000000/tclk;
+ clkspd = (tm/1000000)*1000000/tclk;
mhz = 1000000.0/clkspd/1000000;
sprintf(tmp, ", Clock cycles: %"PRIu64", Clock Speed in MHz: %f", tclk, mhz);
fwrite(tmp, sizeof(char), strlen(tmp), stdout);
#endif
- sprintf(tmp, ", tm: %f\n", ttm/1000000);
+ sprintf(tmp, ", tm: %f\n", tm/1000000);
fwrite(tmp, sizeof(char), strlen(tmp), stdout);
fflush(stdout);
free(tmp);
diff --git a/sux.h b/sux.h
index 5abb29c..2432322 100644
--- a/sux.h
+++ b/sux.h
@@ -6,6 +6,8 @@
#if bench
#include <sys/time.h>
+#include <signal.h>
+#include <math.h>
#endif
#include <curses.h>
@@ -17,6 +19,8 @@
#define STEP_ADDR 0x110
#define CURSES_BACKSPACE 0x7F
+#define copy64 1
+
extern uint8_t kbd_rdy;
extern WINDOW *scr;
@@ -50,9 +54,21 @@ extern void io(uint64_t address, uint8_t rw);
extern void init_scr();
-static inline void *memcopy(void *dst, void *src, size_t n) {
+static void *memcopy(void *dst, void *src, unsigned int n) {
+ #if copy64
+ uint64_t *d = dst, *s = src;
+ unsigned int r = n % 8;
+ n /= 8;
+ #else
uint8_t *d = dst, *s = src;
+ #endif
for (; n; *d++ = *s++, n--);
+ #if copy64
+ if (r) {
+ uint64_t mask = (-(uint64_t)1 >> ((8 - r) * 8));
+ *d = (*d & ~mask) | (*s & mask);
+ }
+ #endif
return dst;
}
@@ -242,45 +258,37 @@ static inline uint64_t get_addr(struct sux *cpu, uint8_t opcode, uint8_t prefix,
return address;
}
-static inline void adc(struct sux *cpu, uint64_t value, uint8_t thread) {
- uint64_t sum = cpu->a+value+getflag(C);
+
+static inline uint64_t adc(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+ uint64_t sum = reg+value+getflag(C);
setflag(sum == 0, Z);
setflag((sum >> 63), N);
- setflag(((cpu->a^value) >> 63) && ((cpu->a^sum) >> 63), V);
+ setflag(((reg^value) >> 63) && ((reg^sum) >> 63), V);
setflag((sum < value), C);
- cpu->a = sum;
+ return sum;
}
-static inline void sbc(struct sux *cpu, uint64_t value, uint8_t thread) {
- uint64_t sum = cpu->a-value-!getflag(C);
+static inline uint64_t sbc(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+ uint64_t sum = reg-value-!getflag(C);
setflag(sum == 0, Z);
setflag(sum >> 63, N);
- setflag(((cpu->a^value) >> 63) && ((cpu->a^sum) >> 63), V);
+ setflag(((reg^value) >> 63) && ((reg^sum) >> 63), V);
setflag((sum > value), C);
- cpu->a = sum;
+ return sum;
}
-static inline void transfer(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t prefix, uint8_t thread) {
- uint64_t reg;
+static inline uint64_t transfer(struct sux *cpu, uint64_t src, uint64_t value, uint8_t opcode, uint8_t prefix, uint8_t thread) {
switch (opcode) {
- case TBA_IMP: cpu->a = cpu->b; reg = cpu->a; break;
- case TXA_IMP: cpu->a = cpu->x; reg = cpu->a; break;
- case TYA_IMP: cpu->a = cpu->y; reg = cpu->a; break;
- case TAB_IMP: cpu->b = cpu->a; reg = cpu->b; break;
- case TAY_IMP: cpu->y = cpu->a; reg = cpu->y; break;
- case TXY_IMP: cpu->y = cpu->x; reg = cpu->y; break;
- case TAX_IMP: cpu->x = cpu->a; reg = cpu->x; break;
- case TYX_IMP: cpu->x = cpu->y; reg = cpu->x; break;
- case TSX_IMP: cpu->x = cpu->sp & 0xFFFF; cpu->x = cpu->stk_st << 16; break;
- case TXS_IMM: cpu->sp = cpu->x;
+ case TXS_IMM:
if (prefix == 0x13 && (value == thread+1 || value > 8)) {
cpu->stk_st = value & 0xFF;
cpu->stk_st += value << 16;
cpu->pc+=2;
}
- break;
+ default: break;
}
- setflag(reg == 0, Z);
- setflag(reg >> 63, N);
+ setflag(src == 0, Z);
+ setflag(src >> 63, N);
+ return src;
}
static inline void push(struct sux *cpu, uint64_t value, uint8_t size, uint8_t thread) {
@@ -296,83 +304,82 @@ static inline uint64_t pull(struct sux *cpu, uint8_t size, uint8_t thread) {
return value;
}
-static inline void and(struct sux *cpu, uint64_t value, uint8_t thread) {
- cpu->a &= value;
- setflag(cpu->a == 0, Z);
- setflag(cpu->a >> 63, N);
+static inline uint64_t and(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+ reg &= value;
+ setflag(reg == 0, Z);
+ setflag(reg >> 63, N);
+ return reg;
}
-static inline void or(struct sux *cpu, uint64_t value, uint8_t thread) {
- cpu->a |= value;
- setflag(cpu->a == 0, Z);
- setflag(cpu->a >> 63, N);
+static inline uint64_t or(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+ reg |= value;
+ setflag(reg == 0, Z);
+ setflag(reg >> 63, N);
+ return reg;
}
-static inline void xor(struct sux *cpu, uint64_t value, uint8_t thread) {
- cpu->a ^= value;
- setflag(cpu->a == 0, Z);
- setflag(cpu->a >> 63, N);
+static inline uint64_t xor(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+ reg ^= value;
+ setflag(reg == 0, Z);
+ setflag(reg >> 63, N);
+ return reg;
}
-static inline void lsl(struct sux *cpu, uint64_t value, uint8_t thread) {
- uint64_t sum = (value < 64) ? cpu->a << value : 0;
+static inline uint64_t lsl(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+ uint64_t sum = (value < 64) ? reg << value : 0;
setflag(sum == 0, Z);
setflag(sum >> 63, N);
- setflag(cpu->a >> (64-value), C);
- cpu->a = sum;
+ setflag(reg >> (64-value), C);
+ return sum;
}
-static inline void lsr(struct sux *cpu, uint64_t value, uint8_t thread) {
- uint64_t sum = (value < 64) ? cpu->a >> value : 0;
+static inline uint64_t lsr(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+ uint64_t sum = (value < 64) ? reg >> value : 0;
setflag(sum == 0, Z);
setflag(sum >> 63, N);
- setflag(cpu->a & 1, C);
- cpu->a = sum;
+ setflag(reg & 1, C);
+ return sum;
}
-static inline void asr(struct sux *cpu, uint64_t value, uint8_t thread) {
- uint8_t sign = cpu->a >> 63;
- uint64_t sum = (value < 64) ? (cpu->a >> value) | ((uint64_t)sign << 63) : 0;
+static inline uint64_t asr(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+ uint8_t sign = reg >> 63;
+ uint64_t sum = (value < 64) ? (reg >> value) | ((uint64_t)sign << 63) : 0;
setflag(sum == 0, Z);
setflag(sum >> 63, N);
- setflag(cpu->a & 1, C);
- cpu->a = sum;
+ setflag(reg & 1, C);
+ return sum;
}
-static inline void rol(struct sux *cpu, uint64_t value, uint8_t thread) {
- uint64_t sum = cpu->a << value;
+static inline uint64_t rol(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+ uint64_t sum = reg << value;
sum |= getflag(C);
setflag(sum == 0, Z);
setflag(sum >> 63, N);
- setflag(cpu->a >> (uint64_t)(64-value), C);
- cpu->a = sum;
+ setflag(reg >> (uint64_t)(64-value), C);
+ return sum;
}
-static inline void ror(struct sux *cpu, uint64_t value, uint8_t thread) {
- uint64_t sum = cpu->a >> value;
+static inline uint64_t ror(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+ uint64_t sum = reg >> value;
sum |= (uint64_t)getflag(C) << (uint64_t)(64-value);
setflag(sum == 0, Z);
setflag(sum >> 63, N);
- setflag(cpu->a & 1, C);
- cpu->a = sum;
+ setflag(reg & 1, C);
+ return sum;
}
-static inline void mul(struct sux *cpu, uint64_t value, uint8_t thread) {
- uint64_t sum = cpu->a*value;
- cpu->a = sum;
+
+static inline uint64_t mul(struct sux *cpu, uint64_t reg, uint64_t value, uint8_t thread) {
+ uint64_t sum = reg*value;
setflag(sum == 0, Z);
setflag(sum >> 63, N);
- setflag(!((cpu->a^value) >> 63) && ((cpu->a^sum) >> 63), V);
+ setflag(!((reg^value) >> 63) && ((reg^sum) >> 63), V);
+ return sum;
}
-static inline void divd(struct sux *cpu, uint64_t value, uint8_t opcode, uint8_t thread) {
- uint64_t sum = cpu->a/value;
- if (opcode != DIV_B) {
- cpu->b = cpu->a % value;
- } else {
- value = cpu->b;
- cpu->x = cpu->a % value;
- }
- cpu->a = sum;
+static inline uint64_t divd(struct sux *cpu, uint64_t reg, uint64_t value, uint64_t *rem, uint8_t thread) {
+ uint64_t sum = reg/value;
+ *rem = reg % value;
setflag(sum == 0, Z);
setflag((sum >> 63), N);
+ return sum;
}
static inline void cmp(struct sux *cpu, uint64_t value, uint64_t reg, uint8_t thread) {
uint64_t sum = reg-value;
@@ -384,11 +391,7 @@ static inline void cmp(struct sux *cpu, uint64_t value, uint64_t reg, uint8_t th
/* Increment, or Decrement register. */
static inline uint64_t idr(struct sux *cpu, uint64_t reg, uint8_t inc, uint8_t thread) {
- if (inc) {
- reg++;
- } else {
- reg--;
- }
+ reg += (inc) ? 1 : -1;
setflag(reg == 0, Z);
setflag(reg >> 63, N);
return reg;
@@ -399,11 +402,7 @@ static inline void idm(struct sux *cpu, uint64_t address, uint8_t prefix, uint8_
uint8_t size = (1 << ((prefix >> 4) & 3))-1;
uint64_t value;
value = read_value(cpu, 0, address, size, 1, 0);
- if (inc) {
- value++;
- } else {
- value--;
- }
+ value += (inc) ? 1 : -1;
uint8_t sign = 0;
switch ((prefix >> 4) & 3) {
default: sign = 7; break;
diff --git a/test/popcnt2.s b/test/popcnt2.s
index 3aa38f0..503b074 100644
--- a/test/popcnt2.s
+++ b/test/popcnt2.s
@@ -14,7 +14,7 @@ popcnt:
bra @loop ; Keep looping.
@end:
tya ; Return the bit count.
- rts.w ; End of popcnt.
+ rts ; End of popcnt.
reset:
@@ -27,7 +27,7 @@ reset:
tay ; Reset Y.
main:
pha.q ; Save A.
- jsr.w popcnt ; Get population count.
+ jsr popcnt ; Get population count.
tay ; Save it in Y.
pla.q ; Get A back.
inc ; Increment A by one.
diff --git a/test/struct.s b/test/struct.s
new file mode 100644
index 0000000..dce527d
--- /dev/null
+++ b/test/struct.s
@@ -0,0 +1,31 @@
+.struct lol
+ oof .byte
+ cia .word
+ glo .dword
+ nig .qword
+ .union asd
+ f .qword
+ ss .byte
+ .struct aa
+ lol .qword
+ why .word
+ .endstruct
+ .endunion
+ why .word
+.endstruct
+
+
+.org 0
+
+lda #1
+ldb #lol.asd.f
+ldx #lol.asd.ss
+ldy #lol.glo
+lda #lol.oof
+ldb #lol.asd.aa.lol
+ldx #lol.asd.aa.why
+ldy #lol.why
+a
+l a
+v
+q