From 3d968c12b5059db62d5b217802670885b16b0325 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sun, 10 May 2015 00:57:54 -0500 Subject: [PATCH] Add more to load instruction. --- src/assembler/inst_support.h | 48 +++++++++++++++++++++------- src/assembler/instructions.c | 76 +++++++++++++++++++++----------------------- 2 files changed, 73 insertions(+), 51 deletions(-) diff --git a/src/assembler/inst_support.h b/src/assembler/inst_support.h index 34bfcae..ce282cd 100644 --- a/src/assembler/inst_support.h +++ b/src/assembler/inst_support.h @@ -24,7 +24,7 @@ #define HANDLE(m) if (key == MAKE_CMP_(#m)) return parse_inst_##m; -/* Internal helper macros for instruction parsers */ +/* Internal helper macros */ #define INST_ALLOC_(len) \ *length = len; \ @@ -43,8 +43,12 @@ INST_DISPATCH_(__VA_ARGS__, INST_SET4_, INST_SET3_, INST_SET2_, \ INST_SET1_, __VA_ARGS__)(__VA_ARGS__)); +#define INST_IX_PREFIX_ 0xDD +#define INST_IY_PREFIX_ 0xFD + #define INST_PREFIX_(reg) \ - (((reg) == REG_IX || (reg) == REG_IXH || (reg) == REG_IXL) ? 0xDD : 0xFD) + (((reg) == REG_IX || (reg) == REG_IXH || (reg) == REG_IXL) ? \ + INST_IX_PREFIX_ : INST_IY_PREFIX_) #define INST_RETURN_WITH_SYMBOL_(len, label, ...) { \ *symbol = cr_strdup(label.text); \ @@ -53,7 +57,7 @@ return ED_NONE; \ } -/* Helper macros for instruction parsers */ +/* Essential/basic helper macros */ #define INST_FUNC(mnemonic) \ static ASMErrorDesc parse_inst_##mnemonic( \ @@ -87,6 +91,15 @@ static ASMErrorDesc parse_inst_##mnemonic( \ #define INST_LABEL(n) args[n].data.label #define INST_COND(n) args[n].data.cond +#define INST_RETURN(len, ...) { \ + (void) symbol; \ + INST_ALLOC_(len) \ + INST_FILL_BYTES_(len, __VA_ARGS__) \ + return ED_NONE; \ + } + +/* Convenience macros */ + #define INST_FORCE_TYPE(n, t) { \ if (INST_TYPE(n) != t) \ INST_ERROR(ARG##n##_TYPE) \ @@ -97,6 +110,13 @@ static ASMErrorDesc parse_inst_##mnemonic( \ INST_ERROR(ARG##n##_RANGE) \ } +#define INST_REG_ONLY(n, reg) { \ + if (INST_TYPE(n) != AT_REGISTER) \ + INST_ERROR(ARG##n##_TYPE) \ + if (INST_REG(n) != reg) \ + INST_ERROR(ARG##n##_BAD_REG) \ + } + #define INST_INDIRECT_HL_ONLY(n) { \ if (INST_INDIRECT(n).type != AT_REGISTER) \ INST_ERROR(ARG##n##_TYPE) \ @@ -104,13 +124,6 @@ static ASMErrorDesc parse_inst_##mnemonic( \ INST_ERROR(ARG##n##_BAD_REG) \ } -#define INST_RETURN(len, ...) { \ - (void) symbol; \ - INST_ALLOC_(len) \ - INST_FILL_BYTES_(len, __VA_ARGS__) \ - return ED_NONE; \ - } - #define INST_INDEX_PREFIX(n) INST_PREFIX_(INST_INDEX(n).reg) #define INST_INDEX_BYTES(n, b) \ @@ -123,7 +136,20 @@ static ASMErrorDesc parse_inst_##mnemonic( \ #define INST_RETURN_INDIRECT_LABEL(n, len, ...) \ INST_RETURN_WITH_SYMBOL_(len, INST_INDIRECT(n).addr.label, __VA_ARGS__) -/* Functions */ +#define INST_HANDLE_MAIN_8_BIT_REGS(base) \ + case REG_A: INST_RETURN(1, base + 7) \ + case REG_B: INST_RETURN(1, base) \ + case REG_C: INST_RETURN(1, base + 1) \ + case REG_D: INST_RETURN(1, base + 2) \ + case REG_E: INST_RETURN(1, base + 3) \ + case REG_H: INST_RETURN(1, base + 4) \ + case REG_L: INST_RETURN(1, base + 5) \ + case REG_IXH: INST_RETURN(2, INST_IX_PREFIX_, base + 4) \ + case REG_IXL: INST_RETURN(2, INST_IX_PREFIX_, base + 5) \ + case REG_IYH: INST_RETURN(2, INST_IY_PREFIX_, base + 4) \ + case REG_IYL: INST_RETURN(2, INST_IY_PREFIX_, base + 5) \ + +/* Internal functions */ uint8_t fill_bytes_variadic(uint8_t*, size_t, ...); ASMErrorDesc parse_args(ASMInstArg args[3], size_t*, ASMArgParseInfo); diff --git a/src/assembler/instructions.c b/src/assembler/instructions.c index b80c3f2..652e210 100644 --- a/src/assembler/instructions.c +++ b/src/assembler/instructions.c @@ -15,17 +15,7 @@ INST_FUNC(adc) switch (INST_TYPE(1)) { case AT_REGISTER: switch (INST_REG(1)) { - case REG_A: INST_RETURN(1, 0x8F) - case REG_B: INST_RETURN(1, 0x88) - case REG_C: INST_RETURN(1, 0x89) - case REG_D: INST_RETURN(1, 0x8A) - case REG_E: INST_RETURN(1, 0x8B) - case REG_H: INST_RETURN(1, 0x8C) - case REG_L: INST_RETURN(1, 0x8D) - case REG_IXH: INST_RETURN(2, 0xDD, 0x8C) - case REG_IXL: INST_RETURN(2, 0xDD, 0x8D) - case REG_IYH: INST_RETURN(2, 0xFD, 0x8C) - case REG_IYL: INST_RETURN(2, 0xFD, 0x8D) + INST_HANDLE_MAIN_8_BIT_REGS(0x88) default: INST_ERROR(ARG1_BAD_REG) } case AT_IMMEDIATE: @@ -62,17 +52,7 @@ INST_FUNC(add) switch (INST_TYPE(1)) { case AT_REGISTER: switch (INST_REG(1)) { - case REG_A: INST_RETURN(1, 0x87) - case REG_B: INST_RETURN(1, 0x80) - case REG_C: INST_RETURN(1, 0x81) - case REG_D: INST_RETURN(1, 0x82) - case REG_E: INST_RETURN(1, 0x83) - case REG_H: INST_RETURN(1, 0x84) - case REG_L: INST_RETURN(1, 0x85) - case REG_IXH: INST_RETURN(2, 0xDD, 0x84) - case REG_IXL: INST_RETURN(2, 0xDD, 0x85) - case REG_IYH: INST_RETURN(2, 0xFD, 0x84) - case REG_IYL: INST_RETURN(2, 0xFD, 0x85) + INST_HANDLE_MAIN_8_BIT_REGS(0x80) default: INST_ERROR(ARG1_BAD_REG) } case AT_IMMEDIATE: @@ -329,6 +309,7 @@ INST_FUNC(jr) INST_FUNC(ld) { + uint8_t base; INST_TAKES_ARGS(2, 2) switch (INST_TYPE(0)) { case AT_REGISTER: @@ -337,19 +318,9 @@ INST_FUNC(ld) 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) + INST_HANDLE_MAIN_8_BIT_REGS(0x78) 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: @@ -369,21 +340,46 @@ INST_FUNC(ld) case AT_LABEL: INST_RETURN_INDIRECT_LABEL(1, 3, 0x3A) default: - INST_ERROR(ARG0_TYPE) + INST_ERROR(ARG1_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_C: // TODO (15 cases) - case REG_D: // TODO (15 cases) - case REG_E: // TODO (15 cases) + case REG_B: + base = 0x00; + case REG_C: + base = 0x08; + case REG_D: + base = 0x10; + case REG_E: + base = 0x18; + switch (INST_TYPE(1)) { + case AT_REGISTER: + switch (INST_REG(1)) { + INST_HANDLE_MAIN_8_BIT_REGS(base + 0x40) + default: INST_ERROR(ARG1_BAD_REG) + } + case AT_IMMEDIATE: + INST_CHECK_IMM(1, IMM_U8) + INST_RETURN(2, base + 0x06, INST_IMM(1).uval) + case AT_INDIRECT: + INST_INDIRECT_HL_ONLY(1) + INST_RETURN(1, base + 0x46) + case AT_INDEXED: + INST_RETURN(3, INST_INDEX_BYTES(1, base + 0x46)) + default: + INST_ERROR(ARG1_TYPE) + } case REG_H: // TODO (11 cases) case REG_L: // TODO (11 cases) - case REG_I: // TODO ( 1 case ) - case REG_R: // TODO ( 1 case ) + case REG_I: + INST_REG_ONLY(1, REG_A) + INST_RETURN(2, 0xED, 0x47) + case REG_R: + INST_REG_ONLY(1, REG_A) + INST_RETURN(2, 0xED, 0x4F) case REG_BC: // TODO ( 2 cases) case REG_DE: // TODO ( 2 cases) case REG_HL: // TODO ( 3 cases)