From 96393257a43ac52f2b911594d106741245dec5f0 Mon Sep 17 00:00:00 2001 From: mrb0nk500 Date: Fri, 4 Dec 2020 15:20:28 -0500 Subject: - Started work on writing the new version of the assembler. - Did alot of stuff in the emulator. - Did alot of stuff in the SuB Suite. --- lexer/backup/assemble.c | 975 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 975 insertions(+) create mode 100644 lexer/backup/assemble.c (limited to 'lexer/backup/assemble.c') 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++; + } +} -- cgit v1.2.3-13-gbd6f