summaryrefslogtreecommitdiff
path: root/assemble.c
diff options
context:
space:
mode:
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;