summaryrefslogtreecommitdiff
path: root/lexer/backup/assemble.c
diff options
context:
space:
mode:
Diffstat (limited to 'lexer/backup/assemble.c')
-rw-r--r--lexer/backup/assemble.c975
1 files changed, 975 insertions, 0 deletions
diff --git a/lexer/backup/assemble.c b/lexer/backup/assemble.c
new file mode 100644
index 0000000..28825d1
--- /dev/null
+++ b/lexer/backup/assemble.c
@@ -0,0 +1,975 @@
+#include "asmmon.h"
+
+#define AM_ADDR (AM_ZM | AM_ZMX | AM_ZMY | \
+ AM_IND | AM_INDX | AM_INDY | \
+ AM_ABS | AM_ABX | AM_ABY | \
+ AM_AIND | AM_AINDX | AM_AINDY | \
+ AM_INDX2 | AM_ZM2)
+
+static const uint64_t mem_size = 0x04000000; /* Size of address space. */
+
+token *tok_global;
+
+uint8_t isexpr(uint8_t type, uint8_t dbg) {
+ switch (type) {
+ case EXPR_PLUS:
+ case EXPR_MINUS:
+ case EXPR_LOW:
+ case EXPR_HIGH:
+ case EXPR_OR:
+ case EXPR_LSHFT:
+ case EXPR_RSHFT:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+uint8_t get_rs(token *t, uint8_t dbg) {
+ if (t->id == TOK_RS) {
+ return t->type;
+ } else {
+ return 0xFF;
+ }
+}
+
+uint8_t get_of(token *t, uint8_t dbg) {
+ if (t->id == TOK_OF) {
+ return t->type;
+ } else {
+ return 0xFF;
+ }
+}
+
+uint8_t get_ind(uint8_t mne, uint8_t am, uint8_t dbg) {
+ uint8_t base_idx = 0;
+ uint8_t offset = 0;
+ switch (mne) {
+ case CMP: base_idx = CMP_IND; break;
+ case CPB: base_idx = CPB_IND; break;
+ case JMP: base_idx = JMP_IND; break;
+ case JSR: base_idx = JSR_IND; break;
+ case LDA: base_idx = LDA_IND; break;
+ case LDB: base_idx = LDB_IND; break;
+ case LDX: base_idx = LDX_IND; break;
+ case LDY: base_idx = LDY_IND; break;
+ case STA: base_idx = STA_IND; break;
+ case STB: base_idx = STB_IND; break;
+ case STX: base_idx = STX_IND; break;
+ case STY: base_idx = STY_IND; break;
+ }
+ switch (am) {
+ case IND : offset = 0; break;
+ case INDY: offset += 1; break;
+ case INDX: offset += 2; break;
+ }
+ return base_idx + offset;
+}
+
+uint8_t get_eind(uint8_t mne, uint8_t dbg) {
+ switch (mne) {
+ case DEC: return DEC_EIND;
+ case INC: return INC_EIND;
+ case STY: return STY_EIND;
+ case STA: return STA_EIND;
+ case STB: return STB_EIND;
+ case LDX: return LDX_EIND;
+ case STX: return STX_EIND;
+ case CPB: return CPB_EIND;
+ case CPX: return CPX_EIND;
+ case CPY: return CPY_EIND;
+ }
+ return 0xFF;
+}
+
+static void write_value(uint64_t value, uint64_t address, uint8_t size) {
+ if (address < mem_size) {
+ size = (size > 7) ? 7 : size;
+ #if 1
+ if (size < 7) {
+ uint64_t mask = (-(uint64_t)1 >> ((7 - size) * 8));
+ *(uint64_t *)(addr+address) = (*(uint64_t *)(addr+address) & ~mask) | (value & mask);
+ } else {
+ *(uint64_t *)(addr+address) = value;
+ }
+ #else
+ memcpy(addr+address, &value, size+1);
+ #endif
+ }
+}
+
+uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t end_expr, uint8_t stop_reg, uint8_t dbg) {
+ uint64_t value = 0;
+ uint64_t tmp_val = 0;
+ uint8_t type = EXPR_NONE;
+ uint8_t isstart = 1;
+ do {
+ if (t->id == TOK_EXPR) {
+ type = t->type;
+ t = t->next;
+ }
+ if (stop_reg && t->id == TOK_REG) {
+ break;
+ }
+ switch (t->id) {
+ case TOK_HEX:
+ case TOK_DEC:
+ case TOK_BIN:
+ case TOK_CHAR: tmp_val = t->qword; t = t->next; break;
+ case TOK_SYM:
+ 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;
+ }
+ if (end_expr != 0xFF && type == end_expr) {
+ break;
+ }
+ switch (type) {
+ case EXPR_PLUS : (isstart) ? (value = tmp_val) : (value += tmp_val); break;
+ case EXPR_MINUS: (isstart) ? (value = -tmp_val) : (value -= tmp_val); break;
+ case EXPR_OR : value |= tmp_val; break;
+ case EXPR_LSHFT: value <<= tmp_val; break;
+ case EXPR_RSHFT: value >>= tmp_val; break;
+ case EXPR_LOW :
+ value = tmp_val;
+ switch (size) {
+ default:
+ case 2 : value &= 0xFFFFFFFF; break;
+ case 1 : value &= 0x0000FFFF; break;
+ case 0 : value &= 0x000000FF; break;
+ }
+ break;
+ case EXPR_HIGH :
+ value = tmp_val;
+ switch (size) {
+ default:
+ case 2 : value >>= 0x20; break;
+ case 1 : value >>= 0x10; break;
+ case 0 : value >>= 0x08; break;
+ }
+ break;
+ case EXPR_NONE : value = tmp_val; break;
+ }
+ isstart = 0;
+ if (dbg) {
+ printf("get_val(): Value: $%"PRIX64", Expression type: $%X, Expression Value: $%"PRIX64".\n", value, type, tmp_val);
+ }
+ } while (t && t->id == TOK_EXPR && isexpr(t->type, dbg));
+ return value;
+}
+
+token *skip_expr(token *t, uint8_t end_expr, uint8_t stop_reg, uint8_t dbg) {
+ do {
+ t = (t->id == TOK_EXPR) ? t->next : t;
+ if (stop_reg && t->id == TOK_REG) {
+ break;
+ }
+ switch (t->id) {
+ case TOK_HEX :
+ case TOK_DEC :
+ case TOK_BIN :
+ case TOK_CHAR :
+ case TOK_SYM :
+ case TOK_LABEL: t = t->next; break;
+ }
+ if (end_expr != 0xFF && t->id == TOK_EXPR && t->type == end_expr) {
+ break;
+ }
+ } while (t && t->id == TOK_EXPR && isexpr(t->type, dbg));
+ return t;
+}
+
+
+
+uint8_t get_directivesize(uint8_t type, uint8_t dbg) {
+ switch (type) {
+ case DIR_QWORD: return 3;
+ case DIR_DWORD: return 2;
+ case DIR_WORD : return 1;
+ case DIR_BYTE : return 0;
+ }
+ return 0;
+}
+
+uint16_t handle_struct(line **ln, uint64_t address, uint16_t offset, uint8_t dbg) {
+ uint8_t is_struct = 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:
+ is_struct = (tok->type == DIR_STRUCT);
+ found = (tok->type == DIR_STRUCT || tok->type == DIR_UNION);
+ break;
+ case TOK_STRUCT: is_struct = 1;
+ case 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 = ((is_struct && t->type == DIR_ENDSTRUCT) || (!is_struct && 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, 0xFF, 0, dbg); t = skip_expr(t, 0xFF, 0, dbg); break;
+ }
+ if (member && t->type != DIR_UNION && t->type != DIR_STRUCT) {
+ member->val = offset;
+ }
+ if (is_struct) {
+ size += member_size;
+ offset += member_size;
+ } else if (size < member_size) {
+ size = member_size;
+ }
+ }
+ ismember = 0;
+ break;
+ }
+ }
+ if (done) {
+ break;
+ }
+ }
+ *ln = l;
+ if (strct != NULL) {
+ strct->val = size;
+ }
+ return 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;
+ uint8_t tmp = 0;
+ uint8_t type = t->type;
+ uint64_t tmpaddr = address;
+ t = t->next;
+ for (; t; t = t->next) {
+ tmp = 0;
+ switch (t->id) {
+ case TOK_HEX:
+ case TOK_DEC:
+ case TOK_BIN:
+ case TOK_CHAR:
+ case TOK_SYM:
+ case TOK_LABEL:
+ val.u64 = get_val(t, tmpaddr, get_directivesize(type, dbg), 0xFF, 0, dbg);
+ switch (type) {
+ case DIR_QWORD: tmp = 8; break;
+ case DIR_DWORD: tmp = 4; break;
+ case DIR_WORD : tmp = 2; break;
+ case DIR_BYTE : tmp = 1; break;
+ }
+ write_value(val.u64, tmpaddr, tmp-1);
+ tmpaddr += tmp;
+ bc->datasize += tmp;
+ if (t->next && t->next->id == TOK_EXPR && isexpr(t->next->type, dbg)) {
+ t = skip_expr(t, 0xFF, 0, dbg);
+ }
+ break;
+ case TOK_STRING:
+ if (type == DIR_BYTE) {
+ for (uint16_t k = 0; t->str[k] != '\0'; k++) {
+ switch (t->str[k]) {
+ case '\\':
+ switch (t->str[k+1]) {
+ case 'n' : c = '\n'; break;
+ case 'r' : c = '\r'; break;
+ case 't' : c = '\t'; break;
+ case '\"': c = '\"'; break;
+ case '\'': c = '\''; break;
+ case '\\': c = '\\'; break;
+ case '0' : c = '\0'; break;
+ }
+ k++;
+ break;
+ default: c = t->str[k]; break;
+ }
+ if (isasm) {
+ addr[tmpaddr] = c;
+ }
+ tmpaddr++;
+ bc->datasize++;
+ }
+ if (isasm) {
+ addr[tmpaddr] = '\0';
+ }
+ tmpaddr++;
+ bc->datasize++;
+ }
+ break;
+ }
+ if (t == NULL) {
+ break;
+ }
+ }
+ return tmpaddr;
+}
+
+static uint8_t write_inst(uint8_t prefix, uint8_t ext_prefix, uint8_t opcode, uint64_t value, uint64_t address, uint8_t size, uint8_t isasm, uint8_t dbg) {
+ uint8_t inst_size = 0;
+ union reg ins;
+ if (prefix & 3) {
+ ins.u8[inst_size++] = prefix;
+ }
+ if ((ext_prefix & 0x0D) == 0x0D) {
+ ins.u8[inst_size++] = ext_prefix;
+ }
+ ins.u8[inst_size++] = opcode;
+ if (isasm) {
+ write_value(ins.u64, address, inst_size-1);
+ if (size) {
+ write_value(value, address+inst_size, size-1);
+ }
+ }
+ inst_size += size;
+ return inst_size;
+}
+
+void get_operands(token *t, operand *op, uint64_t address, uint8_t rs, uint8_t dbg) {
+ uint8_t op_type;
+ uint8_t op_inst;
+ switch (t->id) {
+ case TOK_OPCODE:
+ case TOK_EXTOP :
+ case TOK_ORTHO :
+ op_type = tok->id;
+ op_inst = tok->byte;
+ t = t->next;
+ break;
+ }
+ int i = 0;
+ int old_i = -1;
+ uint8_t expr_type = 0xFF;
+ uint8_t stop_reg = 0;
+ uint64_t value = 0;
+ uint8_t reg = 0;
+ uint8_t got_value = 0;
+ uint8_t is_sib = 0;
+ for (; t; t = t->next) {
+ switch (t->id) {
+ case TOK_HEX :
+ case TOK_DEC :
+ case TOK_BIN :
+ case TOK_SYM :
+ case TOK_LABEL:
+ if (!got_value) {
+ expr_type = (expr_type == 0xFF && t->next && t->next->id == TOK_EXPR) ? t->next->type : expr_type;
+ switch (expr_type) {
+ default : stop_reg = 1; break;
+ case EXPR_MUL : stop_reg = 0; break;
+ }
+ is_sib = !stop_reg;
+ value = get_val(t, address, (rs != 0xFF) ? rs : 0, (!stop_reg) ? expr_type : 0xFF, stop_reg, dbg);
+ got_value = 1;
+ } else {
+ got_value = 0;
+ }
+ /* Falls Through. */
+ case TOK_MEM:
+ if (old_i != i) {
+ op[i].type = 1; /* Set type to memory. */
+ op[i].id = (t->id == TOK_MEM) ? t->type : op[i].id;
+ op[i].id = (is_sib) ? MEM_SIB : op[i].id;
+ op[i].id2[0] = (is_sib) ? value : op[i].id2[0];
+ old_i = i;
+ } else {
+ }
+ op[i].value = (!is_sib && got_value) ? value : op[i].value;
+ if (stop_reg && got_value) {
+ t = skip_expr(t, 0xFF, stop_reg, dgb);
+ }
+ i += (t->next && t->next->id != TOK_EXPR);
+ break;
+ case TOK_REG:
+ if (old_i != i) {
+ op[i].type = 0; /* Set type to register. */
+ op[i].id = t->type;
+ old_i = i;
+ } else {
+ op[i].id = (op[i].id == MEM_IND) ? MEM_RIND : op[i].id;
+ is_sib = (op[i].id == MEM_SIB);
+ op[i].id2[is_sib] = (t->type << (reg*4));
+ reg++;
+ reg = (reg > 1) ? 0 : reg;
+ }
+ i += (t->next && t->next->id != TOK_EXPR);
+ break;
+ case TOK_EXPR:
+ expr_type = t->type;
+ switch (expr_type) {
+ default : stop_reg = 1; break;
+ case EXPR_MUL : stop_reg = 0; break;
+ }
+ if (!got_value) {
+ value = get_val(t, address, (rs != 0xFF) ? rs : 0, (!stop_reg) ? expr_type : 0xFF, stop_reg, dbg);
+ got_value = 1;
+ } else {
+ got_value = 0;
+ }
+ break;
+ }
+ }
+}
+
+uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) {
+ union reg val;
+ uint8_t opsize;
+ uint8_t id;
+ uint8_t instr;
+ uint8_t opcode;
+ uint8_t ext_prefix = 0;
+ uint8_t type;
+ uint32_t am = 0;
+ uint8_t tmp = 0;
+ uint8_t prefix = 0;
+ uint8_t rs = 0;
+ uint8_t of = 0;
+ uint8_t tmp_prefix = 0;
+ uint8_t inst_size = 0;
+ val.u64 = 0;
+ instruction ins;
+ operand op[2];
+ memset(op, 0xFF, sizeof(op));
+
+ for (; t; t = t->next) {
+ if (t->id == TOK_OPCODE || t->id == TOK_EXTOP) {
+ id = t->id;
+ instr = t->byte;
+ type = t->type;
+ } else {
+ break;
+ }
+ tmp = 0;
+ opsize = 1;
+ opcode = 0;
+ if (t->next) {
+ rs = get_rs(t->next, dbg);
+ t = (rs != 0xFF) ? t->next : t;
+ if (t->next) {
+ of = get_of(t->next, dbg);
+ t = (of != 0xFF) ? t->next : t;
+ }
+ }
+ get_operands(t, op, address, rs, dbg);
+ if (rs != 0xFF || of != 0xFF) {
+ tmp_prefix = (rs != 0xFF) ? (rs << 0) : tmp_prefix;
+ tmp_prefix |= (of != 0xFF) ? (of << 2) : tmp_prefix;
+ }
+ prefix = (tmp_prefix) ? ((tmp_prefix << 4) | 3) : 0;
+ uint8_t isincdec = (instr == INC || instr == DEC);
+ uint8_t isimplied = (op[0].type == 0xFF);
+ switch (id) {
+ case TOK_OPCODE: ins = inst[instr]; break;
+ case TOK_EXTOP : ins = ext_inst[instr]; break;
+ case TOK_ORTHO : ins = ortho_inst[instr]; break;
+ }
+ am = ins.am;
+ uint8_t is_eind = (op[0].type && op[0].id == MEM_RIND && op[0].id2[0] == REG_E);
+ uint8_t is_mem = (op[0].type && op[0].id != MEM_IMM);
+ uint8_t is_idx = (is_mem && !op[1].type && (op[1].id == REG_X || op[1].id == REG_Y));
+ if (id == TOK_EXTOP || (id == TOK_OPCODE && is_eind)) {
+ ext_prefix = 0x0D;
+ } else if (!is_idx) {
+ ext_prefix = 0x1D;
+ }
+ if ((am & AM_IMPL) && isimplied) {
+ type = IMPL;
+ } else {
+ if (ins.am & AM_REL) {
+ type = REL;
+ }
+ }
+ opcode = ins.op;
+ uint64_t saveaddr = address;
+ uint64_t max_val = 0;
+ uint8_t i = 0;
+ uint8_t j = 1;
+ uint8_t type2 = 0xFF;
+
+ switch (type) {
+ case REG_B:
+ case IMPL:
+ case REG_E:
+ if (id == TOK_OPCODE && instr == CPS) {
+ rs = 0;
+ }
+ if ((am & (AM_IMPL|AM_BREG|AM_EIND|AM_EIND2))) {
+ if ((type == EIND) && (am & AM_EIND|AM_EIND2)) {
+ int eind_type = ((am & AM_EIND2) != 0);
+ switch (eind_type) {
+ case 0: opcode = (id == TOK_EXTOP) ? opcode+0x14 : opcode+0x10; break;
+ case 1: opcode = (id == TOK_EXTOP) ? opcode+0x01 : eind_base_ops[get_eind(instr, dbg)]; break;
+ }
+ }
+ opcode = ((am & AM_BREG) && type == BREG) ? opcode+0x14 : opcode;
+ }
+ break;
+ case REL:
+ case IMM:
+ if (am & (AM_IMM|AM_REL|AM_ORTHO|AM_ORTHO2)) {
+ rs = (rs != 0xFF) ? rs : 0;
+ tmp = (1 << rs);
+ if (type == REL) {
+ uint64_t max_sign = 0;
+ uint8_t offset = 1;
+ uint64_t tmp_val;
+ tmp_val = val.u64;
+ offset += (prefix != 0);
+ tmp_val -= offset+tmp;
+ tmp_val -= address;
+ switch (rs) {
+ default: max_sign = (int8_t )(1 << 7); break;
+ case 1 : max_sign = (int16_t)(1 << 15); break;
+ case 2 : max_sign = (int32_t)(1 << 31); break;
+ case 3 : max_sign = (int64_t)((uint64_t)1 << 63); break;
+ }
+ if ((int64_t)tmp_val > ~(int64_t)max_sign || (int64_t)tmp_val < (int64_t)max_sign) {
+ offset += (!rs);
+ rs += (rs <= 3);
+ tmp = (1 << rs);
+ tmp_val = val.u64;
+ tmp_val -= offset+tmp;
+ tmp_val -= address;
+ prefix = ((rs << 4) | 3);
+ }
+ val.u64 = tmp_val;
+ }
+ }
+ break;
+ default:
+ if (of != 0xFF) {
+ i = 8;
+ for (; i <= 64; i += 8, j++) {
+ max_val |= ((uint64_t)1 << (i-1));
+ if ((int64_t)val.u64 >= ~(int64_t)(max_val) || (int64_t)val.u64 <= (int64_t)(max_val)) {
+ opsize = j;
+ break;
+ }
+ }
+ } else {
+ for (; i <= 64; i += 8, j++) {
+ max_val |= (0xFF << i);
+ if (val.u64 <= max_val) {
+ opsize = j;
+ break;
+ }
+ }
+ }
+ type2 = type;
+ if (type == 0xFF || (id == TOK_EXTOP && type2 != 0xFF)) {
+ switch (opsize-1) {
+ case 0: case 2: case 5: case 3: type = ZM ; break;
+ case 1: case 4: case 6: case 7: type = ABS; break;
+ }
+ }
+ switch (type2) {
+ case ZMX : type = (type == ABS) ? ABSX : type2; break;
+ case ZMY : type = (type == ABS) ? ABSY : type2; break;
+ case IND : type = (type == ABS) ? AIND : type2; break;
+ case INDX: type = (type == ABS) ? AINDX : type2; break;
+ case INDY: type = (type == ABS) ? AINDY : type2; break;
+ }
+ if (opsize) {
+ uint8_t is_abs = 0;
+ switch (type) {
+ case ABS :
+ case ABSX :
+ case ABSY :
+ case AIND :
+ case AINDX:
+ case AINDY: is_abs = 1; break;
+
+ }
+ if (!is_abs || (type2 != 0xFF && type == type2)) {
+ switch (opsize) {
+ case 2: opsize = 3; break;
+ case 5: opsize = 6; break;
+ }
+ }
+ prefix |= amp[opsize-1];
+ }
+ if (am & AM_ADDR|AM_ORTHO|AM_ORTHO2) {
+ switch (type) {
+ case ZM:
+ if (am & AM_ZM) {
+ opcode += 0x04;
+ } else if (am & AM_ZM2) {
+ opcode += 0x20;
+ }
+ break;
+ case ZMX:
+ if (am & AM_ZMX) {
+ opcode += (id == TOK_OPCODE) ? 0x06 : 0x54;
+ }
+ break;
+ case ZMY:
+ if (am & AM_ZMY) {
+ opcode += 0x14;
+ }
+ break;
+ case INDX:
+ if (am & AM_INDX) {
+ opcode += (id == TOK_OPCODE) ? 0x16 : 0x94;
+ break;
+ }
+ /* Falls Through. */
+ case IND:
+ case INDY:
+ if ((id == TOK_OPCODE) && (am & (AM_IND|AM_INDY|AM_INDX2))) {
+ opcode = ind_ops[get_ind(instr, type, dbg)];
+ } else {
+ opcode += (type == IND) ? 0x44 : 0x84;
+ }
+ break;
+ case ABS:
+ if (am & AM_ABS) {
+ opcode += 0x10;
+ }
+ break;
+ case ABSX:
+ if (am & AM_ABX) {
+ opcode += 0x50;
+ }
+ break;
+ case ABSY:
+ if (am & AM_ABY) {
+ opcode += 0x00;
+ }
+ break;
+ case AIND:
+ if (am & AM_AIND) {
+ opcode += 0x40;
+ }
+ break;
+ case AINDX:
+ if (am & AM_AINDX) {
+ opcode += 0x90;
+ }
+ break;
+ case AINDY:
+ if (am & AM_AINDY) {
+ opcode += 0x80;
+ }
+ break;
+
+ }
+ tmp = opsize;
+ }
+ break;
+ }
+ inst_size = write_inst(prefix, ext_prefix, opcode, val.u64, address, tmp, isasm, dbg);
+ address += inst_size;
+ bc->progsize += inst_size;
+ }
+ return address;
+}
+
+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, 0xFF, 0, dbg); break;
+ case DIR_ORG: t = t->next; address = get_val(t, address, 3, 0xFF, 0, dbg); break;
+ case DIR_BYTE:
+ case DIR_WORD:
+ case DIR_DWORD:
+ case DIR_QWORD: address = handle_directive(t, bc, isasm, address, dbg); break;
+ }
+ break;
+ case TOK_EXTOP :
+ case TOK_OPCODE: address = handle_opcode(t, bc, isasm, address, dbg); break;
+ case TOK_COMMENT: break;
+ }
+ }
+ return address;
+}
+
+token *make_token(uint8_t id, uint8_t type, uint8_t space, uint8_t tab, uint64_t value, char *str, symbol *s) {
+ token *new_tok = malloc(sizeof(token));
+ (last_tok) ? (last_tok->next = new_tok) : (tokens = new_tok);
+
+ new_tok->id = id;
+ new_tok->type = type;
+
+ new_tok->tab = tab;
+ new_tok->space = space;
+
+ new_tok->subtab = 0;
+ new_tok->subspace = 0;
+
+ new_tok->digits = 0;
+
+ if (s) {
+ new_tok->sym = s;
+ } else if (str[0]) {
+ new_tok->str = str;
+ } else {
+ new_tok->qword = value;
+ }
+ new_tok->next = NULL;
+ last_tok = new_tok;
+ return new_tok;
+}
+
+void assemble(line *ln, bytecount *bc, uint8_t dbg) {
+ uint64_t address = 0;
+ line *l = ln;
+ for (int i = 0; i < 2; i++) {
+ l = ln;
+ for (; l; l = l->next) {
+ l->addr = address;
+ token *t = l->tok;
+ address = parse_tokens(t, &l, bc, 0, address, dbg);
+ }
+ l = ln;
+ for (; l; l = l->next) {
+ address = l->addr;
+ token *t = l->tok;
+ for (; t; t = t->next) {
+ if (t->id == TOK_LABEL && t->sym->val != address) {
+ t->sym->val = l->addr;
+ }
+ }
+ }
+ }
+ l = ln;
+ bc->progsize = 0;
+ bc->datasize = 0;
+ for (; l; l = l->next) {
+ address = parse_tokens(l->tok, &l, bc, 1, address, dbg);
+ }
+}
+
+static void find_dupsym() {
+ symbol *root = symbols;
+ symbol *s = symbols;
+ for (; s; s = s->next) {
+ root = symbols;
+ for (int i = 0; root; root = root->next) {
+ if (root == s) {
+ i++;
+ }
+ if (i > 1) {
+ printf("Found duplicate symbol, s->name: %s, root->name: %s\n", s->name, root->name);
+ i = 0;
+ }
+ }
+ }
+}
+
+static symbol *find_fixup(token *t) {
+ fixup* f = fixups;
+ for (; f && t != f->t; f = f->next);
+ return (f && t == f->t) ? f->s : NULL;
+}
+
+
+static void print_symval(symbol *s) {
+ if (s) {
+ if (s->down) {
+ print_symval(s->down);
+ }
+ if (s->name) {
+ printf("s->name: %s, s->val: $%"PRIX64"\n", s->name, s->val);
+ }
+ print_symval(s->next);
+ }
+}
+
+static void print_symtree(symbol *s, int depth) {
+ if (s) {
+ if (s->name != NULL) {
+ for (int i = depth; i; i--) {
+ printf("|%s", (i > 1) ? " " : "--");
+ }
+ printf("%s: $%"PRIX64"\n", s->name, s->val);
+ }
+ if (s->down != NULL) {
+ print_symtree(s->down, depth+1);
+ }
+ print_symtree(s->next, depth);
+ }
+}
+
+void fix_symtree(line *l) {
+ symbol *s = symbols;
+ symbol *cur_sym = NULL;
+ symbol *sym_struct = NULL;
+ symbols = NULL;
+ last_sym = NULL;
+ int islocal = 0;
+ int isanon = 0;
+ int is_struct = 0;
+ int is_structsym = 0;
+ for (; l; l = l->next) {
+ token *t = l->tok;
+ token *lt = NULL;
+ for (; t; t = t->next) {
+ int ismember = (t->id == TOK_MEMBER);
+ switch (t->id) {
+ case TOK_STRUCT:
+ case TOK_UNION : islocal = !(is_struct == 1 && lt && lt->id == TOK_DIR);
+ case TOK_SYM :
+ if (t->id == TOK_SYM && t != l->tok) {
+ break;
+ }
+ case TOK_MEMBER:
+ case TOK_LABEL :
+ if (symbols) {
+ (!islocal && s && !s->up) ? (last_sym = s) : (last_loc = s);
+ }
+ if (((t->type == 1 || ismember) && !islocal) || (islocal && ismember && is_structsym)) {
+ is_structsym = 0;
+ last_loc = NULL;
+ islocal = 1;
+ cur_sym = s;
+ s->down = t->sym;
+ s->down->up = s;
+ s = s->down;
+ if (s) {
+ s->next = NULL;
+ s->prev = NULL;
+ s->down = NULL;
+ }
+ locals = s;
+ } else if ((islocal || t->type == 0)) {
+ if (t->type == 0 && !is_struct && islocal && !ismember) {
+ islocal = 0;
+ if (s) {
+ s->up->down = locals;
+ s = s->up;
+ }
+ }
+ symbol *tmp = s;
+ s = t->sym;
+ if (s) {
+ s->prev = (tmp && tmp != s) ? tmp : NULL;
+ s->up = (s->prev) ? s->prev->up : s->up;
+ }
+ if (s && s->next) {
+ s->next = NULL;
+ }
+ }
+ if (!islocal) {
+ last_loc = NULL;
+ (last_sym) ? (last_sym->next = s) : (symbols = s);
+ cur_sym = s;
+ if (last_sym) {
+ last_sym->next->prev = last_sym;
+ last_sym->next->up = last_sym->up;
+ last_sym->next->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;
+ }
+ }
+ break;
+ case TOK_DIR:
+ if (t->type == DIR_STRUCT || t->type == DIR_UNION) {
+ is_struct++;
+ is_structsym = (t->next && (t->next->id == TOK_STRUCT || t->next->id == TOK_UNION));
+ if ((!is_structsym) || (isanon && is_structsym)) {
+ isanon++;
+ }
+ sym->name = NULL;
+ }
+ s = s->next;
+ free(sym);
+ sym = NULL;
+ free_symbols(s);
+ }
+}
+
+static inline void free_fixups(fixup *f) {
+ fixup *fix;
+ if (f != NULL) {
+ fix = f;
+ f = f->next;
+ free(fix);
+ fix = NULL;
+ free_fixups(f);
+ }
+}
+
+uint64_t get_tokmem(token *t) {
+ uint64_t i = 0;
+ for (; t; t = t->next, i++);
+ return i*sizeof(token);
+}
+
+void get_linemem(line *l) {
+ uint64_t i = 0;
+ uint64_t j = 0;
+ for (; l; j += get_tokmem(l->tok), l = l->next, i++);
+ printf("Bytes per line: %"PRIu64", Bytes per token: %"PRIu64", Total size of line table in bytes: %"PRIu64"\n", sizeof(line), sizeof(token), j+(i*sizeof(line)));
+}
+
+void cleanup() {
+ uint16_t i;
+ if (lines) {
+ /*get_linemem(lines);*/
+ /*fix_symtree(lines);*/
+ free_lines(lines);
+ lines = NULL;
+ }
+ if (symbols) {
+ /*print_symtree(symbols, 0);*/
+ free_symbols(symbols);
+ symbols = NULL;
+ }
+ if (fixups) {
+ free_fixups(fixups);
+ fixups = NULL;
+ }
+ while (i < stridx || i < comidx) {
+ if (i < stridx && string[i]) {
+ free(string[i]);
+ string[i] = NULL;
+ }
+ if (i < comidx && comment[i]) {
+ free(comment[i]);
+ comment[i] = NULL;
+ }
+ i++;
+ }
+}