#include "opcode.h" #include #include #define MAX_TOK 0x1000 typedef struct tok token ; typedef struct ln line ; typedef struct sym symbol; typedef struct fix fixup ; struct tok { token *next; /* Pointer to the next token. */ uint8_t id; /* Token ID. */ uint8_t type; /* Token type ID. */ /* Token value(s). */ union { symbol *sym; char *str; uint8_t byte ; uint16_t word ; uint32_t dword; uint64_t qword; }; }; struct ln { line *next; /* Pointer to the next line. */ token *tok; /* The token(s) for this line. */ uint16_t count; /* Total tokens for this line. */ uint32_t linenum; /* Line number. */ uint64_t addr; /* The address of this line. */ uint8_t stab; /* Number of starting tabs. */ uint8_t sspace; /* Number of starting spaces. */ uint8_t etab; /* Number of ending tabs. */ uint8_t espace; /* Number of ending spaces. */ }; struct fix { fixup *next; symbol *s; token *t; uint64_t adr; }; struct sym { symbol *next; symbol *local; uint16_t count; uint64_t val; uint8_t def; char *name; uint16_t id; }; extern char lexeme[]; extern char *string[]; extern char *comment[]; extern uint16_t incl[]; extern line *lines; extern line *last_line; extern token *tokens; extern token *last_tok; extern symbol *symbols; extern symbol *locals; extern fixup *fixups; extern uint8_t lex_type; enum dir { DIR_ORG, DIR_BYTE, DIR_WORD, DIR_DWORD, DIR_QWORD, DIR_INCLUDE }; enum token { TOK_DIR, TOK_LOCAL, TOK_LABEL, TOK_SYM, TOK_EXPR, TOK_CSV, TOK_STRING, TOK_CHAR, TOK_IND, TOK_IMM, TOK_OPCODE, TOK_RS, TOK_COMMENT, TOK_HEX, TOK_DEC, TOK_BIN, TOK_INCLUDE }; enum pre_token { PTOK_DOT, PTOK_AT, PTOK_COLON, PTOK_EQU, PTOK_PLUS, PTOK_MINUS, PTOK_GT, PTOK_LT, PTOK_LBRACK, PTOK_RBRACK, PTOK_COMMA, PTOK_X, PTOK_Y, PTOK_DQUOTE, PTOK_SQUOTE, PTOK_HASH, PTOK_SCOLON, PTOK_DOLLAR, PTOK_PERCENT, PTOK_NUMBER, PTOK_ALPHA, PTOK_OTHER }; enum expr { EXPR_PLUS, EXPR_MINUS, EXPR_LOW, EXPR_HIGH, EXPR_NONE }; static const uint8_t opcodes[OPNUM][9] = { /* IMM ZM ZMX ZMY IND INDX INDY ABS IMPL*/ [ 0] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}, [ 1] = {0x01, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0xFF}, [ 2] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x02}, [ 3] = {0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [ 4] = {0x09, 0x2D, 0xFF, 0xFF, 0x55, 0xAD, 0xAC, 0x2C, 0xFF}, [ 5] = {0x0A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [ 6] = {0xFF, 0x0D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0xE5}, [ 7] = {0xFF, 0x0E, 0xFF, 0xFF, 0xCE, 0xFF, 0xFF, 0x10, 0xFF}, [ 8] = {0x11, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x14, 0xFF}, [ 9] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x12}, [10] = {0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [11] = {0x19, 0x3D, 0xFF, 0xFF, 0x85, 0xFF, 0xFF, 0x4C, 0xFF}, [12] = {0x1A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [13] = {0xFF, 0x1D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xF5}, [14] = {0xFF, 0x1E, 0xFF, 0xFF, 0xBE, 0xFF, 0xFF, 0x20, 0xFF}, [15] = {0x21, 0x26, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x24, 0xFF}, [16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x22}, [17] = {0x28, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [18] = {0x29, 0x4D, 0xFF, 0xFF, 0xB5, 0xFF, 0xFF, 0x3C, 0xFF}, [19] = {0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [20] = {0xFF, 0x2E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x30, 0xFF}, [21] = {0x31, 0x36, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x34, 0xFF}, [22] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x32}, [23] = {0x38, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [24] = {0x3A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [25] = {0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x40, 0xFF}, [26] = {0x41, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x44, 0xFF}, [27] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x42}, [28] = {0x48, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [29] = {0x4A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [30] = {0xFF, 0x4E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0xFF}, [31] = {0x51, 0x56, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0xFF}, [32] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x52}, [33] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x58}, [34] = {0x5A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [35] = {0xFF, 0x5E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x60, 0xFF}, [36] = {0x61, 0x66, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x64, 0xFF}, [37] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x62}, [38] = {0x68, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [39] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6A}, [40] = {0xFF, 0x6E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x70, 0xFF}, [41] = {0x71, 0x76, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x74, 0xFF}, [42] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x72}, [43] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x78}, [44] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7A}, [45] = {0xFF, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF}, [46] = {0x81, 0x86, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x84, 0xFF}, [47] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x82}, [48] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x88}, [49] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8A}, [50] = {0xFF, 0x8E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x90, 0xFF}, [51] = {0x91, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x94, 0xFF}, [52] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x92}, [53] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x98}, [54] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A}, [55] = {0xFF, 0x9E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0, 0xFF}, [56] = {0xA1, 0xA6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA4, 0xFF}, [57] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA2}, [58] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA8}, [59] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA}, [60] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE}, [61] = {0xB1, 0xB6, 0xFF, 0xFF, 0x25, 0x7D, 0x7C, 0xB4, 0xFF}, [62] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2}, [63] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8}, [64] = {0xB9, 0xBD, 0xFF, 0xC9, 0x95, 0xFF, 0xFF, 0xBC, 0xFF}, [65] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBA}, [66] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0}, [67] = {0xC1, 0xC6, 0x79, 0x39, 0x05, 0x5D, 0x5C, 0xC4, 0xFF}, [68] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC5}, [69] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC8}, [70] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCA}, [71] = {0xFF, 0xCD, 0x89, 0x49, 0x15, 0x6D, 0x6C, 0xCC, 0xFF}, [72] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0}, [73] = {0xD1, 0xD6, 0x99, 0x59, 0x35, 0x8D, 0x8C, 0xD4, 0xFF}, [74] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5}, [75] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD8}, [76] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDA}, [77] = {0xFF, 0xDD, 0xA9, 0x69, 0x45, 0x9D, 0x9C, 0xDC, 0xFF}, [78] = {0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, [79] = {0xE1, 0xE6, 0xE9, 0xFF, 0x65, 0xFF, 0xFF, 0xE4, 0xFF}, [80] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE8}, [81] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEA}, [82] = {0xFF, 0xED, 0xF9, 0xFF, 0x75, 0xFF, 0xFF, 0xEC, 0xFF}, [83] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE}, [84] = {0xF1, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0xFF}, [85] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2}, [86] = {0xFF, 0xFD, 0xFF, 0xD9, 0xA5, 0xFF, 0xFF, 0xFC, 0xFF}, [87] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE} }; static const char *dir_t[6] = { [0] = "org", [1] = "byte", [2] = "word", [3] = "dword", [4] = "qword", [5] = "include" }; static const char *rs_t[4] = { [0] = "", [1] = ".w", [2] = ".d", [3] = ".q" }; static const char *lex_tok[17] = { [0x00] = "TOK_DIR", [0x01] = "TOK_LOCAL", [0x02] = "TOK_LABEL", [0x03] = "TOK_SYM", [0x04] = "TOK_EXPR", [0x05] = "TOK_CSV", [0x06] = "TOK_STRING", [0x07] = "TOK_CHAR", [0x08] = "TOK_IND", [0x09] = "TOK_IMM", [0x0A] = "TOK_OPCODE", [0x0B] = "TOK_RS", [0x0C] = "TOK_COMMENT", [0x0D] = "TOK_HEX", [0x0E] = "TOK_DEC", [0x0F] = "TOK_BIN", [0x10] = "TOK_INCLUDE" }; static const char *adrmode[9] = { [IMM ] = "IMM", [ZM ] = "ZM", [ZMX ] = "ZMX", [ZMY ] = "ZMY", [IND ] = "IND", [INDX] = "INDX", [INDY] = "INDY", [ABS ] = "ABS", [IMPL] = "IMPL" }; static const char *mne[OPNUM] = { [ 0] = "CPS", [ 1] = "ADC", [ 2] = "AAB", [ 3] = "PHP", [ 4] = "CPB", [ 5] = "PHB", [ 6] = "DEC", [ 7] = "JMP", [ 8] = "SBC", [ 9] = "SAB", [10] = "ENT", [11] = "CPY", [12] = "PLB", [13] = "INC", [14] = "JSR", [15] = "AND", [16] = "ABA", [17] = "PLP", [18] = "CPX", [19] = "PHY", [20] = "BPO", [21] = "ORA", [22] = "OAB", [23] = "STT", [24] = "PLY", [25] = "BNG", [26] = "XOR", [27] = "XAB", [28] = "PHA", [29] = "PHX", [30] = "BCS", [31] = "LSL", [32] = "LLB", [33] = "CLC", [34] = "PLX", [35] = "BCC", [36] = "LSR", [37] = "LRB", [38] = "PLA", [39] = "TAB", [40] = "BEQ", [41] = "ROL", [42] = "RLB", [43] = "SEC", [44] = "TBA", [45] = "BNE", [46] = "ROR", [47] = "RRB", [48] = "DEY", [49] = "TAY", [50] = "BVS", [51] = "MUL", [52] = "MAB", [53] = "CLI", [54] = "TYA", [55] = "BVC", [56] = "DIV", [57] = "DAB", [58] = "INY", [59] = "TAX", [60] = "RTS", [61] = "CMP", [62] = "CAB", [63] = "SEI", [64] = "LDX", [65] = "TXA", [66] = "RTI", [67] = "LDA", [68] = "DEX", [69] = "CLV", [70] = "TYX", [71] = "STA", [72] = "TSX", [73] = "LDB", [74] = "INX", [75] = "WAI", [76] = "TXY", [77] = "STB", [78] = "TXS", [79] = "LDY", [80] = "BRK", [81] = "NOP", [82] = "STY", [83] = "DEB", [84] = "ASR", [85] = "ARB", [86] = "STX", [87] = "INB" }; static const char *instdesc[OPNUM] = { [ 0] = "Clears the Processor Status register.", [ 1] = "ADd accumulator, with operand, Carry if needed.", [ 2] = "Add Accumulator, with B, carry if needed.", [ 3] = "PusH the number of bytes specified, from the Processor status register to the stack.", [ 4] = "ComPare the B register, with operand.", [ 5] = "PusH the number of bytes specified, from the B register to the stack.", [ 6] = "DECrement accumulator, or memory.", [ 7] = "JuMP to the address specified.", [ 8] = "SuBtract accumulator, with operand, Carry if needed", [ 9] = "Subtract Accumulator, with B, carry if needed.", [10] = "ENd a Thread.", [11] = "ComPare the Y register, with operand.", [12] = "PuLl the number of bytes specified, from the stack, to the B register.", [13] = "INCrement accumulator, or memory.", [14] = "Jump to a SubRoutine.", [15] = "Bitwise AND accumulator, with operand.", [16] = "Bitwise AND Accumulator, with B.", [17] = "PuLl the number of bytes specified, from the stack, to the Processor status register.", [18] = "ComPare the X register, with operand.", [19] = "PusH the number of bytes specified, from the Y register to the stack.", [20] = "Branch if POsitive.", [21] = "Bitwise OR Accumulator, with operand.", [22] = "Bitwise OR Accumulator, with B.", [23] = "STart a Thread.", [24] = "PuLl the number of bytes specified, from the stack, to the Y register.", [25] = "Branch if NeGative.", [26] = "Bitwise XOR Accumulator, with operand.", [27] = "Bitwise XOR Accumulator, with B.", [28] = "PusH the number of bytes specified, from the Accumulator to the stack.", [29] = "PusH the number of bytes specified, from the X register to the stack.", [30] = "Branch if the Carry flag is Set.", [31] = "Logical Shift Left accumulator, with operand.", [32] = "Logical Shift Left accumulator, with B.", [33] = "CLear the Carry flag.", [34] = "PuLl the number of bytes specified, from the stack, to the X register.", [35] = "Branch if the Carry flag has been Cleared.", [36] = "Logical Shift Right accumulator, with operand.", [37] = "Logical Shift Right accumulator, with B.", [38] = "PuLl the number of bytes specified, from the stack, to the Accumulator.", [39] = "Transfer the value from the Accumulator, to the B register.", [40] = "Branch if EQual (the zero flag has been set).", [41] = "ROtate Left accumulator, with operand.", [42] = "Rotate Left accumulator, with B.", [43] = "SEt the Carry flag.", [44] = "Transfer the value from the Y register, to the Accumulator.", [45] = "Branch if Not Equal (the zero flag has been cleared)", [46] = "ROtate Right accumulator, with operand.", [47] = "Rotate Right accumulator, with B.", [48] = "DEcrement the Y register.", [49] = "Transfer the value from the Accumulator, to the Y register.", [50] = "Branch if the oVerflow flag is Set.", [51] = "MULtiply accumulator, with operand.", [52] = "Multiply Accumulator, with B.", [53] = "CLear the Interrupt flag.", [54] = "Transfer the value from the Y register, to the Accumulator.", [55] = "Branch if the oVerflow flag has been Cleared.", [56] = "DIVide accumulator, with operand, and put the remainder into the B register.", [57] = "Divide Accumulator, with B, and put the remainder into the X register.", [58] = "INcrement the Y register.", [59] = "Transfer the value from the Accumulator, to the X register.", [60] = "ReTurn from a Subroutine.", [61] = "CoMPare acumulator, with operand.", [62] = "Compare Accumulator, with B.", [63] = "SEt the Interrupt flag.", [64] = "LoaD the value from the operand, to the X register.", [65] = "Transfer the value from the X register, to the Accumulator.", [66] = "ReTurn from an Interrupt.", [67] = "LoaD the value from the operand, to the Accumulator.", [68] = "DEcrement the X register.", [69] = "CLear the oVerflow flag.", [70] = "Transfer the value from the Y register, to the X register.", [71] = "STore the value from the Accumulator, in memory.", [72] = "Transfer the value from the Stack pointer, to the X register.", [73] = "LoaD the value from the operand, to the B register.", [74] = "INcrement the X register.", [75] = "WAIt for an interrupt", [76] = "Transfer the value from the X register, to the Y register.", [77] = "STore the value from the B register, in memory.", [78] = "Transfer the value from the X register, to the Stack pointer.", [79] = "LoaD the value from the operand, to the Y register.", [80] = "BReaKpoint", [81] = "NO oPeration", [82] = "STore the value from the Y register, in memory.", [83] = "DEcrement the B register.", [84] = "Arithmetic Shift Right accumulator, with operand.", [85] = "Arithmetic shift Right accumulator, with B.", [86] = "STore the value from the X register, in memory.", [87] = "INcrement the B register." }; static const uint8_t bitsize[4] = { [0] = 0x07, [1] = 0x0F, [2] = 0x1F, [3] = 0x3F }; static const uint8_t amp[8] = { [0] = 0x00, [1] = 0x00, [2] = 0x07, [4] = 0x07, [5] = 0x0B, [6] = 0x0B, [3] = 0x0F, [7] = 0x0F }; extern uint16_t linenum; extern uint16_t lineidx; extern uint16_t stridx; extern uint16_t comidx; extern uint16_t inc_file; /* Number of included files. */ extern uint16_t inc_count; struct bc { uint64_t progsize; uint64_t datasize; }; typedef struct bc bytecount; extern uint8_t defined; extern uint8_t isfixup; extern line *find_line(uint32_t ln, uint8_t dbg); extern uint64_t lex(char *str, uint64_t address, uint8_t dbg); extern uint64_t parse_tokens(token *tm, bytecount *bc, uint8_t isasm, uint64_t address, uint8_t dbg); extern token *make_token(uint8_t id, uint8_t type, uint64_t value, char *str, symbol *sym); extern void assemble(line *ln, bytecount *bc, uint8_t dbg); extern void cleanup();