diff options
author | mrb0nk500 <b0nk@b0nk.xyz> | 2020-12-08 10:42:10 -0500 |
---|---|---|
committer | mrb0nk500 <b0nk@b0nk.xyz> | 2020-12-08 11:16:13 -0500 |
commit | 673efacc37efa90e61eba224efadbb4be863c77b (patch) | |
tree | 9b22d4c8b12a5d5b07329df121a13116cb98c4a1 /assemble.c | |
parent | 96393257a43ac52f2b911594d106741245dec5f0 (diff) |
- Implemented support for the Orthogonal extension into
both the assembler, and the emulator.
I finally figured out how I could get support for the
Ortho extension implemented into the old assembler.
The only reason for doing this, is to buy me some
while I start work on the new assembler, and to help
me get an idea for how to do the same in the new
assembler.
Diffstat (limited to 'assemble.c')
-rw-r--r-- | assemble.c | 587 |
1 files changed, 484 insertions, 103 deletions
@@ -82,6 +82,21 @@ uint8_t get_eind(uint8_t mne, uint8_t dbg) { return 0xFF; } +uint8_t get_ext_ortho(uint8_t mne, uint8_t dbg) { + switch (mne) { + case LEA: return OP_LEA; + case PEA: return OP_PEA; + case ADD: return OP_ADD; + case SUB: return OP_SUB; + case NOT: return OP_NOT; + case CLZ: return OP_CLZ; + case CLO: return OP_CLO; + case SWP: return OP_SWP; + case PCN: return OP_PCN; + } + return 0xFF; +} + static void write_value(uint64_t value, uint64_t address, uint8_t size) { if (address < mem_size) { size = (size > 7) ? 7 : size; @@ -98,16 +113,23 @@ static void write_value(uint64_t value, uint64_t address, uint8_t size) { } } -uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) { +uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t end_expr, uint8_t stop_comma, uint8_t dbg) { uint64_t value = 0; uint64_t tmp_val = 0; uint8_t type = EXPR_NONE; uint8_t isstart = 1; + int done = 0; do { if (t->id == TOK_EXPR) { type = t->type; t = t->next; } + if (stop_comma && t->subtype == TOK_CSV) { + done = 1; + } + if (stop_comma && t->id == TOK_REG) { + break; + } switch (t->id) { case TOK_HEX: case TOK_DEC: @@ -119,6 +141,10 @@ uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) { tmp_val = (t->sym) ? t->sym->val : addr; t = t->next; break; + default: tmp_val = 0; + } + if (end_expr != 0xFF && type == end_expr) { + break; } switch (type) { case EXPR_PLUS : (isstart) ? (value = tmp_val) : (value += tmp_val); break; @@ -150,13 +176,19 @@ uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) { 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)); + } while (!done && t && t->id == TOK_EXPR && isexpr(t->type, dbg)); return value; } -token *skip_expr(token *t, uint8_t dbg) { +token *skip_expr(token *t, uint8_t end_expr, uint8_t stop_comma, uint8_t dbg) { + int done = 0; + int is_reg = 0; do { - t = (t->id == TOK_EXPR) ? t->next : t; + is_reg = (t && t->next && t->next->id == TOK_REG); + t = (t->id == TOK_EXPR && !is_reg) ? t->next : t; + if (is_reg || (stop_comma && (t->subtype == TOK_CSV))) { + done = 1; + } switch (t->id) { case TOK_HEX : case TOK_DEC : @@ -165,7 +197,10 @@ token *skip_expr(token *t, uint8_t dbg) { case TOK_SYM : case TOK_LABEL: t = t->next; break; } - } while (t && t->id == TOK_EXPR && isexpr(t->type, dbg)); + if (end_expr != 0xFF && t->id == TOK_EXPR && t->type == end_expr) { + break; + } + } while (!done && t && t->id == TOK_EXPR && isexpr(t->type, dbg)); return t; } @@ -227,7 +262,7 @@ uint16_t handle_struct(line **ln, uint64_t address, uint16_t offset, uint8_t dbg 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; + 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; @@ -270,7 +305,7 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre case TOK_CHAR: case TOK_SYM: case TOK_LABEL: - val.u64 = get_val(t, tmpaddr, get_directivesize(type, dbg), dbg); + 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; @@ -281,7 +316,7 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre tmpaddr += tmp; bc->datasize += tmp; if (t->next && t->next->id == TOK_EXPR && isexpr(t->next->type, dbg)) { - t = skip_expr(t, dbg); + t = skip_expr(t, 0xFF, 0, dbg); } break; case TOK_STRING: @@ -323,9 +358,13 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre 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) { +static uint8_t write_inst(uint8_t prefix, uint8_t ext_prefix, uint8_t opcode, operand *op, uint64_t address, uint8_t *op_size, uint8_t isasm, uint8_t dbg) { uint8_t inst_size = 0; + uint8_t op_ins_size[2]; union reg ins; + union reg op_ins[2]; + memset(op_ins_size, 0, sizeof(op_ins_size)); + memset(op_ins, 0, sizeof(op_ins_size)); if (prefix & 3) { ins.u8[inst_size++] = prefix; } @@ -333,16 +372,216 @@ static uint8_t write_inst(uint8_t prefix, uint8_t ext_prefix, uint8_t opcode, ui ins.u8[inst_size++] = ext_prefix; } ins.u8[inst_size++] = opcode; + if (ext_prefix == 0x1D) { + for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { + ins.u8[inst_size] |= (op[i].id << (!i*4)); + } + inst_size++; + for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { + int is_sib = 0; + if (op[i].type == 1) { + int reg = 0; + switch (op[i].id) { + case MEM_SIB : op_ins[i].u8[op_ins_size[i]++] = op[i].scale; /* Falls through. */ + case MEM_ABSR : + case MEM_ARIND: + case MEM_AINDR: + case MEM_ZMR : + case MEM_ZRIND: + case MEM_ZINDR: + case MEM_RIND : + op_ins[i].u8[op_ins_size[i]] = op[i].rind[reg]; + reg = (op[i].rind[1] != 0xFF); + op_ins[i].u8[op_ins_size[i]++] |= op[i].rind[reg] << 4; + break; + } + } + } + } if (isasm) { + if (dbg) { + printf("$%04"PRIX64":\t", address); + for (int i = 0; i < inst_size; i++) { + printf("%02X", ins.u8[i]); + if (i < inst_size-1) { + putchar(' '); + } + } + } write_value(ins.u64, address, inst_size-1); - if (size) { - write_value(value, address+inst_size, size-1); + } + for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { + if (op[i].type == 1) { + if (ext_prefix == 0x1D && op_ins_size[i]) { + if (isasm) { + if (dbg) { + putchar(' '); + for (int j = 0; j < op_ins_size[i]; j++) { + printf("%02X", op_ins[i].u8[j]); + if (j < op_ins_size[i]-1) { + putchar(' '); + } + } + } + write_value(op_ins[i].u64, address+inst_size, op_ins_size[i]-1); + } + inst_size += op_ins_size[i]; + } + if (op_size[i] && (ext_prefix != 0x1D || (ext_prefix == 0x1D && op[i].id != MEM_SIB && op[i].id != MEM_RIND))) { + if (isasm) { + if (dbg) { + uint8_t *tmp = (uint8_t *)&op[i].value; + putchar(' '); + for (int j = 0; j < op_size[i]; j++) { + printf("%02X", tmp[j]); + if (j < op_size[i]-1) { + putchar(' '); + } + } + } + write_value(op[i].value, address+inst_size, op_size[i]-1); + } + inst_size += op_size[i]; + } } } - inst_size += size; + if (isasm && dbg) { + putchar('\n'); + } return inst_size; } +token *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 = t->id; + op_inst = t->byte; + t = t->next; + break; + }*/ + int i = 0; + int old_i = -1; + uint8_t expr_type = 0xFF; + uint8_t stop_comma = 0; + uint64_t value = 0; + uint8_t reg = 0; + uint8_t got_value = 0; + uint8_t is_sib = 0; + uint8_t brack_done = 0; + uint8_t is_comma = 0; + token *tmp = t; + /*for (; tmp; tmp = tmp->next) { + printf("t: %p, t->id: $%X, t->id: %s, t->subtype: $%X, t->subtype: %s\n", tmp, tmp->id, (tmp->id <= TOK_MEMBER) ? lex_tok[tmp->id] : "TOK_NONE", tmp->subtype, (tmp->subtype == TOK_IND || tmp->subtype == TOK_CSV) ? lex_tok[tmp->subtype] : "TOK_NONE"); + }*/ + + for (; t && i < 2; t = t->next) { + if (t->subtype == TOK_IND) { + brack_done = 1; + } + switch (t->id) { + case TOK_HEX : + case TOK_DEC : + case TOK_BIN : + case TOK_SYM : + case TOK_CHAR : + 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_comma = 1; break; + case EXPR_MUL : stop_comma = 0; break; + } + is_sib = (!stop_comma && op[i].type && op[i].id == MEM_IND); + value = get_val(t, address, (rs != 0xFF) ? rs : 0, (!stop_comma) ? expr_type : 0xFF, stop_comma, dbg); + op[i].value = (!is_sib) ? value : op[i].value; + got_value = 1; + } else { + op[i].value = (!is_sib) ? value : op[i].value; + got_value = 0; + } + if ((op[i].type == 1 && op[i].id == MEM_RIND) || (!op[i].type)) { + op[i].is_ind = (op[i].type == 1 && op[i].id == MEM_RIND); + op[i].type = 1; + op[i].rind[0] = (op[i].rind[0] == 0xFF) ? op[i].id : op[i].rind[0]; + op[i].id = MEM_ZMR; + } + is_comma += (t && (t->subtype == TOK_CSV || (t->next && t->next->subtype == TOK_CSV))); + is_comma = (is_comma >= 2) ? 0 : is_comma; + /* Falls Through. */ + case TOK_MEM: + is_comma = (t->id == TOK_MEM) ? 0 : is_comma; + if (old_i != i) { + op[i].type = 1; /* Set type to memory. */ + op[i].id = (t->id == TOK_MEM) ? t->type : 0xFF; + op[i].id = (is_sib) ? MEM_SIB : op[i].id; + op[i].scale = (is_sib) ? value : op[i].scale; + old_i = i; + } else { + if (!op[i].type && !is_sib) { + op[i].type = 1; + op[i].id = MEM_ZMR; + } + } + if (got_value && !is_comma) { + if (t && t->subtype != TOK_CSV) { + t = skip_expr(t, (!stop_comma) ? expr_type : 0xFF, stop_comma, dbg); + } + } + i += is_comma; + if (old_i != i) { + got_value = 0; + } + 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 { + if (op[i].type == 1) { + if (op[i].id == MEM_IND) { + op[i].id = (!brack_done && got_value) ? MEM_ZRIND : MEM_RIND; + op[i].id = (brack_done && got_value) ? MEM_ZINDR : op[i].id; + brack_done = 0; + } else { + op[i].id = (got_value) ? MEM_ZMR : op[i].id; + } + op[i].rind[reg] = t->type; + reg++; + reg = (reg > 1) ? 0 : reg; + } + } + is_comma += (t && (t->subtype == TOK_CSV || (t->next && t->next->subtype == TOK_CSV))); + is_comma = (is_comma >= 2) ? 0 : is_comma; + i += is_comma; + break; + case TOK_EXPR: + expr_type = t->type; + switch (expr_type) { + default : stop_comma = 1; break; + case EXPR_MUL : stop_comma = 0; break; + } + if (!got_value) { + if (t->next && t->next->id != TOK_REG) { + value = get_val(t, address, (rs != 0xFF) ? rs : 0, (!stop_comma) ? expr_type : 0xFF, stop_comma, dbg); + got_value = 1; + } + } else { + got_value = 0; + } + break; + } + if (!t) { + break; + } + } + return t; +} + uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg) { union reg val; uint8_t opsize; @@ -352,44 +591,66 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t ext_prefix = 0; uint8_t type; uint32_t am = 0; - uint8_t tmp = 0; + uint8_t op_size[2]; uint8_t prefix = 0; uint8_t rs = 0; uint8_t of = 0; uint8_t tmp_prefix = 0; uint8_t inst_size = 0; + int is_ortho = 0; val.u64 = 0; instruction ins; - - for (; t; t = t->next) { - if (t->id == TOK_OPCODE || t->id == TOK_EXTOP) { + operand op[2]; + memset(op, 0xFF, sizeof(op)); + op_size[0] = 0; + op_size[1] = 0; + if (t) { + if (t->id == TOK_OPCODE || t->id == TOK_EXTOP || t->id == TOK_ORTHO) { id = t->id; instr = t->byte; type = t->type; } else { - break; + return address; } - tmp = 0; + /*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; + is_ortho = (t->next->id == TOK_OS); + t = (is_ortho) ? 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 (dbg) { + for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { + printf("%i: op.type: %u, op.id: $%X, op.scale; $%X, op.rind[0]: $%X, op.rind[1]: $%X, op.value: $%"PRIX64"\n", i, op[i].type, op[i].id, op[i].scale, op[i].rind[0], op[i].rind[1], op[i].value); + } + } + uint8_t is_eind = (op[0].type == 1 && op[0].id == MEM_RIND && op[0].rind[0] == REG_E); + uint8_t is_mem = (op[0].type == 1 && op[0].id != MEM_IMM); + uint8_t is_idx = (is_mem && !op[1].type && (op[1].id == REG_X || op[1].id == REG_Y)); + of = (is_mem && (op[0].id == MEM_RIND || op[0].id == MEM_ZMR) && op[0].rind[0] == REG_SP) ? 1 : of; 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 = ((!t->next || (t->next->id == TOK_COMMENT)) && type == 0xFF); - ins = (id == TOK_OPCODE) ? inst[instr] : ext_inst[instr]; + 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; - if (id == TOK_EXTOP || (id == TOK_OPCODE && type == EIND)) { + if (id == TOK_EXTOP || (id == TOK_OPCODE && is_eind)) { ext_prefix = 0x0D; } if ((am & AM_IMPL) && isimplied) { @@ -398,12 +659,6 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, if (ins.am & AM_REL) { type = REL; } - if (t->next) { - t = t->next; - } - if (type != BREG && type != EIND) { - val.u64 = get_val(t, address, (rs != 0xFF) ? rs : 0, dbg); - } } opcode = ins.op; uint64_t saveaddr = address; @@ -411,62 +666,73 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t i = 0; uint8_t j = 1; uint8_t type2 = 0xFF; - switch (type) { - case BREG: - case IMPL: - case EIND: - 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)) { - 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; + if (!is_ortho) { + is_ortho = (id == TOK_ORTHO); + } + int is_valid = 1; + if (!is_ortho && (is_mem || is_idx)) { + switch (op[0].id) { + case MEM_AINDR: + case MEM_ZINDR: + case MEM_ARIND: + case MEM_ZRIND: + case MEM_SIB : is_valid = 0; break; + case MEM_ZMR : + case MEM_ABSR : + case MEM_RIND : + default : + if (is_mem && !op[1].type && op[1].id != REG_X && op[1].id != REG_Y) { + is_valid = 0; + } else if (op[0].id == MEM_ZMR || op[0].id == MEM_ABSR || op[0].id == MEM_RIND) { + is_valid = (of != 0xFF || op[0].rind[0] == REG_SP); + } else if (is_mem && op[1].type == 1) { + is_valid = 0; } - } - break; - default: + break; + } + } else if (is_ortho) { + is_valid = 0; + } + if (type == IMPL && (am & AM_IMPL)) { + if (id == TOK_OPCODE && instr == CPS) { + rs = 0; + } + opcode = opcode; + is_ortho = 0; + } else if (type == REL) { + rs = (rs != 0xFF) ? rs : 0; + op_size[0] = (1 << rs); + uint64_t max_sign = 0; + uint8_t offset = 1; + uint64_t tmp_val; + tmp_val = op[0].value; + offset += (prefix != 0); + tmp_val -= offset+op_size[0]; + 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); + op_size[0] = (1 << rs); + tmp_val = op[i].value; + tmp_val -= offset+op_size[0]; + tmp_val -= address; + prefix = ((rs << 4) | 3); + } + op[0].value = tmp_val; + is_ortho = 0; + } else if (id != TOK_ORTHO) { + if (!is_eind && is_valid && (is_mem || is_idx)) { 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)) { + if ((int64_t)op[0].value >= ~(int64_t)(max_val) || (int64_t)op[0].value <= (int64_t)(max_val)) { opsize = j; break; } @@ -474,12 +740,20 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, } else { for (; i <= 64; i += 8, j++) { max_val |= (0xFF << i); - if (val.u64 <= max_val) { + if (op[0].value <= max_val) { opsize = j; break; } } } + if (is_idx) { + switch (op[1].id) { + case REG_X: type = (op[0].id == MEM_IND || (of == 1 && op[0].id == MEM_ZMR && op[0].is_ind)) ? INDX : ZMX; break; + case REG_Y: type = (op[0].id == MEM_IND || (of == 1 && op[0].id == MEM_ZMR && op[0].is_ind)) ? INDY : ZMY; break; + } + } else { + type = (op[0].id == MEM_IND || (of == 1 && op[0].id == MEM_ZMR && op[0].is_ind)) ? IND : 0xFF; + } type2 = type; if (type == 0xFF || (id == TOK_EXTOP && type2 != 0xFF)) { switch (opsize-1) { @@ -520,71 +794,192 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, opcode += 0x04; } else if (am & AM_ZM2) { opcode += 0x20; + } else { + is_ortho = 1; } break; case ZMX: if (am & AM_ZMX) { opcode += (id == TOK_OPCODE) ? 0x06 : 0x54; + } else { + is_ortho = 1; } break; case ZMY: if (am & AM_ZMY) { opcode += 0x14; + } else { + is_ortho = 1; } break; case INDX: if (am & AM_INDX) { opcode += (id == TOK_OPCODE) ? 0x16 : 0x94; break; + } else { + is_ortho = 1; } /* 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 { + } else if (id = TOK_EXTOP) { opcode += (type == IND) ? 0x44 : 0x84; + } else { + is_ortho = 1; } break; case ABS: if (am & AM_ABS) { opcode += 0x10; + } else { + is_ortho = 1; } break; case ABSX: if (am & AM_ABX) { opcode += 0x50; + } else { + is_ortho = 1; } break; case ABSY: if (am & AM_ABY) { opcode += 0x00; + } else { + is_ortho = 1; } break; case AIND: if (am & AM_AIND) { opcode += 0x40; + } else { + is_ortho = 1; } break; case AINDX: if (am & AM_AINDX) { opcode += 0x90; + } else { + is_ortho = 1; } break; case AINDY: if (am & AM_AINDY) { opcode += 0x80; + } else { + is_ortho = 1; } break; } - tmp = opsize; + op_size[0] = opsize; } - break; + + } else if (op[1].type == 0xFF) { + if (!op[0].type) { + if (op[0].id == REG_B && (am & AM_BREG)) { + opcode += 0x14; + } else if (op[0].id == REG_A && (am & AM_IMPL)) { + opcode = opcode; + } else { + is_ortho = 1; + } + } else { + if (is_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; + } + } else if ((op[0].id == MEM_IMM) && (am & AM_IMM)) { + rs = (rs != 0xFF) ? rs : 0; + op_size[0] = (1 << rs); + } else { + is_ortho = 1; + } + } + } else { + is_ortho = 1; + } + } + if (is_ortho) { + ext_prefix = 0x1D; + if (id == TOK_EXTOP) { + opcode = ext_ortho_ops[get_ext_ortho(instr, dbg)]; + } + for (int i = 0; i < 2 && op[i].type != 0xFF; i++) { + int i2 = 0; + int j = 0; + (op[i].type == 1) ? (opcode |= (1 << (3+!i))) : (opcode &= ~(1 << (3+!i))); + if (op[i].type == 1 && (am & AM_ORTHO|AM_ORTHO2)) { + switch (op[i].id) { + case MEM_RIND: break; + case MEM_IMM: + rs = (rs != 0xFF) ? rs : 0; + op_size[i] = (1 << rs); + break; + case MEM_ZRIND: + case MEM_ZINDR: + case MEM_ZMR: + case MEM_IND: + default: + if (of != 0xFF) { + max_val = 0; + for (i2 = 8, j = 1; i2 <= 64; i2 += 8, j++) { + max_val |= ((uint64_t)1 << (i2-1)); + if ((int64_t)op[i].value >= ~(int64_t)(max_val) || (int64_t)op[i].value <= (int64_t)(max_val)) { + opsize = j; + break; + } + } + } else { + max_val = 0; + for (i2 = 0, j = 1; i2 <= 64; i2 += 8, j++) { + max_val |= (0xFF << i2); + if (op[i].value <= max_val) { + opsize = j; + break; + } + } + } + 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 (op[i].id) { + case MEM_IND : op[i].id = (type == ABS) ? MEM_AIND : op[i].id; break; + case MEM_ZMR : op[i].id = (type == ABS) ? MEM_ABSR : op[i].id; break; + case MEM_ZRIND: op[i].id = (type == ABS) ? MEM_ARIND : op[i].id; break; + case MEM_ZINDR: op[i].id = (type == ABS) ? MEM_AINDR : op[i].id; break; + case 0xFF : op[i].id = (type == ABS) ? MEM_ABS : MEM_ZM; break; + } + if (opsize) { + uint8_t is_abs = (type == ABS); + if (!is_abs) { + switch (opsize) { + case 2: opsize = 3; break; + case 5: opsize = 6; break; + } + } + prefix |= amp[opsize-1]; + } + op_size[i] = opsize; + if (isasm /*&& dbg*/) { + printf("op_size[%i]: %i, opsize: %u\n", i, op_size[i], opsize); + } + break; + } + } + } } - inst_size = write_inst(prefix, ext_prefix, opcode, val.u64, address, tmp, isasm, dbg); + inst_size = write_inst(prefix, ext_prefix, opcode, op, address, op_size, isasm, /*dbg*/isasm); address += inst_size; bc->progsize += inst_size; + if (isasm /*&& dbg*/) { + printf("inst_size: $%X, bc->progsize: $%"PRIX64"\n", inst_size, bc->progsize); + } } return address; } @@ -596,14 +991,15 @@ uint64_t parse_tokens(token *t, line **l, bytecount *bc, uint8_t isasm, uint64_t 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_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_ORTHO : case TOK_EXTOP : case TOK_OPCODE: address = handle_opcode(t, bc, isasm, address, dbg); break; case TOK_COMMENT: break; @@ -618,6 +1014,7 @@ token *make_token(uint8_t id, uint8_t type, uint8_t space, uint8_t tab, uint64_t new_tok->id = id; new_tok->type = type; + new_tok->subtype = 0xFF; new_tok->tab = tab; new_tok->space = space; @@ -806,29 +1203,13 @@ void fix_symtree(line *l) { if ((!is_structsym) || (isanon && is_structsym)) { isanon++; } - } else if (t->type == DIR_ENDSTRUCT || t->type == DIR_ENDUNION) { - is_struct--; - int skip = 0; - if (isanon > 0) { - if ((cur_sym->up && !cur_sym->up->isanon) || (sym_struct && sym_struct->isanon)) { - isanon--; - } - skip = (!isanon); - } - if ((int)(is_struct-isanon) > 0 && !skip && cur_sym->up) { - for (sym_struct = s->up; sym_struct->prev && !sym_struct->isanon; sym_struct = sym_struct->prev); - s = s->up; - cur_sym = (cur_sym->up != NULL) ? cur_sym->up : s; - } } break; } - lt = t; } } } - static inline void free_tokens(token *t) { token *tok; if (t != NULL) { |