summaryrefslogtreecommitdiff
path: root/assemble.c
diff options
context:
space:
mode:
authormrb0nk500 <b0nk@b0nk.xyz>2020-11-20 15:10:24 -0500
committermrb0nk500 <b0nk@b0nk.xyz>2020-11-20 15:10:24 -0500
commit83ce1151ee1f06ae6b1c5c1018cc2489494e5ea4 (patch)
treeba4edade46c57ec5119d01ab8a7ad9f7943c6804 /assemble.c
parentdc7ebb9d424bb39d59f09b8498746beb871c46f4 (diff)
- Implemented support for Sux's base extension.
This is the biggest milestone I've reached for this project, since the base extension changes alot about what Sux can do by default, and now makes it a viable instruction set for modern day use, when compared with other instruction sets.
Diffstat (limited to 'assemble.c')
-rw-r--r--assemble.c261
1 files changed, 156 insertions, 105 deletions
diff --git a/assemble.c b/assemble.c
index 8d7eb85..297be87 100644
--- a/assemble.c
+++ b/assemble.c
@@ -1,5 +1,13 @@
#include "asmmon.h"
+#define AM_ADDR (AM_ZM | AM_ZMX | AM_ZMY | \
+ AM_IND | AM_INDX | AM_INDY | \
+ AM_ABS | AM_ABX | AM_ABY | \
+ AM_AIND | AM_AINDX | AM_AINDY | \
+ AM_INDX2 | AM_ZM2)
+
+static const uint64_t mem_size = 0x04000000; /* Size of address space. */
+
token *tok_global;
uint8_t isexpr(uint8_t type, uint8_t dbg) {
@@ -58,6 +66,38 @@ uint8_t get_ind(uint8_t mne, uint8_t am, uint8_t dbg) {
return base_idx + offset;
}
+uint8_t get_eind(uint8_t mne, uint8_t dbg) {
+ switch (mne) {
+ case DEC: return DEC_EIND;
+ case INC: return INC_EIND;
+ case STY: return STY_EIND;
+ case STA: return STA_EIND;
+ case STB: return STB_EIND;
+ case LDX: return LDX_EIND;
+ case STX: return STX_EIND;
+ case CPB: return CPB_EIND;
+ case CPX: return CPX_EIND;
+ case CPY: return CPY_EIND;
+ }
+ return 0xFF;
+}
+
+static void write_value(uint64_t value, uint64_t address, uint8_t size) {
+ if (address < mem_size) {
+ size = (size > 7) ? 7 : size;
+ #if 1
+ if (size < 7) {
+ uint64_t mask = (-(uint64_t)1 >> ((7 - size) * 8));
+ *(uint64_t *)(addr+address) = (*(uint64_t *)(addr+address) & ~mask) | (value & mask);
+ } else {
+ *(uint64_t *)(addr+address) = value;
+ }
+ #else
+ memcpy(addr+address, &value, size+1);
+ #endif
+ }
+}
+
uint64_t get_val(token *t, uint64_t addr, uint8_t size, uint8_t dbg) {
uint64_t value = 0;
uint64_t tmp_val = 0;
@@ -232,34 +272,14 @@ uint64_t handle_directive(token *t, bytecount *bc, uint8_t isasm, uint64_t addre
case TOK_LABEL:
val.u64 = get_val(t, tmpaddr, get_directivesize(type, dbg), dbg);
switch (type) {
- case DIR_QWORD: /* Falls through. */
- if (isasm) {
- addr[tmpaddr+7] = val.u8[7];
- addr[tmpaddr+6] = val.u8[6];
- addr[tmpaddr+5] = val.u8[5];
- addr[tmpaddr+4] = val.u8[4];
- }
- tmp += 4;
- case DIR_DWORD: /* Falls through. */
- if (isasm) {
- addr[tmpaddr+3] = val.u8[3];
- addr[tmpaddr+2] = val.u8[2];
- }
- tmp += 2;
- case DIR_WORD: /* Falls through. */
- if (isasm) {
- addr[tmpaddr+1] = val.u8[1];
- }
- tmp++;
- case DIR_BYTE:
- if (isasm) {
- addr[tmpaddr ] = val.u8[0];
- }
- tmp++;
- tmpaddr += tmp;
- bc->datasize += tmp;
- break;
+ case DIR_QWORD: tmp = 8; break;
+ case DIR_DWORD: tmp = 4; break;
+ case DIR_WORD : tmp = 2; break;
+ case DIR_BYTE : tmp = 1; break;
}
+ write_value(val.u64, tmpaddr, tmp-1);
+ tmpaddr += tmp;
+ bc->datasize += tmp;
if (t->next && t->next->id == TOK_EXPR && isexpr(t->next->type, dbg)) {
t = skip_expr(t, dbg);
}
@@ -303,21 +323,47 @@ 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) {
+ uint8_t inst_size = 0;
+ union reg ins;
+ if (prefix & 3) {
+ ins.u8[inst_size++] = prefix;
+ }
+ if ((ext_prefix & 0x0D) == 0x0D) {
+ ins.u8[inst_size++] = ext_prefix;
+ }
+ ins.u8[inst_size++] = opcode;
+ if (isasm) {
+ write_value(ins.u64, address, inst_size-1);
+ if (size) {
+ write_value(value, address+inst_size, size-1);
+ }
+ }
+ inst_size += size;
+ return inst_size;
+}
+
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 id;
uint8_t instr;
uint8_t opcode;
+ uint8_t ext_prefix = 0;
uint8_t type;
- uint16_t am = 0;
+ uint32_t am = 0;
uint8_t tmp = 0;
uint8_t prefix = 0;
uint8_t rs = 0;
uint8_t of = 0;
uint8_t tmp_prefix = 0;
+ uint8_t inst_size = 0;
+ val.u64 = 0;
+ instruction ins;
for (; t; t = t->next) {
- if (t->id == TOK_OPCODE) {
+ if (t->id == TOK_OPCODE || t->id == TOK_EXTOP) {
+ id = t->id;
instr = t->byte;
type = t->type;
} else {
@@ -340,51 +386,47 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
}
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));
- am = inst[instr].am;
+ uint8_t isimplied = ((!t->next || (t->next->id == TOK_COMMENT)) && type == 0xFF);
+ ins = (id == TOK_OPCODE) ? inst[instr] : ext_inst[instr];
+ am = ins.am;
+ if (id == TOK_EXTOP || (id == TOK_OPCODE && type == EIND)) {
+ ext_prefix = 0x0D;
+ }
if ((am & AM_IMPL) && isimplied) {
type = IMPL;
} else {
- if (inst[instr].am & AM_REL) {
+ if (ins.am & AM_REL) {
type = REL;
}
if (t->next) {
t = t->next;
}
- val.u64 = get_val(t, address, (rs != 0xFF) ? rs : 0, dbg);
- }
- /* Special case for TXS. */
- if (instr == TXS) {
- if (type == IMM) {
- rs = 1;
- } else {
- type = IMPL;
+ if (type != BREG && type != EIND) {
+ val.u64 = get_val(t, address, (rs != 0xFF) ? rs : 0, dbg);
}
}
- opcode = inst[instr].op;
+ opcode = ins.op;
uint64_t saveaddr = address;
uint64_t max_val = 0;
uint8_t i = 0;
uint8_t j = 1;
+ uint8_t type2 = 0xFF;
switch (type) {
case BREG:
case IMPL:
- if (instr == CPS) {
+ case EIND:
+ if (id == TOK_OPCODE && instr == CPS) {
rs = 0;
}
- if ((am & (AM_IMPL|AM_BREG))) {
- if ((am & AM_IMPL) && (prefix)) {
- if (isasm) {
- addr[address] = prefix;
+ 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;
}
- address++;
- bc->progsize++;
}
- if (isasm) {
- addr[address] = (am & AM_BREG) ? opcode+0x14 : opcode;
- }
- address++;
- bc->progsize++;
+ opcode = (am & AM_BREG) ? opcode+0x14 : opcode;
}
break;
case REL:
@@ -417,21 +459,6 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
}
val.u64 = tmp_val;
}
- if (prefix) {
- if (isasm) {
- addr[address] = prefix;
- }
- address++;
- bc->progsize++;
- }
- if (isasm) {
- addr[address] = opcode;
- }
- address++;
- bc->progsize++;
- if (isasm) {
- setreg(addr, +, address, val.u8, +, 0, tmp-1);
- }
}
break;
default:
@@ -453,14 +480,32 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
}
}
}
- if (type == 0xFF) {
+ type2 = type;
+ if (type == 0xFF || (id == TOK_EXTOP && type2 != 0xFF)) {
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 (type2) {
+ case ZMX : type = (type == ABS) ? ABSX : type2; break;
+ case ZMY : type = (type == ABS) ? ABSY : type2; break;
+ case IND : type = (type == ABS) ? AIND : type2; break;
+ case INDX: type = (type == ABS) ? AINDX : type2; break;
+ case INDY: type = (type == ABS) ? AINDY : type2; break;
+ }
if (opsize) {
- if (type != ABS) {
+ uint8_t is_abs = 0;
+ switch (type) {
+ case ABS :
+ case ABSX :
+ case ABSY :
+ case AIND :
+ case AINDX:
+ case AINDY: is_abs = 1; break;
+
+ }
+ if (!is_abs || (type2 != 0xFF && type == type2)) {
switch (opsize) {
case 2: opsize = 3; break;
case 5: opsize = 6; break;
@@ -468,7 +513,7 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
}
prefix |= amp[opsize-1];
}
- if (am & (AM_ZM|AM_ZMX|AM_ZMY|AM_IND|AM_INDX|AM_INDY|AM_ABS|AM_INDX2|AM_ZM2)) {
+ if (am & AM_ADDR) {
switch (type) {
case ZM:
if (am & AM_ZM) {
@@ -479,7 +524,7 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
break;
case ZMX:
if (am & AM_ZMX) {
- opcode += 0x06;
+ opcode += (id == TOK_OPCODE) ? 0x06 : 0x54;
}
break;
case ZMY:
@@ -487,54 +532,59 @@ uint64_t handle_opcode(token *t, bytecount *bc, uint8_t isasm, uint64_t address,
opcode += 0x14;
}
break;
- case ABS:
- if (am & AM_ABS) {
- opcode += 0x10;
- }
- break;
case INDX:
if (am & AM_INDX) {
- opcode += 0x16;
+ opcode += (id == TOK_OPCODE) ? 0x16 : 0x94;
break;
}
/* Falls Through. */
case IND:
case INDY:
- if (am & (AM_IND|AM_INDY|AM_INDX2)) {
+ if ((id == TOK_OPCODE) && (am & (AM_IND|AM_INDY|AM_INDX2))) {
opcode = ind_ops[get_ind(instr, type, dbg)];
+ } else {
+ opcode += (type == IND) ? 0x44 : 0x84;
}
break;
- }
- if (prefix) {
- if (isasm) {
- addr[address] = prefix;
- }
- address++;
- bc->progsize++;
- }
- 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];
- }
+ case ABS:
+ if (am & AM_ABS) {
+ opcode += 0x10;
+ }
+ break;
+ case ABSX:
+ if (am & AM_ABX) {
+ opcode += 0x50;
+ }
+ break;
+ case ABSY:
+ if (am & AM_ABY) {
+ opcode += 0x00;
+ }
+ break;
+ case AIND:
+ if (am & AM_AIND) {
+ opcode += 0x40;
+ }
+ break;
+ case AINDX:
+ if (am & AM_AINDX) {
+ opcode += 0x90;
+ }
+ break;
+ case AINDY:
+ if (am & AM_AINDY) {
+ opcode += 0x80;
+ }
+ break;
+
}
tmp = opsize;
}
break;
}
- address += tmp;
- bc->progsize += tmp;
+ inst_size = write_inst(prefix, ext_prefix, opcode, val.u64, address, tmp, isasm, dbg);
+ address += inst_size;
+ bc->progsize += inst_size;
}
return address;
}
@@ -554,6 +604,7 @@ uint64_t parse_tokens(token *t, line **l, bytecount *bc, uint8_t isasm, uint64_t
case DIR_QWORD: address = handle_directive(t, bc, isasm, address, dbg); break;
}
break;
+ case TOK_EXTOP :
case TOK_OPCODE: address = handle_opcode(t, bc, isasm, address, dbg); break;
case TOK_COMMENT: break;
}