From eea04e3327972f052dcfb8ae0854b77f87d3d52f Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Fri, 18 Sep 2020 14:49:07 -0400 Subject: - 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. --- asmmon.c | 6 +++ asmmon.h | 46 ++++++++++++----- assemble.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++------- lexer.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++----- sux.c | 118 ++++++++++++++++++++++++++---------------- sux.h | 159 ++++++++++++++++++++++++++++----------------------------- test/popcnt2.s | 4 +- test/struct.s | 31 +++++++++++ 8 files changed, 493 insertions(+), 173 deletions(-) create mode 100644 test/struct.s 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 +#include +#include #endif #include @@ -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 -- cgit v1.2.3-13-gbd6f