static uint16_t ea_indexed(struct MC6809 *cpu) { unsigned ea; unsigned postbyte; uint16_t *reg; postbyte = byte_immediate(cpu); switch ((postbyte >> 5) & 3) { case 0: reg = ®_X; break; case 1: reg = ®_Y; break; case 2: reg = ®_U; break; case 3: reg = ®_S; break; default: return 0; } if ((postbyte & 0x80) == 0) { peek_byte(cpu, REG_PC); NVMA_CYCLE; return *reg + sex5(postbyte & 0x1f); } switch (postbyte & 0x0f) { case 0x00: ea = *reg; *reg += 1; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; break; case 0x01: ea = *reg; *reg += 2; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; case 0x02: *reg -= 1; ea = *reg; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; break; case 0x03: *reg -= 2; ea = *reg; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; case 0x04: ea = *reg; peek_byte(cpu, REG_PC); break; case 0x05: ea = *reg + sex8(RREG_B); peek_byte(cpu, REG_PC); NVMA_CYCLE; break; case 0x07: // illegal case 0x06: ea = *reg + sex8(RREG_A); peek_byte(cpu, REG_PC); NVMA_CYCLE; break; case 0x08: ea = byte_immediate(cpu); ea = sex8(ea) + *reg; NVMA_CYCLE; break; case 0x09: ea = word_immediate(cpu); ea = ea + *reg; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; case 0x0a: ea = REG_PC | 0xff; break; case 0x0b: ea = *reg + REG_D; peek_byte(cpu, REG_PC); peek_byte(cpu, REG_PC + 1); NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; case 0x0c: ea = byte_immediate(cpu); ea = sex8(ea) + REG_PC; NVMA_CYCLE; break; case 0x0d: ea = word_immediate(cpu); ea = ea + REG_PC; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; case 0x0e: ea = 0xffff; break; // illegal case 0x0f: ea = word_immediate(cpu); NVMA_CYCLE; break; default: ea = 0; break; } if (postbyte & 0x10) { unsigned tmp_ea = fetch_byte(cpu, ea) << 8; ea = tmp_ea | fetch_byte(cpu, ea + 1); NVMA_CYCLE; } return ea; }
void m6809_trace_byte(unsigned int byte, unsigned int pc) { static int ins_type = PAGE0; static unsigned int byte_val = 0, word_val = 0; static int indexed_mode = 0; static const char *indexed_fmt; static unsigned int indexed_flags; byte &= 0xff; pc &= 0xffff; if (bytes_count == 0) { instr_pc = pc; } if (bytes_count < BYTES_BUF_SIZE && state != WANT_PRINT) { bytes_buf[bytes_count++] = byte; } switch (state) { default: case WANT_INSTRUCTION: mnemonic = instructions[page][byte].mnemonic; ins_type = instructions[page][byte].type; switch (ins_type) { case PAGE2: case PAGE3: page = ins_type; break; default: case ILLEGAL: case INHERENT: state = WANT_PRINT; break; case IMMEDIATE: case DIRECT: case RELATIVE: case STACKS: case STACKU: case REGISTER: case INDEXED: state = WANT_BYTE; break; case WORD_IMMEDIATE: case EXTENDED: case LONG_RELATIVE: state = WANT_WORD1; break; } break; case WANT_IRQVEC1: mnemonic = irq_names[irq_vector]; ins_type = IRQVECTOR; state = WANT_IRQVEC2; break; case WANT_IRQVEC2: state = WANT_PRINT; break; case WANT_BYTE: if (ins_type == INDEXED && indexed_mode == 0) { indexed_mode = byte; if ((indexed_mode & 0x80) == 0) { state = WANT_PRINT; break; } indexed_fmt = indexed_modes[byte & 0x0f].fmt; indexed_flags = indexed_modes[byte & 0x0f].flags; if (indexed_flags & INDEXED_WANT_WORD) { state = WANT_WORD1; } else if (indexed_flags & INDEXED_WANT_BYTE) { state = WANT_BYTE; } else { state = WANT_PRINT; } } else { byte_val = byte; state = WANT_PRINT; } break; case WANT_WORD1: word_val = byte; state = WANT_WORD2; break; case WANT_WORD2: word_val = (word_val << 8) | byte; state = WANT_PRINT; break; case WANT_PRINT: /* Now waiting for a call to m6809_trace_print() */ return; } /* If state got set to WANT_PRINT, create the operand text */ if (state != WANT_PRINT) return; operand_text[0] = '\0'; switch (ins_type) { case ILLEGAL: case INHERENT: break; case IMMEDIATE: snprintf(operand_text, sizeof(operand_text), "#$%02x", byte_val); break; case DIRECT: snprintf(operand_text, sizeof(operand_text), "<$%02x", byte_val); break; case WORD_IMMEDIATE: snprintf(operand_text, sizeof(operand_text), "#$%04x", word_val); break; case EXTENDED: snprintf(operand_text, sizeof(operand_text), "$%04x", word_val); break; case STACKS: { int not_first = 0; if (byte_val & 0x01) { STACK_PRINT("CC"); } if (byte_val & 0x02) { STACK_PRINT("A"); } if (byte_val & 0x04) { STACK_PRINT("B"); } if (byte_val & 0x08) { STACK_PRINT("DP"); } if (byte_val & 0x10) { STACK_PRINT("X"); } if (byte_val & 0x20) { STACK_PRINT("Y"); } if (byte_val & 0x40) { STACK_PRINT("U"); } if (byte_val & 0x80) { STACK_PRINT("PC"); } } break; case STACKU: { int not_first = 0; if (byte_val & 0x01) { STACK_PRINT("CC"); } if (byte_val & 0x02) { STACK_PRINT("A"); } if (byte_val & 0x04) { STACK_PRINT("B"); } if (byte_val & 0x08) { STACK_PRINT("DP"); } if (byte_val & 0x10) { STACK_PRINT("X"); } if (byte_val & 0x20) { STACK_PRINT("Y"); } if (byte_val & 0x40) { STACK_PRINT("S"); } if (byte_val & 0x80) { STACK_PRINT("PC"); } } break; case REGISTER: snprintf(operand_text, sizeof(operand_text), "%s,%s", tfr_regs[(byte_val&0xf0)>>4], tfr_regs[byte_val&0x0f]); break; case INDEXED: { const char *reg = indexed_regs[(indexed_mode>>5)&3]; const char *pre = ""; const char *post = ""; int value = word_val; if (indexed_flags & INDEXED_WANT_BYTE) value = byte_val; if ((indexed_mode & 0x80) == 0) { value = sex5(indexed_mode & 0x1f); snprintf(operand_text, sizeof(operand_text), "%d,%s", value, reg); break; } if (indexed_mode & 0x10) { pre = "["; post = "]"; } if (indexed_flags & (INDEXED_WANT_WORD | INDEXED_WANT_BYTE)) { if (indexed_flags & INDEXED_WANT_REG) { snprintf(operand_text, sizeof(operand_text), indexed_fmt, pre, value, reg, post); } else { snprintf(operand_text, sizeof(operand_text), indexed_fmt, pre, value, post); } } else { if (indexed_flags & INDEXED_WANT_REG) { snprintf(operand_text, sizeof(operand_text), indexed_fmt, pre, reg, post); } else { snprintf(operand_text, sizeof(operand_text), indexed_fmt, pre, post); } } } break; case RELATIVE: pc += (byte_val & 0x80) ? 0xff00 : 0; pc += 1 + byte_val; pc &= 0xffff; snprintf(operand_text, sizeof(operand_text), "$%04x", pc); break; case LONG_RELATIVE: pc += 1 + word_val; pc &= 0xffff; snprintf(operand_text, sizeof(operand_text), "$%04x", pc); break; case IRQVECTOR: trace_print_short(); break; default: break; } indexed_mode = 0; byte_val = word_val = 0; }