summaryrefslogtreecommitdiff
path: root/assemble.c
diff options
context:
space:
mode:
Diffstat (limited to 'assemble.c')
-rw-r--r--assemble.c587
1 files changed, 484 insertions, 103 deletions
diff --git a/assemble.c b/assemble.c
index 297be87..87d0464 100644
--- a/assemble.c
+++ b/assemble.c
@@ -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) ? 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) {