diff options
author | mrb0nk500 <b0nk@b0nk.xyz> | 2020-08-08 18:11:35 -0400 |
---|---|---|
committer | mrb0nk500 <b0nk@b0nk.xyz> | 2020-08-08 18:11:35 -0400 |
commit | f16af793a58a9f398fc598a0c129e3bb90eb61f6 (patch) | |
tree | 2f674574f2955a1bc52ee3a6818516226833ea9b /assemble.c | |
parent | 1ec19679b3db209429b0897f6ccda6d09d018a70 (diff) |
- Refactored the opcode table, in order to make the
instruction formatting simpler.
- Refactored the instruction table of the emulator's
assembler, it now has two parts, the addressing mode
bits, and the base value.
The base value is what's used to generate the actual
opcode, with the addressing mode bits telling the
assembler what addressing modes this instruction
supports.
The reason for doing this was to use less space. For
comparison, the previous version used 870 bytes for
the instruction table, while the new version uses
only 222 bytes. The new version is nearly 4 times
smaller than the pervious version.
- The B register based ALU instructions now use their
own addressing mode, and are specified by using 'b'
as the operand for those instructions.
For example, to add the Accumulator with the B
register, you now use "ADC B" instead of "AAB".
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; |