Browse Source

Add more to load instruction.

master
Ben Kurtovic 9 years ago
parent
commit
3d968c12b5
2 changed files with 73 additions and 51 deletions
  1. +37
    -11
      src/assembler/inst_support.h
  2. +36
    -40
      src/assembler/instructions.c

+ 37
- 11
src/assembler/inst_support.h View File

@@ -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);

+ 36
- 40
src/assembler/instructions.c View File

@@ -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)


Loading…
Cancel
Save