#include "opcode.h"
#include <ctype.h>
#include <string.h>
#define debug 1
#define SETOP(num, _mne, _IMM, _ZM, _ZMX, _ZMY, _IND, _INX, _INY, _ABS, _IMPL) \
{opcodes[num].mnemonic[3] = '\0'; strncpy(opcodes[num].mnemonic, _mne, 3); \
opcodes[num].imm = _IMM; \
opcodes[num].zm = _ZM; opcodes[num].zmx = _ZMX; opcodes[num].zmy = _ZMY; \
opcodes[num].ind = _IND; opcodes[num].inx = _INX; opcodes[num].iny = _INY; \
opcodes[num].abs = _ABS; opcodes[num].impl = _IMPL;}
struct fixup {
struct fixup *nxt;
struct label *l;
uint64_t adr;
};
struct label {
struct label* nxt;
uint64_t adr;
uint8_t def;
char name[1];
};
static char tstr[2048];
struct label *labels = 0;
struct fixup *fixups = 0;
uint8_t defined = 0;
struct label *mklabel(const char *name, uint64_t adr, uint8_t def) {
struct label *l;
for (l = labels; l; l = l->nxt) {
if (!strcasecmp(name, l->name)) {
if (def) {
if (l->def) {
printf("oof, you cannot redefine the label: %s\n", name);
defined = 1;
} else {
defined = 0;
}
l->def = def;
l->adr = adr;
}
return l;
}
}
l = malloc(sizeof(*l) + strlen(name));
l->def = def;
l->adr = adr;
strcpy(l->name, name);
l->nxt = labels;
labels = l;
defined = 0;
return l;
}
uint64_t use_label(const char *name, uint64_t adr) {
struct label *l = mklabel(name, 0, 0);
adr++;
if (l->def) {
return l->adr;
} else {
printf("oof, label %s, does not exist, yet.\n", name);
struct fixup *f = malloc(sizeof(*f));
f->nxt = fixups;
f->adr = adr;
f->l = l;
fixups = f;
return adr-1;
}
}
void reslv_fixups(void) {
struct fixup *f;
for (f = fixups; f; f = f->nxt) {
if (f->l->def) {
addr[f->adr] = f->l->adr & 0xFF;
if (f->l->adr & 0xFF00)
addr[f->adr+1] = f->l->adr >> 8;
if (f->l->adr & 0xFF000000) {
addr[f->adr+2] = f->l->adr >> 16;
addr[f->adr+3] = f->l->adr >> 24;
}
if (f->l->adr & 0xFF00000000000000) {
addr[f->adr+4] = f->l->adr >> 32;
addr[f->adr+5] = f->l->adr >> 40;
addr[f->adr+6] = f->l->adr >> 48;
addr[f->adr+7] = f->l->adr >> 56;
}
} else {
printf("oof, undefined reference to '%s', at $%016llx.\n", f->l->name, f->adr);
}
}
}
void viewmem(uint64_t address) {
printf("\t\t\t");
for (int ind = 0; ind < 0x10; ind++) {
printf("%02x", ind);
if (ind < 0x0F)
printf(" ");
}
printf("\n\n");
for (int hi = 0; hi < 0x10; hi++) {
printf("%016llx:\t", (address & ~0xF)+(hi*0x10));
for (int lo = 0; lo < 0x10; lo++) {
printf("%02x", addr[(address & ~0xF)+lo+(hi*0x10)]);
if (lo < 0x0F)
printf(" ");
}
printf("\n");
}
}
void usage() {
puts("SuBAsm for CISC-0.2");
puts("Commands:");
puts("\tviewmem, vm, v\t\tGet the contents of memory\n"
"\t\t\t\t(Displays 256 bytes of memory\n"
"\t\t\t\t starting from where the program counter\n"
"\t\t\t\t currently is).");
puts("\trelsv, rf, r\t\tResolve any currently unknown labels.");
puts("\tdisasm, dis,\n"
"\td [start-][end]\t\tDisassemble from starting address, to\n"
"\t\t\t\tending address.");
puts("\tinst, i [inst]\t\tGet a descriptions of that instruction.\n"
"\t\t\t\tIf no argument is specified, or the\n"
"\t\t\t\targument specified is \"all\", list all\n"
"\t\t\t\tinstructions, along with a description\n"
"\t\t\t\tfor each of them.");
puts("\tquit, q\t\t\tQuit the emulator.");
puts("\thelp, h\t\t\tDisplays this mesage.");
}
void instinfo(const char *inst) {
for(int i = 0; i < OPNUM; i++) {
if (!strcasecmp(inst, mne[i])) {
printf("%s\t%s\n", mne[i], instdesc[i]);
break;
} else if (!strcasecmp(inst, "all")) {
printf("%s\t%s\n", mne[i], instdesc[i]);
}
}
}
void disasm(uint8_t prefix, uint8_t opcode, uint64_t value) {
char postfix[3];
char op[4];
uint8_t addrsize = (prefix & 8) >> 3;
uint8_t rs = (prefix & 0x30) >> 4;
uint8_t regsize = (1 << rs);
op[0] = opname[opcode][0];
op[1] = opname[opcode][1];
op[2] = opname[opcode][2];
op[3] = '\0';
if (regsize == 1) {
postfix[0] = '\0';
postfix[1] = '\0';
postfix[2] = '\0';
} else {
postfix[0] = '.';
if (regsize == 2)
postfix[1] = 'W';
else if (regsize == 4)
postfix[1] = 'D';
else if (regsize == 8)
postfix[1] = 'Q';
else {
postfix[0] = '\0';
postfix[1] = '\0';
}
postfix[2] = '\0';
}
switch (optype[opcode]) {
case IMPL:
printf("%s\n" , opname[opcode]);
break;
case IMM:
if (regsize == 1)
printf("%s #$%02x\n" , op, value);
if (regsize == 2)
printf("%s%s #$%04x\n" , op, postfix, value);
if (regsize == 4)
printf("%s%s #$%08x\n" , op, postfix, value);
if (regsize == 8)
printf("%s%s #$%016llx\n" , op, postfix, value);
break;
case ZM:
case ZMX:
case ZMY:
if (addrsize)
printf("%s%s $%08x%s\n" , op, postfix, value, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y"));
else
printf("%s%s $%02x%s\n" , op, postfix, value, (optype[opcode] == ZM) ? "" : ((optype[opcode] == ZMX) ? ", x" : ", y"));
break;
case IND:
case INDX:
case INDY:
if (addrsize)
printf("%s%s ($%08x%s\n" , op, postfix, value, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y"));
else
printf("%s%s ($%02x%s\n" , op, postfix, value, (optype[opcode] == IND) ? ")" : ((optype[opcode] == INDX) ? ", x)" : "), y"));
break;
case ABS:
if (addrsize)
printf("%s%s $%016llx\n" , op, postfix, value);
else
printf("%s%s $%04x\n" , op, postfix, value);
break;
}
}
int asmmon(const char *fn) {
SETOP( 0, "CPS", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP( 1, "ADC", 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00);
SETOP( 2, "AAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02);
SETOP( 3, "PHP", 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP( 4, "CPB", 0x09, 0x2D, 0x00, 0x00, 0x55, 0xAD, 0xAC, 0x2C, 0x00);
SETOP( 5, "PHB", 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP( 6, "DEC", 0x00, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xE5);
SETOP( 7, "JMP", 0x00, 0x0E, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x10, 0x00);
SETOP( 8, "SBC", 0x11, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00);
SETOP( 9, "SAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12);
SETOP(10, "ENT", 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP(11, "CPY", 0x19, 0x3D, 0x00, 0x00, 0x85, 0x00, 0x00, 0x4C, 0x00);
SETOP(12, "PLB", 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP(13, "INC", 0x00, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0xF5);
SETOP(14, "JSR", 0x00, 0x1E, 0x00, 0x00, 0xBE, 0x00, 0x00, 0x00, 0x00);
SETOP(15, "JSL", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00);
SETOP(16, "AND", 0x21, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00);
SETOP(17, "ABA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22);
SETOP(18, "PLP", 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP(19, "CPX", 0x29, 0x4D, 0x00, 0x00, 0xB5, 0x00, 0x00, 0x3C, 0x00);
SETOP(20, "PHY", 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP(21, "BPO", 0x00, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00);
SETOP(22, "ORA", 0x31, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00);
SETOP(23, "OAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32);
SETOP(24, "STT", 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP(25, "PLY", 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP(26, "BNG", 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00);
SETOP(27, "XOR", 0x41, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00);
SETOP(28, "XAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42);
SETOP(29, "PHA", 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP(30, "PHX", 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP(31, "BCS", 0x00, 0x4E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00);
SETOP(32, "LSL", 0x51, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00);
SETOP(33, "LLB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52);
SETOP(34, "CLC", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58);
SETOP(35, "PLX", 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP(36, "BCC", 0x00, 0x5E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00);
SETOP(37, "LSR", 0x61, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00);
SETOP(38, "LRB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62);
SETOP(39, "PLA", 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP(40, "TAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6A);
SETOP(41, "BEQ", 0x00, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00);
SETOP(42, "ROL", 0x71, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00);
SETOP(43, "RLB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72);
SETOP(44, "SEC", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78);
SETOP(45, "TBA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A);
SETOP(46, "BNE", 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00);
SETOP(47, "ROR", 0x81, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00);
SETOP(48, "RRB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82);
SETOP(49, "DEY", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88);
SETOP(50, "TAY", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A);
SETOP(51, "BVS", 0x00, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00);
SETOP(52, "MUL", 0x91, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00);
SETOP(53, "MAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92);
SETOP(54, "CLI", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98);
SETOP(55, "TYA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9A);
SETOP(56, "BVC", 0x00, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00);
SETOP(57, "DIV", 0xA1, 0xA6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x00);
SETOP(58, "DAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA2);
SETOP(59, "INY", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA8);
SETOP(60, "TAX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA);
SETOP(61, "RTS", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAE);
SETOP(62, "RTL", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0);
SETOP(63, "CMP", 0xB1, 0xB6, 0x00, 0x00, 0x25, 0x7D, 0x7C, 0xB4, 0x00);
SETOP(64, "CAB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2);
SETOP(65, "SEI", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8);
SETOP(66, "LDX", 0xB9, 0xBD, 0x00, 0xC9, 0x95, 0x00, 0x00, 0xBC, 0x00);
SETOP(67, "TXA", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBA);
SETOP(68, "RTI", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0);
SETOP(69, "LDA", 0xC1, 0xC6, 0x79, 0x39, 0x05, 0x5D, 0x5C, 0xC4, 0x00);
SETOP(70, "DEX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC5);
SETOP(71, "CLV", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC8);
SETOP(72, "TYX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCA);
SETOP(73, "STA", 0x00, 0xCD, 0x89, 0x49, 0x15, 0x6D, 0x6C, 0xCC, 0x00);
SETOP(74, "TSX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0);
SETOP(75, "LDB", 0xD1, 0xD6, 0x99, 0x59, 0x35, 0x8D, 0x8C, 0xD4, 0x00);
SETOP(76, "INX", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5);
SETOP(77, "WAI", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8);
SETOP(78, "TXY", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDA);
SETOP(79, "STB", 0x00, 0xDD, 0xA9, 0x69, 0x45, 0x9D, 0x9C, 0xDC, 0x00);
SETOP(80, "TXS", 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
SETOP(81, "LDY", 0xE1, 0xE6, 0xE9, 0x00, 0x65, 0x00, 0x00, 0xE4, 0x00);
SETOP(82, "BRK", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8);
SETOP(83, "NOP", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEA);
SETOP(84, "STY", 0x00, 0xED, 0xF9, 0x00, 0x75, 0x00, 0x00, 0xEC, 0x00);
SETOP(85, "DEB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE);
SETOP(86, "ASR", 0xF1, 0xF6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0x00);
SETOP(87, "ARB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2);
SETOP(88, "STX", 0x00, 0xFD, 0x00, 0xD9, 0xA5, 0x00, 0x00, 0xFC, 0x00);
SETOP(89, "INB", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE);
FILE *fp;
if (strcasecmp(fn, "stdin") != 0) {
fp = fopen(fn, "r");
if (fp == NULL)
return 2;
}
uint8_t done = 0;
uint64_t address = 0x0000;
uint64_t start, end;
uint8_t prefix, opcode;
while (!(done & 1)) {
char *buf = NULL;
char *ins;
char *postfix;
char mode[3];
opent op;
uint8_t addrmode = IMPL;
uint8_t addrtok = 0;
uint64_t value = 0;
char *oprand;
char *oprand2;
char *cmd;
char ir[2] = "";
int a = 0;
int b = 0;
char *tmp = malloc(sizeof(char *)*128);
char *tmp2;
size_t size;
prefix = 0;
done = 0;
if (!strcasecmp(fn, "stdin")) {
getline(&buf, &size, stdin);
} else {
getline(&buf, &size, fp);
}
cmd = strtok_r(buf, "\n", &tmp);
if (cmd != NULL) {
if (strcasecmp(cmd, "done") == 0) {
done |= 1;
} else {
ins = strtok(buf, "\t\n ");
if (ins != NULL) {
oprand = strtok(NULL, "\t\n");
strtok_r(ins, ".", &postfix);
if (oprand != NULL) {
for (int i = 0; i < strlen(oprand); i++) {
switch (oprand[i]) {
case '(':
addrmode = IND;
break;
case '+':
addrtok = 1;
break;
case '-':
addrtok = 2;
}
if (oprand[i] == '"')
break;
if (a && oprand[a] == ',') {
if (oprand[i] == 'x' || oprand[i] == 'X') {
ir[0] = 'x';
ir[1] = '\0';
}
if (oprand[i] == 'y' || oprand[i+1] == 'Y') {
ir[0] = 'y';
ir[1] = '\0';
}
if (b && ir[0] == 'y')
oprand[b] = '\0';
}
if (oprand[i] == ')' && oprand[i+1] == ',')
b = i;
else if (oprand[i] == ')')
oprand[i] = '\0';
if (oprand[i] == ',' || oprand[i] == ';')
a = i;
}
if (a)
oprand[a] = '\0';
}
}
if (!strcasecmp(cmd, "quit") || !strcasecmp(cmd, "q")) {
return 2;
}
if (!strcasecmp(cmd, "viewmem") || !strcasecmp(cmd, "vm") || !strcasecmp(cmd, "v")) {
done |= 4;
viewmem(address);
}
if (!strcasecmp(cmd, "reslv") || !strcasecmp(cmd, "rf") || !strcasecmp(cmd, "r")) {
done |= 4;
puts("Resolving unknown labels.");
reslv_fixups();
puts("Finished resolving unknown labels.");
}
if (!strcasecmp(cmd, "help") || !strcasecmp(cmd, "h")) {
done |= 4;
usage();
}
if (oprand == NULL && ins == NULL && postfix == NULL) {
done |= 2;
}
cmd = strtok(cmd, " \n");
if (!strcasecmp(cmd, "inst") || !strcasecmp(cmd, "i")) {
done |= 64;
done |= 6;
if (oprand != NULL) {
instinfo(oprand);
} else {
instinfo("all");
}
}
if (!strcasecmp(cmd, "disasm") || !strcasecmp(cmd, "dis") || !strcasecmp(cmd, "d")) {
done |= 64;
done |= 6;
if (oprand != NULL) {
cmd = strtok_r(oprand, " -", &tmp);
if (cmd != NULL) {
for (int i = 0; i < strlen(cmd); i++) {
if ((isalnum(cmd[i]) || cmd[i] == '_') && cmd[i] != '"') {
value = use_label(tmp, address);
sprintf(tmp, "%llx", value);
break;
}
if (cmd[i] == '$') {
cmd = strtok(cmd, "$");
value = strtoull(cmd, NULL, 16);
break;
}
if (cmd[i] == ';') {
done |= 16;
break;
}
}
start = value;
for (int i = 0; i < strlen(tmp); i++) {
if ((isalnum(tmp[i]) || tmp[i] == '_') && tmp[i] != '"') {
value = use_label(tmp, address);
sprintf(tmp, "%llx", value);
break;
}
if (tmp[i] == '$') {
tmp = strtok(tmp, "$");
value = strtoull(tmp, NULL, 16);
break;
}
if (tmp[i] == ';') {
done |= 16;
break;
}
}
(!strlen(tmp)) ? (end = address) : (end = value);
} else {
start = value;
end = address;
}
} else {
start = 0;
end = address;
}
while (start < end) {
uint8_t rs;
uint8_t regsize;
uint8_t addrsize;
if (start < 0xFF)
printf("$%02llx: ", start);
else if (start < 0xFFFF)
printf("$%04llx: ", start);
else if (start < 0xFFFFFFFF)
printf("$%08llx: ", start);
else if (start < 0xFFFFFFFFFFFFFFFF)
printf("$%016llx: ", start);
prefix = addr[start];
if ((prefix & 0x03) == 0x03) {
start+=1;
addrsize = (prefix & 0x0C) >> 2;
rs = (prefix & 0x30) >> 4;
regsize = (1 << rs);
} else {
prefix = 0;
regsize = 1;
addrsize = 0;
}
opcode = addr[start];
start+=1;
switch (optype[opcode]) {
case IMPL:
break;
case IMM:
value = addr[start];
switch (regsize) {
case 8:
value |= (uint64_t)addr[start+7] << 56;
value |= (uint64_t)addr[start+6] << 48;
value |= (uint64_t)addr[start+5] << 40;
value |= (uint64_t)addr[start+4] << 32;
case 4:
value |= addr[start+3] << 24;
value |= addr[start+2] << 16;
case 2:
value |= addr[start+1] << 8;
}
start += regsize;
break;
case ZM:
case ZMX:
case ZMY:
case IND:
case INDX:
case INDY:
value = addr[start];
switch (addrsize) {
case 0:
start+=1;
break;
case 1:
value |= addr[start+1] << 8;
value |= addr[start+2] << 16;
start+=3;
break;
case 2:
value |= addr[start+1] << 8;
value |= addr[start+2] << 16;
value |= addr[start+3] << 24;
value |= (uint64_t)addr[start+4] << 32;
value |= (uint64_t)addr[start+5] << 40;
start+=6;
break;
case 3:
value |= addr[start+1] << 8;
value |= addr[start+2] << 16;
value |= addr[start+3] << 24;
start+=4;
break;
}
break;
case ABS:
value = addr[start];
value |= addr[start+1] << 8;
switch (addrsize) {
case 0:
start+=2;
break;
case 1:
value |= addr[start+2] << 16;
value |= addr[start+3] << 24;
value |= (uint64_t)addr[start+4] << 32;
start+=5;
break;
case 2:
value |= addr[start+2] << 16;
value |= addr[start+3] << 24;
value |= (uint64_t)addr[start+4] << 32;
value |= (uint64_t)addr[start+5] << 40;
value |= (uint64_t)addr[start+6] << 48;
start+=7;
break;
case 3:
value |= addr[start+2] << 16;
value |= addr[start+3] << 24;
value |= (uint64_t)addr[start+4] << 32;
value |= (uint64_t)addr[start+5] << 40;
value |= (uint64_t)addr[start+6] << 48;
value |= (uint64_t)addr[start+7] << 56;
start+=8;
break;
}
break;
}
disasm(prefix, opcode, value);
}
}
if (!(done & 64)) {
if (ins != NULL) {
for (int i = 0; i < strlen(ins); i++) {
if (i && ins[i] == ':') {
ins[i] = '\0';
mklabel(ins, address, 1);
#if debug
printf("Created label with the name %s, at address: $%llx\n", ins, address);
#endif
done |= 6;
break;
}
if (ins[i] == ';') {
if (i && (ins[i-1] == ' ' || ins[i-1] == '\t'))
ins[i] = '\0';
else
done |=6;
break;
}
}
if (!(done & 6)) {
if (oprand != NULL) {
if (!strcasecmp(ins, ".org")) {
done |= 6;
oprand = strtok(oprand, "$");
address = strtoull(oprand, NULL, 16);
#if debug
printf("Origin for program code is now at address $%llx.\n", address);
#endif
}
if (!strcasecmp(ins, ".byte") || !strcasecmp(ins, ".word") || !strcasecmp(ins, ".dword") || !strcasecmp(ins, ".qword")) {
done |= 6;
uint8_t qstr = 0;
uint64_t staddr = address;
uint16_t slen = 0;
char *tmpstr = tstr;
char c;
for (int i = 0; i < strlen(oprand); i++) {
if (!qstr) {
if ((isalnum(oprand[i]) || oprand[i] == '_') && oprand[i] != '"') {
qstr = 0;
value = use_label(oprand, address);
sprintf(oprand, "%llx", value);
break;
}
if (!strcasecmp(ins, ".byte")) {
if (oprand[i] == '"') {
qstr = 1;
continue;
} else if (oprand[i] == '\'') {
qstr = 2;
continue;
}
}
if (oprand[i] == '$') {
qstr = 0;
oprand = strtok(oprand, "$");
value = strtoull(oprand, NULL, 16);
break;
}
if (oprand[i] == ';') {
qstr = 0;
done |= 16;
break;
}
} else if (qstr == 1) {
switch (oprand[i]) {
case 0:
puts("oof, unterminated string.");
qstr = 4;
break;
case '"':
value = '\0';
c = '\0';
tmpstr[slen++] = '\0';
qstr = 3;
break;
case '\\':
switch (oprand[i+1]) {
case 'n':
value = '\n';
c = '\n';
tmpstr[slen++] = '\\';
tmpstr[slen++] = 'n';
break;
case 't':
value = '\t';
c = '\t';
tmpstr[slen++] = '\\';
tmpstr[slen++] = 't';
break;
case 'r':
value = '\r';
c = '\r';
tmpstr[slen++] = '\\';
tmpstr[slen++] = 'r';
break;
case '0':
break;
default:
value = oprand[i];
tmpstr[slen++] = '\\';
tmpstr[slen++] = oprand[i];
break;
}
i++;
break;
default:
value = oprand[i];
c = oprand[i];
tmpstr[slen++] = c;
break;
}
addr[address++] = (uint8_t)value & 0xFF;
} else if (qstr == 2) {
switch (oprand[i]) {
case 0:
puts("oof, unterminated string.");
qstr = 4;
break;
case '\'':
c = '\0';
tmpstr[slen++] = '\0';
qstr = 3;
break;
case '\\':
switch (oprand[i+1]) {
case 'n':
value = '\n';
c = '\n';
tmpstr[slen++] = '\\';
tmpstr[slen++] = 'n';
break;
case 't':
value = '\t';
c = '\t';
tmpstr[slen++] = '\\';
tmpstr[slen++] = 't';
break;
case 'r':
value = '\r';
c = '\r';
tmpstr[slen++] = '\\';
tmpstr[slen++] = 'r';
break;
case '0':
break;
default:
value = oprand[i];
tmpstr[slen++] = '\\';
tmpstr[slen++] = oprand[i];
break;
}
i++;
break;
default:
value = oprand[i];
c = oprand[i];
tmpstr[slen++] = c;
break;
}
if (qstr != 3)
addr[address++] = (uint8_t)value & 0xFF;
}
}
if (!strcasecmp(ins, ".byte") && !qstr)
addr[address++] = value & 0xFF;
if (!strcasecmp(ins, ".word")) {
addr[address] = (uint8_t)value & 0xFF;
addr[address+1] = value >> 8;
address+=2;
}
if (!strcasecmp(ins, ".dword")) {
addr[address] = (uint8_t)value & 0xFF;
addr[address+1] = value >> 8;
addr[address+2] = value >> 16;
addr[address+3] = value >> 24;
address+=4;
}
if (!strcasecmp(ins, ".qword")) {
addr[address] = (uint8_t)value & 0xFF;
addr[address+1] = value >> 8;
addr[address+2] = value >> 16;
addr[address+3] = value >> 24;
addr[address+4] = value >> 32;
addr[address+5] = value >> 40;
addr[address+6] = value >> 48;
addr[address+7] = value >> 56;
address+=8;
}
#if debug
if (!qstr) {
printf("The value $%llx was placed at address%s ", value, (staddr != address-1) ? "es" : "");
if (staddr == address-1)
printf("$%llx.\n", staddr);
else
printf("$%llx-$%llx.\n", staddr, address-1);
} else {
printf("The string \"%s\", was placed at address%s ", tmpstr, (staddr != address-1) ? "es" : "");
if (staddr == address-1)
printf("$%llx.\n", staddr);
else
printf("$%llx-$%llx.\n", staddr, address-1);
}
#endif
}
}
}
}
}
if (oprand == NULL && !strcasecmp(ins, "TXS")) {
addrmode = IMM;
done |= 32;
}
else if (oprand != NULL && !strcasecmp(ins, "TXS"))
prefix = 0x13;
if (!(done & 2) && oprand != NULL) {
mode[0] = oprand[0];
mode[1] = oprand[1];
strtok_r(oprand, "+-", &oprand2);
if (ir[0] == 'x' || ir[0] == 'y')
oprand2 = strtok_r(oprand2, ",)", &tmp2);
uint8_t isimm = oprand[0] == '#';
uint8_t issectok = (oprand[1] == '$' || oprand[1] == '%' || isdigit(oprand[1]));
if (oprand[0] == '$' || (isimm && issectok) || (oprand[0] == '(' && issectok)) {
oprand = strtok(oprand, "#($%");
if (isimm) {
addrmode = IMM;
done |= 32;
if (mode[1] == '$')
value = strtoull(oprand, NULL, 16);
else if (mode[1] == '%')
value = strtoull(oprand, NULL, 2);
else
value = strtoull(oprand, NULL, 10);
} else {
if (mode[0] == '$' || mode[1] == '$')
value = strtoull(oprand, NULL, 16);
else if (mode[0] == '%' || mode[1] == '%')
value = strtoull(oprand, NULL, 2);
else
value = strtoull(oprand, NULL, 10);
if (mode[0] != '(') {
if ((value & 0xFF0000 || value & 0xFFFF00000000 || value & 0xFFFF0000 || !(value & 0xFF00)))
addrmode = ZM;
else if (value & 0xFF00000000 || value & 0xFF000000000000 || value & 0xFF00000000000000 || (value & 0xFF00))
addrmode = ABS;
}
if (addrmode == ZM || addrmode == IND) {
if (value & 0xFFFF00)
prefix |= 0x7;
else if (value & 0xFFFF00000000)
prefix |= 0xB;
else if (value & 0xFFFF000000)
prefix |= 0xF;
}
if (addrmode == ABS) {
if (value & 0xFF00000000)
prefix |= 0x7;
else if (value & 0xFF000000000000)
prefix |= 0xB;
else if (value & 0xFF00000000000000)
prefix |= 0xF;
}
if ((addrmode == 2 || addrmode == 6) && ir != NULL) {
switch (ir[0]) {
case 'x':
if (addrmode == ZM)
addrmode = ZMX;
else if (addrmode == IND)
addrmode = INDX;
break;
case 'y':
if (addrmode == ZM)
addrmode = ZMY;
else if (addrmode == IND)
addrmode = INDY;
break;
default:
done |= 32;
break;
}
}
}
} else {
if (mode[0] == '(') {
oprand = strtok(oprand, "#($%");
} else if (isimm) {
oprand = strtok(oprand, "#");
addrmode = IMM;
done |= 32;
}
for (int i = 0; i < strlen(oprand); i++) {
if (oprand[i] == ';') {
done |= 16;
break;
}
if ((isalnum(oprand[i]) || oprand[i] == '_') && oprand[i] != '"') {
value = use_label(oprand, address);
if (!isimm) {
if (mode[0] != '(') {
if ((value & 0xFF0000 || value & 0xFFFF00000000 || value & 0xFFFF0000 || !(value & 0xFF00)))
addrmode = ZM;
else if (value & 0xFF00000000 || value & 0xFF000000000000 || value & 0xFF00000000000000 || (value & 0xFF00))
addrmode = ABS;
}
if (addrmode == ZM || addrmode == IND) {
if (value & 0xFFFF00)
prefix |= 0x7;
else if (value & 0xFFFF00000000)
prefix |= 0xB;
else if (value & 0xFFFF000000)
prefix |= 0xF;
}
if (addrmode == ABS) {
if (value & 0xFF00000000)
prefix |= 0x7;
else if (value & 0xFF000000000000)
prefix |= 0xB;
else if (value & 0xFF00000000000000)
prefix |= 0xF;
}
if ((addrmode == ZM || addrmode == IND) && ir != NULL && a) {
switch (ir[0]) {
case 'x':
if (addrmode == ZM)
addrmode = ZMX;
else if (addrmode == IND)
addrmode = INDX;
break;
case 'y':
if (addrmode == ZM)
addrmode = ZMY;
else if (addrmode == IND)
addrmode = INDY;
break;
default:
done |= 32;
break;
}
}
}
sprintf(oprand, "%llx", value);
break;
}
}
}
if (oprand2 != NULL && (addrtok == 1 || addrtok == 2)) {
uint64_t val2 = 0;
mode[0] = oprand2[0];
oprand2 = strtok(oprand2, "$%");
if (mode[0] == '$')
val2 = strtoull(oprand2, NULL, 16);
else if (mode[0] == '%')
val2 = strtoull(oprand2, NULL, 2);
else
val2 = strtoull(oprand2, NULL, 10);
switch (addrtok) {
case 1:
value += val2;
break;
case 2:
value -= val2;
break;
}
}
}
if (ins != NULL && !(done & 6)) {
uint8_t i;
for (i = 0; i < OPNUM; i++) {
if (strcasecmp(opcodes[i].mnemonic, ins) == 0) {
if (addrmode == IMPL && (opcodes[i].impl || opcodes[i].impl == CPS)) {
done |= 8;
} else if (addrmode == IMM) {
switch (opcodes[i].imm) {
case PHB:
case PHP:
case PHA:
case PHY:
case PHX:
case PLB:
case PLP:
case PLA:
case PLY:
case PLX:
case STT:
case TXS:
case LSL:
case LSR:
case ROL:
case ROR:
case ASR:
case ENT:
done |= 8;
break;
}
} else {
if (strcasecmp(ins, "JMP") == 0)
done |=8;
if (strcasecmp(ins, "JSR") == 0)
done |=8;
if (strcasecmp(ins, "JSL") == 0)
done |=8;
if (strcasecmp(ins, "INC") == 0)
done |=8;
if (strcasecmp(ins, "BPO") == 0)
done |=8;
if (strcasecmp(ins, "BNG") == 0)
done |=8;
if (strcasecmp(ins, "BCS") == 0)
done |=8;
if (strcasecmp(ins, "BCC") == 0)
done |=8;
if (strcasecmp(ins, "BEQ") == 0)
done |=8;
if (strcasecmp(ins, "BNE") == 0)
done |=8;
if (strcasecmp(ins, "BVS") == 0)
done |=8;
if (strcasecmp(ins, "BVC") == 0)
done |=8;
}
op = opcodes[i];
break;
}
}
if (postfix != NULL && !(done & 8)) {
if (!strcasecmp(postfix, "w") || !strcasecmp(postfix, "2")) {
prefix |= 0x13;
} else if (!strcasecmp(postfix, "d") || !strcasecmp(postfix, "4")) {
prefix |= 0x23;
} else if (!strcasecmp(postfix, "q") || !strcasecmp(postfix, "8")) {
prefix |= 0x33;
} else if (!prefix) {
done |=8;
}
} else if (postfix == NULL && (!(done & 8) && !prefix)) {
done |=8;
}
uint8_t r;
uint8_t r2;
if (!(done & 8)) {
r = prefix;
addr[address] = prefix;
address += 1;
} else {
r = 0;
}
r2 = 1 << ((prefix & 0x30) >> 4);
switch (addrmode) {
case IMPL:
if (op.impl || op.impl == CPS) {
addr[address++] = op.impl;
break;
} else {
fprintf(stderr, "oof, %s requires an operand.\n", op.mnemonic);
}
break;
case IMM:
if (op.imm) {
if ((prefix & 0x30) == 0x10 && op.imm == TXS)
r = prefix;
addr[address++] = op.imm;
switch (op.imm) {
case PHP:
case PHA:
case PHY:
case PHX:
case PLP:
case PLA:
case PLY:
case PLX:
case STT:
case LSL:
case LSR:
case ROL:
case ROR:
case ASR:
case ENT:
addr[address++] = value & 0xFF;
break;
case TXS:
if ((r & 0x30) == 0x10) {
addr[address] = value & 0xFF;
addr[address+2] = value >> 8;
address+=2;
}
break;
default:
addr[address] = value & 0xFF;
if (r & 0x10) {
addr[address+1] = value >> 8;
}
if (r & 0x20) {
addr[address+2] = value >> 16;
addr[address+3] = value >> 24;
}
if (r & 0x30) {
addr[address+4] = value >> 32;
addr[address+5] = value >> 40;
addr[address+6] = value >> 48;
addr[address+7] = value >> 56;
}
address+=r2;
break;
}
break;
} else {
fprintf(stderr, "oof, %s does not use Immediate data.\n", op.mnemonic);
}
break;
case ZM:
if (op.zm) {
addr[address++] = op.zm;
addr[address] = value & 0xFF;
switch ((r & 0x0C) >> 2) {
case 2:
addr[address+5] = (uint64_t)value >> 40;
addr[address+4] = (uint64_t)value >> 32;
address += 2;
case 3:
addr[address+3] = value >> 24;
address += 1;
case 1:
addr[address+2] = value >> 16;
addr[address+1] = value >> 8;
address += 2;
}
address += 1;
break;
} else {
fprintf(stderr, "oof, %s does not use Zero Matrix.\n", op.mnemonic);
}
break;
case ZMX:
if (op.zmx) {
addr[address++] = op.zmx;
addr[address] = value & 0xFF;
switch ((r & 0x0C) >> 2) {
case 2:
addr[address+5] = (uint64_t)value >> 40;
addr[address+4] = (uint64_t)value >> 32;
address += 2;
case 3:
addr[address+3] = value >> 24;
address += 1;
case 1:
addr[address+2] = value >> 16;
addr[address+1] = value >> 8;
address += 2;
}
address += 1;
break;
} else {
fprintf(stderr, "oof, %s does not use Zero Matrix, indexed with x.\n", op.mnemonic);
}
break;
case ZMY:
if (op.zmy) {
addr[address++] = op.zmy;
addr[address] = value & 0xFF;
switch ((r & 0x0C) >> 2) {
case 2:
addr[address+5] = (uint64_t)value >> 40;
addr[address+4] = (uint64_t)value >> 32;
address += 2;
case 3:
addr[address+3] = value >> 24;
address += 1;
case 1:
addr[address+2] = value >> 16;
addr[address+1] = value >> 8;
address += 2;
}
address += 1;
break;
} else {
fprintf(stderr, "oof, %s does not use Zero Matrix, indexed with y.\n", op.mnemonic);
}
break;
case ABS:
if (op.abs) {
addr[address++] = op.abs;
addr[address] = value & 0xFF;
addr[address+1] = value >> 8;
switch ((r & 0x0C) >> 2) {
case 3:
addr[address+7] = value >> 56;
address += 1;
case 2:
addr[address+6] = (uint64_t)value >> 48;
addr[address+5] = (uint64_t)value >> 40;
address += 2;
case 1:
addr[address+4] = (uint64_t)value >> 32;
addr[address+3] = value >> 24;
addr[address+2] = value >> 16;
address += 3;
}
address += 2;
break;
} else {
fprintf(stderr, "oof, %s cannot be an absolute dictator.\n", op.mnemonic);
}
break;
case IND:
if (op.ind) {
addr[address++] = op.ind;
addr[address] = value & 0xFF;
switch ((r & 0x0C) >> 2) {
case 2:
addr[address+5] = (uint64_t)value >> 40;
addr[address+4] = (uint64_t)value >> 32;
address += 2;
case 3:
addr[address+3] = value >> 24;
address += 1;
case 1:
addr[address+2] = value >> 16;
addr[address+1] = value >> 8;
address += 2;
}
address += 1;
break;
} else {
fprintf(stderr, "oof, %s cannot use pointers.\n", op.mnemonic);
}
break;
case INDX:
if (op.inx) {
addr[address++] = op.inx;
addr[address] = value & 0xFF;
switch ((r & 0x0C) >> 2) {
case 2:
addr[address+5] = (uint64_t)value >> 40;
addr[address+4] = (uint64_t)value >> 32;
address += 2;
case 3:
addr[address+3] = value >> 24;
address += 1;
case 1:
addr[address+2] = value >> 16;
addr[address+1] = value >> 8;
address += 2;
}
address += 1;
break;
} else {
fprintf(stderr, "oof, %s does not use Indexed Indirect.\n", op.mnemonic);
}
break;
case INDY:
if (op.iny) {
addr[address++] = op.iny;
addr[address] = value & 0xFF;
switch ((r & 0x0C) >> 2) {
case 2:
addr[address+5] = (uint64_t)value >> 40;
addr[address+4] = (uint64_t)value >> 32;
address += 2;
case 3:
addr[address+3] = value >> 24;
address += 1;
case 1:
addr[address+2] = value >> 16;
addr[address+1] = value >> 8;
address += 2;
}
address += 1;
break;
} else {
fprintf(stderr, "oof, %s does not use Indirect Indexed.\n", op.mnemonic);
}
break;
}
#if debug
if (!(done & 6)) {
printf("instruction: %s, ", ins);
printf("addrmode: %s, ", adrmode[addrmode]);
#if (!__GLIBC__) || (__TINYC__)
printf("Postfix: %s, ", (postfix != NULL) ? postfix : "none");
#else
printf("Postfix: %s, ", (postfix[0] != '\0') ? postfix : "none");
#endif
printf("Operand: %s, ", (oprand != NULL && !(done & 16)) ? oprand : "none");
printf("Index Register: %s, ", (ir != NULL && !(done & 32)) ? ir : "none");
printf("Address: $%llx\n", address);
}
#endif
}
}
}
}
reslv_fixups();
return 0;
}