Assuming there will be a secondary operand byte isn't wise (think of single-byte opcodes like NOP, LSR A, ASL A, etc.). I can't really describe this to you in text easily, but:
Code:
enum addressingmode_e {
MODE_IMPLIED,
MODE_IMMEDIATE,
MODE_ZP,
MODE_ABSOLUTE,
MODE_INDIRECT_INDEXED,
MODE_INDEXED_INDIRECT,
MODE_INDIRECT,
MODE_UNUSED
};
struct opcode_t {
const char *opcodestring; /* opcode string; NULL if an unused opcode */
uint16_t addressingmode; /* see enum addressingmode_e */
uint16_t operandsize; /* number of literal operand byte size */
uint16_t features; /* spare field; use these for internal control/features/etc., as a bitmask */
};
const struct opcode_t opcodetable = {
/* 0x00: BRK imm */ { "BRK", MODE_IMMEDIATE, 1, NULL }, /* note immediate syntax quirk */
/* 0x01: ORA (zp,x) */ { "ORA", MODE_INDEXED_INDIRECT, 1, NULL },
/* 0x02: unused /* { NULL, MODE_UNUSED, 0, NULL },
/* 0x03: unused /* { NULL, MODE_UNUSED, 0, NULL },
/* 0x04: unused /* { NULL, MODE_UNUSED, 0, NULL },
/* 0x05: ORA zp /* { "ORA", MODE_ZP, 1, NULL },
/* 0x06: ASL zp /* { "ASL", MODE_ZP, 1, NULL },
/* 0x07: unused /* { NULL, MODE_UNUSED, 0, NULL },
/* 0x08: PHP /* { "PHP", MODE_IMPLIED, 0, NULL },
/* 0x09: ORA imm /* { "ORA", MODE_IMMEDIATE, 1, NULL },
/* 0x0a: ASL /* { "ASL", MODE_IMPLIED, 1, NULL },
/* 0x0b: unused /* { NULL, MODE_UNUSED, 0, NULL },
/* 0x0c: unused /* { NULL, MODE_UNUSED, 0, NULL },
/* 0x0d: ORA abs /* { "ORA", MODE_ABSOLUTE, 2, NULL },
/* 0x0e: ASL abs /* { "ASL", MODE_ABSOLUTE, 2, NULL },
/* 0x0f: unused /* { NULL, MODE_UNUSED, 0, NULL },
...
};
For BRK, using the features bitmask would help, for example, to allow a syntax one-off for "BRK $xxx" syntax too, rather than what's normally expected for MODE_IMMEDIATE (which is usually some form of hexadecimal or decimal value preceded by "#", or a label, etc...). Alternately you could get around this by using, say, MODE_ABSOLUTE for BRK, with an operand size of 1, but you'd need to handle that in the subroutine for handling MODE_ABSOLUTE. Your call.
You get the idea I hope.
P.S. -- You're entering a very painful arena writing an assembler. Prepare for massive amounts of string parsing and syntax pain. Disassemblers = easier. ;-)