summaryrefslogtreecommitdiff
path: root/asmmon.c
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-05-28 20:03:09 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2020-05-28 20:03:09 -0400
commit7ba25336342282bfe57dbb6ddf8f3e2ae3e1b719 (patch)
tree1e9a5921d19056be61b9f613f254556edf5242a7 /asmmon.c
parent691ae45b3916379b0b1d845a5581d9068426b134 (diff)
Refactored the assembler, yet again, and implemented
support for comma separated values. The assembler now uses a linked list of tokenized lines, each containing a linked list of tokens for that line. I also moved all of the large tables into the higher parts of memory, in order to free up the lower part of memory for the user. Comma sepparated values only work with directives, and only with the byte", word, dword, and qword directives. I also added support for getting the upper, and lower halves of an address. The tokens for both of those are '<', and '>' respectively.
Diffstat (limited to 'asmmon.c')
-rw-r--r--asmmon.c554
1 files changed, 107 insertions, 447 deletions
diff --git a/asmmon.c b/asmmon.c
index 81e4b28..840deae 100644
--- a/asmmon.c
+++ b/asmmon.c
@@ -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;
}