summaryrefslogtreecommitdiff
path: root/assemble.c
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-08-08 18:11:35 -0400
committermrb0nk500 <b0nk@b0nk.xyz>2020-08-08 18:11:35 -0400
commitf16af793a58a9f398fc598a0c129e3bb90eb61f6 (patch)
tree2f674574f2955a1bc52ee3a6818516226833ea9b /assemble.c
parent1ec19679b3db209429b0897f6ccda6d09d018a70 (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.c211
1 files changed, 141 insertions, 70 deletions
diff --git a/assemble.c b/assemble.c
index 8100485..ed56cc8 100644
--- a/assemble.c
+++ b/assemble.c
@@ -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;