| @@ -44,6 +44,13 @@ | |||||
| #define INST_PREFIX_(reg) \ | #define INST_PREFIX_(reg) \ | ||||
| (((reg) == REG_IX || (reg) == REG_IXH || (reg) == REG_IXL) ? 0xDD : 0xFD) | (((reg) == REG_IX || (reg) == REG_IXH || (reg) == REG_IXL) ? 0xDD : 0xFD) | ||||
| #define INST_RETURN_WITH_SYMBOL_(len, label, ...) { \ | |||||
| *symbol = cr_strdup(label.text); \ | |||||
| INST_ALLOC_(len) \ | |||||
| INST_FILL_BYTES_(len - 2, __VA_ARGS__) \ | |||||
| return ED_NONE; \ | |||||
| } | |||||
| /* Helper macros for instruction parsers */ | /* Helper macros for instruction parsers */ | ||||
| #define INST_FUNC(mnemonic) \ | #define INST_FUNC(mnemonic) \ | ||||
| @@ -102,18 +109,18 @@ static ASMErrorDesc parse_inst_##mnemonic( \ | |||||
| return ED_NONE; \ | return ED_NONE; \ | ||||
| } | } | ||||
| #define INST_RETURN_WITH_SYMBOL(len, label, ...) { \ | |||||
| *symbol = cr_strdup(label); \ | |||||
| INST_ALLOC_(len) \ | |||||
| INST_FILL_BYTES_(len - 2, __VA_ARGS__) \ | |||||
| return ED_NONE; \ | |||||
| } | |||||
| #define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg) | #define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg) | ||||
| #define INST_INDEX_BYTES(n, b) \ | #define INST_INDEX_BYTES(n, b) \ | ||||
| INST_INDEX_PREFIX(n), b, INST_INDEX(n).offset | INST_INDEX_PREFIX(n), b, INST_INDEX(n).offset | ||||
| #define INST_INDIRECT_IMM(n) \ | |||||
| INST_INDIRECT(n).addr.imm.uval >> 8, \ | |||||
| INST_INDIRECT(n).addr.imm.uval & 0xFF | |||||
| #define INST_RETURN_INDIRECT_LABEL(n, len, ...) \ | |||||
| INST_RETURN_WITH_SYMBOL_(len, INST_INDIRECT(n).addr.label, __VA_ARGS__) | |||||
| /* | /* | ||||
| Fill an instruction's byte array with the given data. | Fill an instruction's byte array with the given data. | ||||
| @@ -537,7 +544,49 @@ INST_FUNC(ld) | |||||
| switch (INST_TYPE(0)) { | switch (INST_TYPE(0)) { | ||||
| case AT_REGISTER: | case AT_REGISTER: | ||||
| switch (INST_REG(0)) { | switch (INST_REG(0)) { | ||||
| case REG_A: // TODO (20 cases) | |||||
| case REG_A: | |||||
| switch (INST_TYPE(1)) { | |||||
| case AT_REGISTER: | |||||
| switch (INST_REG(1)) { | |||||
| case REG_A: INST_RETURN(1, 0x7F) | |||||
| case REG_B: INST_RETURN(1, 0x78) | |||||
| case REG_C: INST_RETURN(1, 0x79) | |||||
| case REG_D: INST_RETURN(1, 0x7A) | |||||
| case REG_E: INST_RETURN(1, 0x7B) | |||||
| case REG_H: INST_RETURN(1, 0x7C) | |||||
| case REG_L: INST_RETURN(1, 0x7D) | |||||
| case REG_I: INST_RETURN(2, 0xED, 0x57) | |||||
| case REG_R: INST_RETURN(2, 0xED, 0x5F) | |||||
| case REG_IXH: INST_RETURN(2, 0xDD, 0x7C) | |||||
| case REG_IXL: INST_RETURN(2, 0xDD, 0x7D) | |||||
| case REG_IYH: INST_RETURN(2, 0xFD, 0x7C) | |||||
| case REG_IYL: INST_RETURN(2, 0xFD, 0x7D) | |||||
| default: INST_ERROR(ARG1_BAD_REG) | |||||
| } | |||||
| case AT_IMMEDIATE: | |||||
| INST_CHECK_IMM(1, IMM_U8) | |||||
| INST_RETURN(2, 0x3E, INST_IMM(1).uval) | |||||
| case AT_INDIRECT: | |||||
| switch (INST_INDIRECT(1).type) { | |||||
| case AT_REGISTER: | |||||
| switch (INST_INDIRECT(1).addr.reg) { | |||||
| case REG_BC: INST_RETURN(1, 0x0A) | |||||
| case REG_DE: INST_RETURN(1, 0x1A) | |||||
| case REG_HL: INST_RETURN(1, 0x7E) | |||||
| default: INST_ERROR(ARG0_BAD_REG) | |||||
| } | |||||
| case AT_IMMEDIATE: | |||||
| INST_RETURN(3, 0x3A, INST_INDIRECT_IMM(1)) | |||||
| case AT_LABEL: | |||||
| INST_RETURN_INDIRECT_LABEL(1, 3, 0x3A) | |||||
| default: | |||||
| INST_ERROR(ARG0_TYPE) | |||||
| } | |||||
| case AT_INDEXED: | |||||
| INST_RETURN(3, INST_INDEX_BYTES(1, 0x7E)) | |||||
| default: | |||||
| INST_ERROR(ARG1_TYPE) | |||||
| } | |||||
| case REG_B: // TODO (15 cases) | case REG_B: // TODO (15 cases) | ||||
| case REG_C: // TODO (15 cases) | case REG_C: // TODO (15 cases) | ||||
| case REG_D: // TODO (15 cases) | case REG_D: // TODO (15 cases) | ||||