diff options
Diffstat (limited to 'assemble.c')
-rw-r--r-- | assemble.c | 211 |
1 files changed, 141 insertions, 70 deletions
@@ -14,7 +14,7 @@ uint8_t isexpr(uint8_t type, uint8_t dbg) { } } -uint8_t get_rs(token *t, uint8_t inst, uint8_t dbg) { +uint8_t get_rs(token *t, uint8_t dbg) { if (t->id == TOK_RS) { return t->type; } else { @@ -30,6 +30,31 @@ uint8_t get_of(token *t, uint8_t dbg) { } } +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; +} + uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) { uint64_t value = 0; uint64_t tmp_val = 0; @@ -172,9 +197,10 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre 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 inst; + uint8_t instr; uint8_t opcode; uint8_t type; + uint16_t am = 0; uint8_t tmp = 0; uint8_t prefix = 0; uint8_t rs = 0; @@ -183,7 +209,7 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, for (; t; t = t->next) { if (t->id == TOK_OPCODE) { - inst = t->byte; + instr = t->byte; type = t->type; } else { break; @@ -192,7 +218,7 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, opsize = 1; opcode = 0; if (t->next) { - rs = get_rs(t->next, inst, dbg); + rs = get_rs(t->next, dbg); t = (rs != 0xFF) ? t->next : t; if (t->next) { of = get_of(t->next, dbg); @@ -204,12 +230,13 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, tmp_prefix |= (of != 0xFF) ? (of << 2) : tmp_prefix; } prefix = (tmp_prefix) ? ((tmp_prefix << 4) | 3) : 0; - uint8_t isincdec = (inst == INC || inst == DEC); + uint8_t isincdec = (instr == INC || instr == DEC); uint8_t isimplied = (!t->next || (t->next->id == TOK_COMMENT)); - if (opcodes[inst][IMPL] != 0xFF && isimplied) { + am = inst[instr].am; + if ((am & AM_IMPL) && isimplied) { type = IMPL; } else { - if (opcodes[inst][REL] != 0xFF) { + if (inst[instr].am & AM_REL) { type = REL; } if (t->next) { @@ -217,78 +244,85 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, } val.u64 = get_val(t, address, (rs != 0xFF) ? rs : 0, dbg); } - opcode = opcodes[inst][type]; /* Special case for TXS. */ - if (inst == TXS) { + if (instr == TXS) { if (type == IMM) { rs = 1; } else { type = IMPL; - opcode = opcodes[inst][IMM]; } } + opcode = inst[instr].op; uint64_t saveaddr = address; uint64_t max_val = 0; uint8_t i = 0; uint8_t j = 1; switch (type) { + case BREG: case IMPL: - if (prefix) { + if (instr == CPS) { + rs = 0; + } + if ((am & (AM_IMPL|AM_BREG))) { + if ((am & AM_IMPL) && (prefix)) { + if (isasm) { + addr[address] = prefix; + } + address++; + bc->progsize++; + } if (isasm) { - addr[address] = prefix; + addr[address] = (am & AM_BREG) ? opcode+0x14 : opcode; } address++; bc->progsize++; } - if (isasm) { - addr[address] = opcode; - } - address++; - bc->progsize++; break; case REL: case IMM: - 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); + 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; - prefix = ((rs << 4) | 3); + 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 (prefix) { + if (isasm) { + addr[address] = prefix; + } + address++; + bc->progsize++; } - val.u64 = tmp_val; - } - if (prefix) { if (isasm) { - addr[address] = prefix; + addr[address] = opcode; } address++; bc->progsize++; - } - if (isasm) { - addr[address] = opcode; - } - address++; - bc->progsize++; - if (isasm) { - setreg(addr, +, address, val.u8, +, 0, tmp-1); + if (isasm) { + setreg(addr, +, address, val.u8, +, 0, tmp-1); + } } break; default: @@ -325,32 +359,69 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address, } prefix |= amp[opsize-1]; } - if (prefix) { + if (am & (AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_INDX2|AM_ZM2)) { + 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 += 0x06; + } + break; + case ZMY: + if (am & AM_ZMY) { + opcode += 0x14; + } + break; + case ABS: + if (am & AM_ABS) { + opcode += 0x10; + } + break; + case INDX: + if (am & AM_INDX) { + opcode += 0x16; + break; + } + /* Falls Through. */ + case IND: + case INDY: + if (am & (AM_IND|AM_INDY|AM_INDX2)) { + opcode = ind_ops[get_ind(instr, type, dbg)]; + } + break; + } + if (prefix) { + if (isasm) { + addr[address] = prefix; + } + address++; + bc->progsize++; + } if (isasm) { - addr[address] = prefix; + addr[address] = opcode; } address++; bc->progsize++; - } - opcode = opcodes[inst][type]; - if (isasm) { - addr[address] = opcode; - } - address++; - bc->progsize++; - if (isasm) { - switch (opsize-1) { - case 7: addr[address+7] = val.u8[7]; - case 6: addr[address+6] = val.u8[6]; - case 5: addr[address+5] = val.u8[5]; - case 4: addr[address+4] = val.u8[4]; - case 3: addr[address+3] = val.u8[3]; - case 2: addr[address+2] = val.u8[2]; - case 1: addr[address+1] = val.u8[1]; - case 0: addr[address ] = val.u8[0]; + if (isasm) { + switch (opsize-1) { + case 7: addr[address+7] = val.u8[7]; + case 6: addr[address+6] = val.u8[6]; + case 5: addr[address+5] = val.u8[5]; + case 4: addr[address+4] = val.u8[4]; + case 3: addr[address+3] = val.u8[3]; + case 2: addr[address+2] = val.u8[2]; + case 1: addr[address+1] = val.u8[1]; + case 0: addr[address ] = val.u8[0]; + } } + tmp = opsize; } - tmp = opsize; break; } address += tmp; |