diff options
Diffstat (limited to 'asmmon.c')
-rw-r--r-- | asmmon.c | 554 |
1 files changed, 107 insertions, 447 deletions
@@ -13,7 +13,8 @@ char lexeme[MAX_TOK]; char *string[MAX_TOK]; char *comment[MAX_TOK]; uint16_t incl[MAX_TOK]; -struct line tokline[MAX_TOK]; +line *lines; +line *last_line; struct line tln[MAX_TOK]; struct symbol *symbols[MAX_TOK]; struct fixup *fixups[MAX_TOK]; @@ -109,8 +110,9 @@ char *showbits(uint64_t value, uint8_t bitnum, uint8_t dbg) { } -void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, uint8_t dbg) { - uint16_t i = start; +void list(uint16_t start, uint16_t end, uint8_t all, uint8_t ln, uint8_t addr, uint8_t dbg) { + line *s = find_line(start, dbg); + line *e = find_line(end, dbg); uint8_t j = 0; uint8_t flags = 0; uint8_t isstr; @@ -125,31 +127,24 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln, char ch[6]; if (all) { - end = lineidx; + s = lines; + e = last_line; } - for (; i < end; i++) { - flags = 0; - flags |= (l[i].dir != 0x00FF) << 0; - flags |= (l[i].mne != 0x00FF) << 1; - flags |= (l[i].rs != 0x00FF) << 2; - flags |= (l[i].am != 0x00FF) << 3; - flags |= (l[i].opbase != 0x00FF) << 4; - flags |= (l[i].sym != 0xFFFF) << 5; - flags |= (l[i].rs != 0x00FF) << 6; - flags |= (l[i].am != 0x00FF) << 7; - iscm = l[i].cm != 0xFF; - isstr = l[i].str != 0xFFFF; - iscom = l[i].com != 0xFFFF; + + do { + token *t = s->tok; + uint8_t am = 0xFF; + uint8_t rs = 0xFF; if (dbg) { printf("list(): "); } if (ln) { - printf("%u\t", l[i].linenum); + printf("%u\t", s->linenum); } else if (addr) { - printf("$%"PRIX64":\t", l[i].addr); + printf("$%"PRIX64":\t", s->addr); } - spaces = l[i].sspace; - tabs = l[i].stab; + spaces = s->sspace; + tabs = s->stab; while (spaces || tabs) { if (spaces) { putchar(' '); @@ -160,136 +155,89 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln, tabs--; } } - if (flags & 0x01) { - printf(".%s ", dir_t[l[i].dir]); - if (isstr) { - printf("\"%s\"", string[l[i].str]); - } - } - if (flags & 0x02) { - for (; j < 3; j++) { - mne_lower[j] = tolower(mne[l[i].mne][j]); - } - mne_lower[j] = '\0'; - j = 0; - printf("%s", mne_lower); - } - if (flags & 0x04) { - printf("%s ", rs_t[l[i].rs]); - } else if (flags & 0x02) { - printf(" "); - } - if (flags & 0x7F) { - switch (l[i].am) { - case IMM: - putchar('#'); + for (; t && t->id != TOK_COMMENT; t = t->next) { + switch (t->id) { + case TOK_DIR : printf(".%s ", dir_t[t->type]); break; + case TOK_STRING: printf("\"%s\"", t->str) ; break; + case TOK_OPCODE: + for (; j < 3; j++) { + mne_lower[j] = tolower(mne[t->byte][j]); + } + mne_lower[j] = '\0'; + j = 0; + printf("%s", mne_lower); + am = t->type; + t = t->next; + if (t->id == TOK_RS) { + rs = t->type; + printf("%s", rs_t[t->type]); + } + switch (am) { + case IMM : putchar('#'); break; + case IND : + case INDX: + case INDY: putchar('('); break; + } break; - case INDX: - case INDY: - case IND: - putchar('('); + case TOK_SYM: + case TOK_LABEL: + printf("%s", symbols[t->word]->name); + if (t->id == TOK_LABEL) { + putchar(':'); + } else if (t == s->tok && t->id == TOK_SYM) { + printf(" = "); + } break; - } - } - if (flags & 0x20) { - printf("%s", symbols[l[i].sym]->name); - if (l[i].islabel) { - printf(": "); - } else if (l[i].issym) { - printf(" = "); - } - } - if (flags & 0x10) { - if (flags & 0x04) { - bitnum = (l[i].rs << 3); - } else { - opsize += (l[i].op <= 0x000000FF) + 0; - opsize += (l[i].op > 0x000000FF) + 1; - opsize += (l[i].op > 0x0000FFFF) + 2; - opsize += (l[i].op > 0xFFFFFFFF) + 3; - if (opsize) { - bitnum = bitsize[opsize-1]; - } - } - - j = 0; - - if (l[i].opbase == BASE_CHAR) { - switch (l[i].op) { - default : ch[j++] = l[i].op; break; - case '\n': ch[j++] = '\\'; ch[j++] = 'n' ; break; - case '\r': ch[j++] = '\\'; ch[j++] = 'r' ; break; - case '\b': ch[j++] = '\\'; ch[j++] = 'b' ; break; - case '\\': ch[j++] = '\\'; ch[j++] = '\\'; break; - case '\'': ch[j++] = '\\'; ch[j++] = '\''; break; - case '\"': ch[j++] = '\\'; ch[j++] = '\"'; break; - } - } - - ch[j] = '\0'; - j = 0; - - switch (l[i].opbase) { - case BASE_HEX: printf("$%"PRIX64, l[i].op); break; - case BASE_DEC: printf("%"PRIu64, l[i].op); break; - case BASE_BIN: printf("%%%s", showbits(l[i].op, bitnum, dbg)); break; - case BASE_CHAR: printf("\'%s\'", ch); break; - } - bitnum = 0; - opsize = 0; - } - if (iscm) { - switch (l[i].cm) { - case 0: - putchar('+'); + case TOK_HEX: printf("$%"PRIX64, t->qword); break; + case TOK_DEC: printf( "%"PRIu64, t->qword); break; + case TOK_BIN: + if (rs != 0xFF) { + bitnum = (rs << 3); + } else { + opsize += (t->qword <= 0x000000FF) + 0; + opsize += (t->qword > 0x000000FF) + 1; + opsize += (t->qword > 0x0000FFFF) + 2; + opsize += (t->qword > 0xFFFFFFFF) + 3; + if (opsize) { + bitnum = bitsize[opsize-1]; + } + } + printf("%%%s", showbits(t->qword, bitnum, dbg)); + bitnum = 0; + opsize = 0; break; - case 1: - putchar ('-'); + case TOK_CHAR: + j = 0; + switch (t->byte) { + default : ch[j++] = t->byte; break; + case '\n': ch[j++] = '\\'; ch[j++] = 'n' ; break; + case '\r': ch[j++] = '\\'; ch[j++] = 'r' ; break; + case '\b': ch[j++] = '\\'; ch[j++] = 'b' ; break; + case '\\': ch[j++] = '\\'; ch[j++] = '\\'; break; + case '\'': ch[j++] = '\\'; ch[j++] = '\''; break; + case '\"': ch[j++] = '\\'; ch[j++] = '\"'; break; + } + ch[j] = '\0'; + j = 0; + printf("\'%s\'", ch); + break; + case TOK_EXPR: + switch (t->type) { + case EXPR_PLUS : putchar('+'); break; + case EXPR_MINUS: putchar('-'); break; + } break; } - opsize += (l[i].aop <= 0x000000FF) + 0; - opsize += (l[i].aop > 0x000000FF) + 1; - opsize += (l[i].aop > 0x0000FFFF) + 2; - opsize += (l[i].aop > 0xFFFFFFFF) + 3; - if (opsize) { - bitnum = bitsize[opsize-1]; - } - - j = 0; - - if (l[i].aopbase == BASE_CHAR) { - switch (l[i].aop) { - default : ch[j++] = l[i].aop; break; - case '\n': ch[j++] = '\\'; ch[j++] = 'n' ; break; - case '\r': ch[j++] = '\\'; ch[j++] = 'r' ; break; - case '\b': ch[j++] = '\\'; ch[j++] = 'b' ; break; - case '\\': ch[j++] = '\\'; ch[j++] = '\\'; break; - case '\'': ch[j++] = '\\'; ch[j++] = '\''; break; - case '\"': ch[j++] = '\\'; ch[j++] = '\"'; break; - } - } - - ch[j] = '\0'; - j = 0; - - switch (l[i].aopbase) { - case BASE_HEX : printf("$%"PRIX64, l[i].aop); break; - case BASE_DEC : printf("%"PRIu64, l[i].aop); break; - case BASE_BIN : printf("%%%s", showbits(l[i].aop, bitnum, dbg)); break; - case BASE_CHAR: printf("\'%s\'", ch); break; - } - bitnum = 0; - opsize = 0; } - if (flags & 0x7F) { + if (am != 0xFF) { if (fall) { fall = 0; } - switch (l[i].am) { + switch (am) { case INDX: case ZMX: printf(", x"); - if (l[i].am == ZMX) { + if (am == ZMX) { break; } fall = 1; @@ -308,8 +256,8 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln, break; } } - spaces = l[i].espace; - tabs = l[i].etab; + spaces = s->espace; + tabs = s->etab; while (spaces || tabs) { if (spaces) { putchar(' '); @@ -320,302 +268,12 @@ void list(struct line *l, uint16_t start, uint16_t end, uint8_t all, uint8_t ln, tabs--; } } - if (iscom) { - printf(";%s", comment[l[i].com]); + if (t->id == TOK_COMMENT) { + printf(";%s", t->str); } puts(""); - } -} - -void assemble(struct line *line, bytecount *bc, uint8_t dbg) { - bc->progsize = 0; - bc->datasize = 0; - uint64_t tmpaddr; - uint64_t value; - uint16_t flags = 0; - uint16_t i = 0; - uint16_t k = 0; - uint16_t tmp; - uint8_t c = 0; - uint8_t prefix = 0; - uint8_t opsize = 0; - uint8_t skip = 0; - - uint64_t address; - uint64_t op; - uint64_t aop; - uint16_t symid; - uint16_t str; - uint16_t com; - uint8_t islabel; - uint8_t opbase; - uint8_t aopbase; - uint8_t dir; - uint8_t am; - uint8_t cm; - uint8_t rs; - uint8_t ins; - - for (; i < lineidx; i++) { - if (dbg) { - printf("assemble(): i: $%X\n", i); - } - address = line[i].addr; - tmpaddr = address; - op = line[i].op; - aop = line[i].aop; - symid = line[i].sym; - str = line[i].str; - com = line[i].com; - islabel = line[i].islabel; - opbase = line[i].opbase; - aopbase = line[i].aopbase; - dir = line[i].dir; - am = line[i].am; - cm = line[i].cm; - rs = line[i].rs; - ins = line[i].mne; - flags = 0; - flags |= (dir != 0x00FF) << 0x00; - flags |= (ins != 0x00FF) << 0x01; - flags |= (rs != 0x00FF) << 0x02; - flags |= (am != 0x00FF) << 0x03; - flags |= (opbase != 0x00FF) << 0x04; - flags |= (aopbase != 0x00FF) << 0x05; - flags |= (symid != 0xFFFF) << 0x06; - flags |= (islabel ) << 0x07; - flags |= (am != 0x00FF) << 0x08; - flags |= (cm != 0x00FF) << 0x09; - flags |= (str != 0xFFFF) << 0x0A; - if (dbg) { - printf("assemble(): "); - putchar('%'); - printf("%u", str != 0xFFFF); - printf("%u", cm != 0x00FF); - printf("%u", am != 0x00FF); - printf("%u", islabel ); - printf("%u", symid != 0xFFFF); - printf("%u", aopbase != 0x00FF); - printf("%u", opbase != 0x00FF); - printf("%u", am != 0x00FF); - printf("%u", rs != 0x00FF); - printf("%u", ins != 0x00FF); - printf("%u", dir != 0x00FF); - putchar('\n'); - - printf("assemble(): "); - printf("flags: $%04X\n", flags); - } - if (!flags) { - if (dbg) { - printf("assemble(): "); - puts("This line only contains a comment, so skip it."); - } - continue; - } - opsize = 0; - skip = 0; - if ((flags & 0x53) == 0x42 || (flags & 0x51) == 0x41) { - value = symbols[symid]->val; - } else { - value = op; - } - if (flags & 0x220) { - switch (cm) { - case 0: value += aop; break; - case 1: value -= aop; break; - } - } - if (dbg) { - printf("assemble(): value: $%"PRIX64"\n", value); - } - switch (dir) { - case DIR_ORG: - tmpaddr = value; - if (dbg) { - printf("assemble(): "); - printf("The Program Counter's origin is now at, $%"PRIX64".\n", value); - } - skip = 1; - break; - case DIR_BYTE: - if (flags & 0x400) { - for (k = 0; string[str][k] != '\0'; k++) { - switch (string[str][k]) { - case '\\': - switch (string[str][k+1]) { - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case '0': c = '\0'; break; - } - k++; - break; - default: - c = string[str][k]; - break; - } - bc->datasize++; - addr[tmpaddr++] = c; - } - addr[tmpaddr] = '\0'; - if (dbg) { - printf("assemble(): "); - printf("Placed string \"%s\"", string[str]); - printf(", at address(es) $%"PRIX64"-$%"PRIX64".\n", address, tmpaddr); - } - } else { - bc->datasize++; - addr[tmpaddr++] = value & 0xFF; - } - break; - case DIR_QWORD: - addr[tmpaddr+7] = value >> 0x38; - addr[tmpaddr+6] = value >> 0x30; - addr[tmpaddr+5] = value >> 0x28; - addr[tmpaddr+4] = value >> 0x20; - tmp+=4; - bc->datasize+=4; - case DIR_DWORD: - addr[tmpaddr+3] = value >> 0x18; - addr[tmpaddr+2] = value >> 0x10; - tmp+=2; - bc->datasize+=2; - case DIR_WORD: - addr[tmpaddr+1] = value >> 0x08; - addr[tmpaddr ] = value & 0xFF; - tmp+=2; - bc->datasize+=2; - break; - } - tmpaddr += tmp; - tmp = 0; - if (skip | (flags & 0x80) | (flags == 0x108)) { - if (dbg) { - printf("assemble(): The address that this line starts at is, $%"PRIX64".\n", address); - printf("assemble(): The address that this line ends on is, $%"PRIX64".\n", tmpaddr); - } - continue; - } - if (flags & 0x04) { - prefix = (rs << 4) | 3; - } else { - rs = 0; - } - if (flags & 0x102) { - if (ins == 80) { - if (flags & 0x10) { - am = IMM; - prefix |= 0x13; - } else { - am = IMPL; - addr[tmpaddr++] = opcodes[ins][IMM]; - bc->progsize++; - if (dbg) { - printf("assemble(): The instruction that is being used is, %s.\n", mne[ins]); - printf("assemble(): The addressing mode that this instruction is using is, %s.\n", adrmode[IMM]); - printf("assemble(): The opcode for this instruction, and addressing mode is, $%02X.\n", opcodes[ins][IMM]); - } - } - } - opsize = 0; - if (am != IMM && am != IMPL) { - opsize = (value <= 0x00000000000000FF) ? 1 : opsize; - opsize = (value > 0x00000000000000FF) ? 2 : opsize; - opsize = (value > 0x000000000000FFFF) ? 3 : opsize; - opsize = (value > 0x0000000000FFFFFF) ? 4 : opsize; - opsize = (value > 0x00000000FFFFFFFF) ? 5 : opsize; - opsize = (value > 0x000000FFFFFFFFFF) ? 6 : opsize; - opsize = (value > 0x0000FFFFFFFFFFFF) ? 7 : opsize; - opsize = (value > 0x00FFFFFFFFFFFFFF) ? 8 : opsize; - if (opsize) { - opsize--; - prefix |= amp[opsize]; - } - } - if (prefix) { - if (dbg) { - printf("assemble(): "); - puts("Prefix byte detected."); - } - addr[tmpaddr++] = prefix; - bc->progsize++; - if (dbg) { - uint8_t addrsize = (prefix & 0x0C) >> 2; - uint8_t regsize = (prefix & 0x30) >> 4; - - printf("assemble(): "); - printf("The values of the prefix bits are"); - printf(", AM: %u, RS: %u\n", addrsize, regsize); - } - prefix = 0; - } - if (opcodes[ins][am] != 0xFF) { - addr[tmpaddr++] = opcodes[ins][am]; - bc->progsize++; - if (dbg) { - printf("assemble(): The instruction that is being used is, %s.\n", mne[ins]); - printf("assemble(): The addressing mode that this instruction is using is, %s.\n", adrmode[am]); - printf("assemble(): The opcode for this instruction, and addressing mode is, $%02X.\n", opcodes[ins][am]); - } - switch (am) { - case IMM: - switch (rs) { - case 3: - addr[tmpaddr+7] = value >> 0x38; - addr[tmpaddr+6] = value >> 0x30; - addr[tmpaddr+5] = value >> 0x28; - addr[tmpaddr+4] = value >> 0x20; - tmp+=4; - case 2: - addr[tmpaddr+3] = value >> 0x18; - addr[tmpaddr+2] = value >> 0x10; - tmp+=2; - case 1: - addr[tmpaddr+1] = value >> 0x08; - tmp+=1; - case 0: - addr[tmpaddr ] = value & 0xFF; - tmp+=1; - } - break; - case ABS: - case ZM: - case ZMX: - case ZMY: - case IND: - case INDX: - case INDY: - switch (opsize) { - case 7: addr[tmpaddr+7] = value >> 0x38; tmp++; - case 6: addr[tmpaddr+6] = value >> 0x30; tmp++; - case 5: addr[tmpaddr+5] = value >> 0x28; tmp++; - case 4: addr[tmpaddr+4] = value >> 0x20; tmp++; - case 3: addr[tmpaddr+3] = value >> 0x18; tmp++; - case 2: addr[tmpaddr+2] = value >> 0x10; tmp++; - case 1: addr[tmpaddr+1] = value >> 0x08; tmp++; - case 0: addr[tmpaddr ] = value & 0xFF; tmp++; - } - break; - } - tmpaddr += tmp; - bc->progsize += tmp; - tmp = 0; - } - } - if (dbg) { - printf("assemble(): The address that this line starts at is, $%"PRIX64".\n", address); - printf("assemble(): The address that this line ends on is, $%"PRIX64".\n", tmpaddr); - - printf("assemble(): The program size is now at"); - printf(", %"PRIu64" bytes in decimal", bc->progsize); - printf(", and $%"PRIX64" bytes in hex.\n", bc->progsize); - - printf("assemble(): The data size is now at"); - printf(", %"PRIu64" bytes in decimal", bc->datasize); - printf(", and $%"PRIX64" bytes in hex.\n", bc->datasize); - } - } + s = s->next; + } while (s != e && s); } int asmmon(const char *fn) { @@ -700,6 +358,9 @@ int asmmon(const char *fn) { if (fp2 != NULL) { fclose(fp2); } + if (lines) { + free_lines(); + } return 2; case 0x02: viewmem(address); @@ -727,12 +388,12 @@ int asmmon(const char *fn) { for (; isspace(tmp[i]); i++); } switch (tmp[i]) { - case '$': base = BASE_HEX; i++; break; - case '%': base = BASE_BIN; i++; break; + case '$': base = 16; i++; break; + case '%': base = 2; i++; break; default: j = i; for (; isdigit(tmp[j]); j++, isflag++); - base = (isflag) ? BASE_DEC : 0xFF; + base = (isflag) ? 10 : 0xFF; isflag = 0; j = 0; break; @@ -741,11 +402,7 @@ int asmmon(const char *fn) { arg[j] = '\0'; j = 0; if (base != 0xFF) { - switch (base) { - case BASE_HEX: value = strtol(arg, NULL, 16); break; - case BASE_BIN: value = strtol(arg, NULL, 2); break; - case BASE_DEC: value = strtol(arg, NULL, 10); break; - } + value = strtol(arg, NULL, base); base = 0xFF; (isstart) ? (start = value) : (end = value); if (isstart) { @@ -765,15 +422,15 @@ int asmmon(const char *fn) { } i++; } - list(tokline, start, end, isstart, islinenum, isaddr, isdebug); + list(start, end, isstart, islinenum, isaddr, isdebug); } else { - list(tokline, 0, 0, 1, 0, 0, 0); + list(0, 0, 1, 0, 0, 0); } break; case 0x08: if (!inc_file) { printf("Assembling %s\n", (strcasecmp(fn, "stdin")) ? fn : "typed in program."); - assemble(tokline, &bc, dbg); + assemble(lines, &bc, dbg); progsize = bc.progsize; datasize = bc.datasize; printf("Finished assembling %s\n", (strcasecmp(fn, "stdin")) ? fn : "typed in program."); @@ -846,7 +503,7 @@ int asmmon(const char *fn) { case 0xFF: break; default: - address = lex(lex_line, tokline, address, dbg); + address = lex(lex_line, address, dbg); break; } } @@ -860,5 +517,8 @@ int asmmon(const char *fn) { if (fp2 != NULL) { fclose(fp2); } + if (lines) { + free_lines(); + } return 0; } |