void* callBack::registerCCall(int index) { void* result = malloc(10); char* chunk = (char*) result; // MOV ECX, index chunk = store_byte(chunk, '\xB9'); chunk = store_long(chunk, index); // JMP _handleCCallStub chunk = store_byte(chunk, '\xE9'); chunk = store_long(chunk, ((long)StubRoutines::handle_C_callback_stub()) - (4 + (long) chunk)); return result; }
void FileAccess::store_word(Uint16 p_dest) { ERR_FAIL_COND(!f); ERR_FAIL_COND( !(current_mode&WRITE ) ); Uint8 aux_byte1,aux_byte2; aux_byte1=p_dest & 0xFF; aux_byte2=p_dest >> 8; // endian_swap(aux_byte1,aux_byte2); store_byte(aux_byte1); store_byte(aux_byte2); }
void _styAbsl(void) { word addr; addr = fetch_word((word)(cpu.pc + 1)); store_byte(addr, cpu.y); cpu.pc += 3; }
/** * Tests 'store_byte()' and 'get_byte()'. */ void test_store_get_byte() { allocate(); uint8_t dummy_value = 0xAB; store_byte(ram, DUMMY_OFFSET, dummy_value); CU_ASSERT(dummy_value == get_byte(ram, DUMMY_OFFSET)); deallocate(); }
void _staAby(void) { word addr; addr = fetch_word((word)(cpu.pc + 1)); addr += cpu.y; store_byte(addr, cpu.a); cpu.pc += 3; }
/* * push a value onto the stack */ void push(byte c) { if (cpu.sp == STACKEND) { warning("stack overflow error.\n"); err = 1; return; } store_byte((word)(PAGEONE + cpu.sp--), c); }
void* callBack::registerPascalCall(int index, int nofArgs) { void* result = malloc(15); char* chunk = (char*) result; // MOV ECX, index chunk = store_byte(chunk, '\xB9'); chunk = store_long(chunk, index); // MOV EDX, number of bytes for parameters chunk = store_byte(chunk, '\xBA'); chunk = store_long(chunk, nofArgs * sizeof(int)); // JMP _handleCCallStub chunk = store_byte(chunk, '\xE9'); chunk = store_long(chunk, ((long)StubRoutines::handle_pascal_callback_stub()) - (4 + (long) chunk)); return result; }
void _stxZpy(void) { byte zaddr; zaddr = fetch_byte((word)(cpu.pc + 1)); zaddr += cpu.y; store_byte(zaddr, cpu.x); cpu.pc += 2; }
void _styZpx(void) { byte zaddr; zaddr = fetch_byte((word)(cpu.pc + 1)); zaddr += cpu.x; store_byte(zaddr, cpu.y); cpu.pc += 2; }
void _staZp(void) { byte zaddr; zaddr = fetch_byte((word)(cpu.pc + 1)); store_byte(zaddr, cpu.a); cpu.pc += 2; }
void _staIdx(void) { byte zaddr; word addr; zaddr = fetch_byte((word)(cpu.pc + 1)); zaddr += cpu.x; addr = fetch_word(zaddr); store_byte(addr, cpu.a); cpu.pc += 2; }
void _staIdy(void) { byte zaddr; word addr; zaddr = fetch_byte((word)(cpu.pc + 1)); addr = fetch_word(zaddr) + cpu.y; store_byte(addr, cpu.a); cpu.pc += 2; }
/** * @brief Obsluha preruseni UART * @param None * @retval None */ void USART1_IRQHandler() { volatile unsigned int StatusValue; StatusValue = USART1->SR; if (StatusValue & USART_SR_RXNE) { store_byte(USART1->DR); } if (0 != (StatusValue & USART_SR_TXE)) { send_next(); } };
void _decZp(void) { byte addr; word res; addr = fetch_byte((word)(cpu.pc + 1)); res = fetch_byte(addr); res = (res - 1) & 0xFF; store_byte(addr, (byte)res); set_nz(res); cpu.pc += 2; }
void _decAbsl(void) { word addr; word res; addr = fetch_word((word)(cpu.pc + 1)); res = fetch_byte(addr); res = (res - 1) & 0xFF; store_byte(addr, (byte)res); set_nz(res); cpu.pc += 3; }
void _incAbx(void) { word addr; word res; addr = fetch_word((word)(cpu.pc + 1)); addr += cpu.x; res = fetch_byte(addr); res = (res + 1) & 0xFF; store_byte(addr, (byte)res); set_nz(res); cpu.pc += 3; }
void _incZpx(void) { byte addr; word res; addr = fetch_byte((word)(cpu.pc + 1)); addr += cpu.x; res = fetch_byte(addr); res = (res + 1) & 0xFF; store_byte(addr, (byte)res); set_nz(res); cpu.pc += 2; }
void program_interrupt (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, SIM_SIGNAL sig) { int status; struct hw *device; static int in_interrupt = 0; #ifdef SIM_CPU_EXCEPTION_TRIGGER SIM_CPU_EXCEPTION_TRIGGER(sd,cpu,cia); #endif /* avoid infinite recursion */ if (in_interrupt) { (*mn10300_callback->printf_filtered) (mn10300_callback, "ERROR: recursion in program_interrupt during software exception dispatch."); } else { in_interrupt = 1; /* copy NMI handler code from dv-mn103cpu.c */ store_word (SP - 4, CPU_PC_GET (cpu)); store_half (SP - 8, PSW); /* Set the SYSEF flag in NMICR by backdoor method. See dv-mn103int.c:write_icr(). This is necessary because software exceptions are not modelled by actually talking to the interrupt controller, so it cannot set its own SYSEF flag. */ if ((NULL != board) && (strcmp(board, BOARD_AM32) == 0)) store_byte (0x34000103, 0x04); } PSW &= ~PSW_IE; SP = SP - 8; CPU_PC_SET (cpu, 0x40000008); in_interrupt = 0; sim_engine_halt(sd, cpu, NULL, cia, sim_stopped, sig); }
/** * A utility function to avoid duplication when testing push() implementations. * * @param pop_value TODO * @param push_mode TODO * @param storage_location TODO * @param source_location TODO */ void push_test_util(uint32_t pop_value, uint8_t push_mode, uint32_t storage_location, int source_location) { allocate(); if (storage_location != IMMEDIATE) { if (storage_location == NEXT2_INSTR) store_dword(ram, NEXT_INSTR, NEXT2_INSTR); if (source_location == SOURCE_IMMEDIATE && storage_location == NEXT3_INSTR) { store_dword(ram, NEXT_INSTR, NEXT2_INSTR); store_dword(ram, NEXT2_INSTR, NEXT3_INSTR); } else if (source_location == SOURCE_REGISTER) r[TEST_REGISTER] = NEXT_INSTR; } switch (pop_value) { case DUMMY_VALUE_8: if (source_location == SOURCE_IMMEDIATE) { store_byte(ram, storage_location, DUMMY_VALUE_8); exec(create_instruction(INSTR_PUSH, push_mode, EMPTY_BYTE, DUMMY_VALUE_8)); } else if (source_location == SOURCE_REGISTER) { if (storage_location == IMMEDIATE) r[TEST_REGISTER] = DUMMY_VALUE_8; else store_byte(ram, storage_location, DUMMY_VALUE_8); } break; case DUMMY_VALUE_16: if (source_location == SOURCE_IMMEDIATE) { store_word(ram, storage_location, DUMMY_VALUE_16); exec(create_instruction(INSTR_PUSH, push_mode, DUMMY_VALUE_8, DUMMY_VALUE_8)); } else if (source_location == SOURCE_REGISTER) { if (storage_location == IMMEDIATE) r[TEST_REGISTER] = DUMMY_VALUE_16; else store_word(ram, storage_location, DUMMY_VALUE_16); } break; case DUMMY_VALUE_32: if (source_location == SOURCE_IMMEDIATE) { store_dword(ram, storage_location, DUMMY_VALUE_32); exec(create_instruction(INSTR_PUSH, push_mode, EMPTY_BYTE, EMPTY_BYTE)); } else if (source_location == SOURCE_REGISTER) { if (storage_location == IMMEDIATE) r[TEST_REGISTER] = DUMMY_VALUE_32; else store_dword(ram, storage_location, DUMMY_VALUE_32); } break; default: CU_FAIL("Invalid pop_value"); } if (source_location == SOURCE_REGISTER) exec(create_instruction(INSTR_PUSH, push_mode, EMPTY_BYTE, TEST_REGISTER)); CU_ASSERT(pop_value == pop()); deallocate(); }
static void mc6809_run(struct MC6809 *cpu) { do { _Bool nmi_active = cpu->nmi && ((cpu->cycle - cpu->nmi_cycle) <= (UINT_MAX/2)); _Bool firq_active = cpu->firq && ((cpu->cycle - cpu->firq_cycle) <= (UINT_MAX/2)); _Bool irq_active = cpu->irq && ((cpu->cycle - cpu->irq_cycle) <= (UINT_MAX/2)); // Prevent overflow if (firq_active) cpu->firq_cycle = cpu->cycle; if (irq_active) cpu->irq_cycle = cpu->cycle; switch (cpu->state) { case mc6809_state_reset: REG_DP = 0; REG_CC |= (CC_F | CC_I); cpu->nmi = 0; cpu->nmi_armed = 0; cpu->state = mc6809_state_reset_check_halt; // fall through case mc6809_state_reset_check_halt: if (cpu->halt) { NVMA_CYCLE; continue; } REG_PC = fetch_byte(cpu, MC6809_INT_VEC_RESET) << 8; REG_PC |= fetch_byte(cpu, MC6809_INT_VEC_RESET + 1); NVMA_CYCLE; cpu->state = mc6809_state_label_a; continue; // done_instruction case for backwards-compatibility case mc6809_state_done_instruction: case mc6809_state_label_a: if (cpu->halt) { NVMA_CYCLE; continue; } cpu->state = mc6809_state_label_b; // fall through case mc6809_state_label_b: if (cpu->nmi_armed && nmi_active) { peek_byte(cpu, REG_PC); peek_byte(cpu, REG_PC); stack_irq_registers(cpu, 1); cpu->state = mc6809_state_dispatch_irq; continue; } if (!(REG_CC & CC_F) && firq_active) { peek_byte(cpu, REG_PC); peek_byte(cpu, REG_PC); stack_irq_registers(cpu, 0); cpu->state = mc6809_state_dispatch_irq; continue; } if (!(REG_CC & CC_I) && irq_active) { peek_byte(cpu, REG_PC); peek_byte(cpu, REG_PC); stack_irq_registers(cpu, 1); cpu->state = mc6809_state_dispatch_irq; continue; } cpu->state = mc6809_state_next_instruction; // Instruction fetch hook called here so that machine // can be stopped beforehand. DELEGATE_SAFE_CALL0(cpu->instruction_hook); continue; case mc6809_state_dispatch_irq: if (cpu->nmi_armed && nmi_active) { cpu->nmi = 0; REG_CC |= (CC_F | CC_I); take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_NMI); cpu->state = mc6809_state_label_a; continue; } if (!(REG_CC & CC_F) && firq_active) { REG_CC |= (CC_F | CC_I); take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_FIRQ); cpu->state = mc6809_state_label_a; continue; } if (!(REG_CC & CC_I) && irq_active) { REG_CC |= CC_I; take_interrupt(cpu, CC_I, MC6809_INT_VEC_IRQ); cpu->state = mc6809_state_label_a; continue; } cpu->state = mc6809_state_cwai_check_halt; continue; case mc6809_state_cwai_check_halt: NVMA_CYCLE; if (cpu->halt) { continue; } cpu->state = mc6809_state_dispatch_irq; continue; case mc6809_state_sync: if (nmi_active || firq_active || irq_active) { NVMA_CYCLE; NVMA_CYCLE; instruction_posthook(cpu); cpu->state = mc6809_state_label_b; continue; } NVMA_CYCLE; if (cpu->halt) cpu->state = mc6809_state_sync_check_halt; continue; case mc6809_state_sync_check_halt: NVMA_CYCLE; if (!cpu->halt) { cpu->state = mc6809_state_sync; } continue; case mc6809_state_next_instruction: { unsigned op; // Fetch op-code and process op = byte_immediate(cpu); switch (op) { // 0x00 - 0x0f direct mode ops // 0x40 - 0x4f inherent A register ops // 0x50 - 0x5f inherent B register ops // 0x60 - 0x6f indexed mode ops // 0x70 - 0x7f extended mode ops case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0f: case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4f: case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5f: case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6f: case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7f: { uint16_t ea; unsigned tmp1; switch ((op >> 4) & 0xf) { case 0x0: ea = ea_direct(cpu); tmp1 = fetch_byte(cpu, ea); break; case 0x4: ea = 0; tmp1 = RREG_A; break; case 0x5: ea = 0; tmp1 = RREG_B; break; case 0x6: ea = ea_indexed(cpu); tmp1 = fetch_byte(cpu, ea); break; case 0x7: ea = ea_extended(cpu); tmp1 = fetch_byte(cpu, ea); break; default: ea = tmp1 = 0; break; } switch (op & 0xf) { case 0x1: // NEG illegal case 0x0: tmp1 = op_neg(cpu, tmp1); break; // NEG, NEGA, NEGB case 0x2: tmp1 = op_negcom(cpu, tmp1); break; // NEGCOM illegal case 0x3: tmp1 = op_com(cpu, tmp1); break; // COM, COMA, COMB case 0x5: // LSR illegal case 0x4: tmp1 = op_lsr(cpu, tmp1); break; // LSR, LSRA, LSRB case 0x6: tmp1 = op_ror(cpu, tmp1); break; // ROR, RORA, RORB case 0x7: tmp1 = op_asr(cpu, tmp1); break; // ASR, ASRA, ASRB case 0x8: tmp1 = op_asl(cpu, tmp1); break; // ASL, ASLA, ASLB case 0x9: tmp1 = op_rol(cpu, tmp1); break; // ROL, ROLA, ROLB case 0xb: // DEC illegal case 0xa: tmp1 = op_dec(cpu, tmp1); break; // DEC, DECA, DECB case 0xc: tmp1 = op_inc(cpu, tmp1); break; // INC, INCA, INCB case 0xd: tmp1 = op_tst(cpu, tmp1); break; // TST, TSTA, TSTB case 0xf: tmp1 = op_clr(cpu, tmp1); break; // CLR, CLRA, CLRB default: break; } switch (op & 0xf) { case 0xd: // TST NVMA_CYCLE; NVMA_CYCLE; break; default: // the rest need storing switch ((op >> 4) & 0xf) { default: case 0x0: case 0x6: case 0x7: NVMA_CYCLE; store_byte(cpu, ea, tmp1); break; case 0x4: WREG_A = tmp1; peek_byte(cpu, REG_PC); break; case 0x5: WREG_B = tmp1; peek_byte(cpu, REG_PC); break; } } } break; // 0x0e JMP direct // 0x6e JMP indexed // 0x7e JMP extended case 0x0e: case 0x6e: case 0x7e: { unsigned ea; switch ((op >> 4) & 0xf) { case 0x0: ea = ea_direct(cpu); break; case 0x6: ea = ea_indexed(cpu); break; case 0x7: ea = ea_extended(cpu); break; default: ea = 0; break; } REG_PC = ea; } break; // 0x10 Page 2 case 0x10: cpu->state = mc6809_state_instruction_page_2; continue; // 0x11 Page 3 case 0x11: cpu->state = mc6809_state_instruction_page_3; continue; // 0x12 NOP inherent case 0x12: peek_byte(cpu, REG_PC); break; // 0x13 SYNC inherent case 0x13: peek_byte(cpu, REG_PC); cpu->state = mc6809_state_sync; continue; // 0x14, 0x15 HCF? (illegal) case 0x14: case 0x15: cpu->state = mc6809_state_hcf; goto done_instruction; // 0x16 LBRA relative case 0x16: { uint16_t ea; ea = long_relative(cpu); REG_PC += ea; NVMA_CYCLE; NVMA_CYCLE; } break; // 0x17 LBSR relative case 0x17: { uint16_t ea; ea = long_relative(cpu); ea += REG_PC; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; push_word(cpu, ®_S, REG_PC); REG_PC = ea; } break; // 0x18 Shift CC with mask inherent (illegal) case 0x18: REG_CC = (REG_CC << 1) & (CC_H | CC_Z); NVMA_CYCLE; peek_byte(cpu, REG_PC); break; // 0x19 DAA inherent case 0x19: { unsigned tmp = 0; if ((RREG_A&0x0f) >= 0x0a || REG_CC & CC_H) tmp |= 0x06; if (RREG_A >= 0x90 && (RREG_A&0x0f) >= 0x0a) tmp |= 0x60; if (RREG_A >= 0xa0 || REG_CC & CC_C) tmp |= 0x60; tmp += RREG_A; WREG_A = tmp; // CC.C NOT cleared, only set if appropriate CLR_NZV; SET_NZC8(tmp); peek_byte(cpu, REG_PC); } break; // 0x1a ORCC immediate case 0x1a: { unsigned data; data = byte_immediate(cpu); REG_CC |= data; peek_byte(cpu, REG_PC); } break; // 0x1b NOP inherent (illegal) case 0x1b: peek_byte(cpu, REG_PC); break; // 0x1c ANDCC immediate case 0x1c: { unsigned data; data = byte_immediate(cpu); REG_CC &= data; peek_byte(cpu, REG_PC); } break; // 0x1d SEX inherent case 0x1d: WREG_A = (RREG_B & 0x80) ? 0xff : 0; CLR_NZ; SET_NZ16(REG_D); peek_byte(cpu, REG_PC); break; // 0x1e EXG immediate case 0x1e: { unsigned postbyte; uint16_t tmp1, tmp2; postbyte = byte_immediate(cpu); switch (postbyte >> 4) { case 0x0: tmp1 = REG_D; break; case 0x1: tmp1 = REG_X; break; case 0x2: tmp1 = REG_Y; break; case 0x3: tmp1 = REG_U; break; case 0x4: tmp1 = REG_S; break; case 0x5: tmp1 = REG_PC; break; case 0x8: tmp1 = RREG_A | 0xff00; break; case 0x9: tmp1 = RREG_B | 0xff00; break; // TODO: verify this behaviour case 0xa: tmp1 = (REG_CC << 8) | REG_CC; break; case 0xb: tmp1 = (REG_DP << 8) | REG_DP; break; default: tmp1 = 0xffff; break; } switch (postbyte & 0xf) { case 0x0: tmp2 = REG_D; REG_D = tmp1; break; case 0x1: tmp2 = REG_X; REG_X = tmp1; break; case 0x2: tmp2 = REG_Y; REG_Y = tmp1; break; case 0x3: tmp2 = REG_U; REG_U = tmp1; break; case 0x4: tmp2 = REG_S; REG_S = tmp1; break; case 0x5: tmp2 = REG_PC; REG_PC = tmp1; break; case 0x8: tmp2 = RREG_A | 0xff00; WREG_A = tmp1; break; case 0x9: tmp2 = RREG_B | 0xff00; WREG_B = tmp1; break; // TODO: verify this behaviour case 0xa: tmp2 = (REG_CC << 8) | REG_CC; REG_CC = tmp1; break; case 0xb: tmp2 = (REG_DP << 8) | REG_DP; REG_DP = tmp1; break; default: tmp2 = 0xffff; break; } switch (postbyte >> 4) { case 0x0: REG_D = tmp2; break; case 0x1: REG_X = tmp2; break; case 0x2: REG_Y = tmp2; break; case 0x3: REG_U = tmp2; break; case 0x4: REG_S = tmp2; break; case 0x5: REG_PC = tmp2; break; case 0x8: WREG_A = tmp2; break; case 0x9: WREG_B = tmp2; break; case 0xa: REG_CC = tmp2; break; case 0xb: REG_DP = tmp2; break; default: break; } NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; } break; // 0x1f TFR immediate case 0x1f: { unsigned postbyte; uint16_t tmp1; postbyte = byte_immediate(cpu); switch (postbyte >> 4) { case 0x0: tmp1 = REG_D; break; case 0x1: tmp1 = REG_X; break; case 0x2: tmp1 = REG_Y; break; case 0x3: tmp1 = REG_U; break; case 0x4: tmp1 = REG_S; break; case 0x5: tmp1 = REG_PC; break; case 0x8: tmp1 = RREG_A | 0xff00; break; case 0x9: tmp1 = RREG_B | 0xff00; break; // TODO: verify this behaviour case 0xa: tmp1 = (REG_CC << 8) | REG_CC; break; case 0xb: tmp1 = (REG_DP << 8) | REG_DP; break; default: tmp1 = 0xffff; break; } switch (postbyte & 0xf) { case 0x0: REG_D = tmp1; break; case 0x1: REG_X = tmp1; break; case 0x2: REG_Y = tmp1; break; case 0x3: REG_U = tmp1; break; case 0x4: REG_S = tmp1; break; case 0x5: REG_PC = tmp1; break; case 0x8: WREG_A = tmp1; break; case 0x9: WREG_B = tmp1; break; case 0xa: REG_CC = tmp1; break; case 0xb: REG_DP = tmp1; break; default: break; } NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; } break; // 0x20 - 0x2f short branches case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: { unsigned tmp = sex8(byte_immediate(cpu)); NVMA_CYCLE; if (branch_condition(cpu, op)) REG_PC += tmp; } break; // 0x30 LEAX indexed case 0x30: REG_X = ea_indexed(cpu); CLR_Z; SET_Z(REG_X); NVMA_CYCLE; break; // 0x31 LEAY indexed case 0x31: REG_Y = ea_indexed(cpu); CLR_Z; SET_Z(REG_Y); NVMA_CYCLE; break; // 0x32 LEAS indexed case 0x32: REG_S = ea_indexed(cpu); NVMA_CYCLE; cpu->nmi_armed = 1; // XXX: Really? break; // 0x33 LEAU indexed case 0x33: REG_U = ea_indexed(cpu); NVMA_CYCLE; break; // 0x34 PSHS immediate case 0x34: psh(cpu, ®_S, REG_U); break; // 0x35 PULS immediate case 0x35: pul(cpu, ®_S, ®_U); break; // 0x36 PSHU immediate case 0x36: psh(cpu, ®_U, REG_S); break; // 0x37 PULU immediate case 0x37: pul(cpu, ®_U, ®_S); break; // 0x38 ANDCC immediate (illegal) case 0x38: { unsigned data; data = byte_immediate(cpu); REG_CC &= data; peek_byte(cpu, REG_PC); /* Differs from legal 0x1c version by * taking one more cycle: */ NVMA_CYCLE; } break; // 0x39 RTS inherent case 0x39: peek_byte(cpu, REG_PC); REG_PC = pull_word(cpu, ®_S); NVMA_CYCLE; break; // 0x3a ABX inherent case 0x3a: REG_X += RREG_B; peek_byte(cpu, REG_PC); NVMA_CYCLE; break; // 0x3b RTI inherent case 0x3b: peek_byte(cpu, REG_PC); REG_CC = pull_byte(cpu, ®_S); if (REG_CC & CC_E) { WREG_A = pull_byte(cpu, ®_S); WREG_B = pull_byte(cpu, ®_S); REG_DP = pull_byte(cpu, ®_S); REG_X = pull_word(cpu, ®_S); REG_Y = pull_word(cpu, ®_S); REG_U = pull_word(cpu, ®_S); REG_PC = pull_word(cpu, ®_S); } else { REG_PC = pull_word(cpu, ®_S); } cpu->nmi_armed = 1; peek_byte(cpu, REG_S); break; // 0x3c CWAI immediate case 0x3c: { unsigned data; data = byte_immediate(cpu); REG_CC &= data; peek_byte(cpu, REG_PC); NVMA_CYCLE; stack_irq_registers(cpu, 1); NVMA_CYCLE; cpu->state = mc6809_state_dispatch_irq; goto done_instruction; } break; // 0x3d MUL inherent case 0x3d: { unsigned tmp = RREG_A * RREG_B; REG_D = tmp; CLR_ZC; SET_Z(tmp); if (tmp & 0x80) REG_CC |= CC_C; peek_byte(cpu, REG_PC); NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; } break; // 0x3e RESET (illegal) case 0x3e: peek_byte(cpu, REG_PC); push_irq_registers(cpu); instruction_posthook(cpu); take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_RESET); cpu->state = mc6809_state_label_a; continue; // 0x3f SWI inherent case 0x3f: peek_byte(cpu, REG_PC); stack_irq_registers(cpu, 1); instruction_posthook(cpu); take_interrupt(cpu, CC_F|CC_I, MC6809_INT_VEC_SWI); cpu->state = mc6809_state_label_a; continue; // 0x80 - 0xbf A register arithmetic ops // 0xc0 - 0xff B register arithmetic ops case 0x80: case 0x81: case 0x82: case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x90: case 0x91: case 0x92: case 0x94: case 0x95: case 0x96: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0xa0: case 0xa1: case 0xa2: case 0xa4: case 0xa5: case 0xa6: case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xb0: case 0xb1: case 0xb2: case 0xb4: case 0xb5: case 0xb6: case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xc0: case 0xc1: case 0xc2: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xd0: case 0xd1: case 0xd2: case 0xd4: case 0xd5: case 0xd6: case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe5: case 0xe6: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xf0: case 0xf1: case 0xf2: case 0xf4: case 0xf5: case 0xf6: case 0xf8: case 0xf9: case 0xfa: case 0xfb: { unsigned tmp1, tmp2; tmp1 = !(op & 0x40) ? RREG_A : RREG_B; switch ((op >> 4) & 3) { case 0: tmp2 = byte_immediate(cpu); break; case 1: tmp2 = byte_direct(cpu); break; case 2: tmp2 = byte_indexed(cpu); break; case 3: tmp2 = byte_extended(cpu); break; default: tmp2 = 0; break; } switch (op & 0xf) { case 0x0: tmp1 = op_sub(cpu, tmp1, tmp2); break; // SUBA, SUBB case 0x1: (void)op_sub(cpu, tmp1, tmp2); break; // CMPA, CMPB case 0x2: tmp1 = op_sbc(cpu, tmp1, tmp2); break; // SBCA, SBCB case 0x4: tmp1 = op_and(cpu, tmp1, tmp2); break; // ANDA, ANDB case 0x5: (void)op_and(cpu, tmp1, tmp2); break; // BITA, BITB case 0x6: tmp1 = op_ld(cpu, 0, tmp2); break; // LDA, LDB case 0x7: tmp1 = op_discard(cpu, tmp1, tmp2); break; // illegal case 0x8: tmp1 = op_eor(cpu, tmp1, tmp2); break; // EORA, EORB case 0x9: tmp1 = op_adc(cpu, tmp1, tmp2); break; // ADCA, ADCB case 0xa: tmp1 = op_or(cpu, tmp1, tmp2); break; // ORA, ORB case 0xb: tmp1 = op_add(cpu, tmp1, tmp2); break; // ADDA, ADDB default: break; } if (!(op & 0x40)) { WREG_A = tmp1; } else { WREG_B = tmp1; } } break; // 0x83, 0x93, 0xa3, 0xb3 SUBD // 0x8c, 0x9c, 0xac, 0xbc CMPX // 0xc3, 0xd3, 0xe3, 0xf3 ADDD case 0x83: case 0x93: case 0xa3: case 0xb3: case 0x8c: case 0x9c: case 0xac: case 0xbc: case 0xc3: case 0xd3: case 0xe3: case 0xf3: { unsigned tmp1, tmp2; tmp1 = !(op & 0x08) ? REG_D : REG_X; switch ((op >> 4) & 3) { case 0: tmp2 = word_immediate(cpu); break; case 1: tmp2 = word_direct(cpu); break; case 2: tmp2 = word_indexed(cpu); break; case 3: tmp2 = word_extended(cpu); break; default: tmp2 = 0; break; } switch (op & 0x4f) { case 0x03: tmp1 = op_sub16(cpu, tmp1, tmp2); break; // SUBD case 0x0c: (void)op_sub16(cpu, tmp1, tmp2); break; // CMPX case 0x43: tmp1 = op_add16(cpu, tmp1, tmp2); break; // ADDD default: break; } NVMA_CYCLE; if (!(op & 0x08)) { REG_D = tmp1; } } break; // 0x8d BSR // 0x9d, 0xad, 0xbd JSR case 0x8d: case 0x9d: case 0xad: case 0xbd: { unsigned ea; switch ((op >> 4) & 3) { case 0: ea = short_relative(cpu); ea += REG_PC; NVMA_CYCLE; NVMA_CYCLE; NVMA_CYCLE; break; case 1: ea = ea_direct(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break; case 2: ea = ea_indexed(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break; case 3: ea = ea_extended(cpu); peek_byte(cpu, ea); NVMA_CYCLE; break; default: ea = 0; break; } push_word(cpu, ®_S, REG_PC); REG_PC = ea; } break; // 0x8e, 0x9e, 0xae, 0xbe LDX // 0xcc, 0xdc, 0xec, 0xfc LDD // 0xce, 0xde, 0xee, 0xfe LDU case 0x8e: case 0x9e: case 0xae: case 0xbe: case 0xcc: case 0xdc: case 0xec: case 0xfc: case 0xce: case 0xde: case 0xee: case 0xfe: { unsigned tmp1, tmp2; switch ((op >> 4) & 3) { case 0: tmp2 = word_immediate(cpu); break; case 1: tmp2 = word_direct(cpu); break; case 2: tmp2 = word_indexed(cpu); break; case 3: tmp2 = word_extended(cpu); break; default: tmp2 = 0; break; } tmp1 = op_ld16(cpu, 0, tmp2); switch (op & 0x42) { case 0x02: REG_X = tmp1; break; case 0x40: REG_D = tmp1; break; case 0x42: REG_U = tmp1; break; default: break; } } break; // 0x97, 0xa7, 0xb7 STA // 0xd7, 0xe7, 0xf7 STB case 0x97: case 0xa7: case 0xb7: case 0xd7: case 0xe7: case 0xf7: { uint16_t ea; uint8_t tmp1; tmp1 = !(op & 0x40) ? RREG_A : RREG_B; switch ((op >> 4) & 3) { case 1: ea = ea_direct(cpu); break; case 2: ea = ea_indexed(cpu); break; case 3: ea = ea_extended(cpu); break; default: ea = 0; break; } store_byte(cpu, ea, tmp1); CLR_NZV; SET_NZ8(tmp1); } break; // 0x9f, 0xaf, 0xbf STX // 0xdd, 0xed, 0xfd STD // 0xdf, 0xef, 0xff STU case 0x9f: case 0xaf: case 0xbf: case 0xdd: case 0xed: case 0xfd: case 0xdf: case 0xef: case 0xff: { uint16_t ea, tmp1; switch (op & 0x42) { case 0x02: tmp1 = REG_X; break; case 0x40: tmp1 = REG_D; break; case 0x42: tmp1 = REG_U; break; default: tmp1 = 0; break; } switch ((op >> 4) & 3) { case 1: ea = ea_direct(cpu); break; case 2: ea = ea_indexed(cpu); break; case 3: ea = ea_extended(cpu); break; default: ea = 0; break; } CLR_NZV; SET_NZ16(tmp1); store_byte(cpu, ea, tmp1 >> 8); store_byte(cpu, ea+1, tmp1); } break; // 0x8f STX immediate (illegal) // 0xcf STU immediate (illegal) // Illegal instruction only part working case 0x8f: case 0xcf: { unsigned tmp1; tmp1 = !(op & 0x40) ? REG_X : REG_U; (void)fetch_byte(cpu, REG_PC); REG_PC++; store_byte(cpu, REG_PC, tmp1); REG_PC++; CLR_NZV; REG_CC |= CC_N; } break; // 0xcd HCF? (illegal) case 0xcd: cpu->state = mc6809_state_hcf; goto done_instruction; // Illegal instruction default: NVMA_CYCLE; break; } cpu->state = mc6809_state_label_a; goto done_instruction; } case mc6809_state_instruction_page_2: { unsigned op; op = byte_immediate(cpu); switch (op) { // 0x10, 0x11 Page 2 case 0x10: case 0x11: cpu->state = mc6809_state_instruction_page_2; continue; // 0x1020 - 0x102f long branches case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: { unsigned tmp = word_immediate(cpu); if (branch_condition(cpu, op)) { REG_PC += tmp; NVMA_CYCLE; } NVMA_CYCLE; } break; // 0x103f SWI2 inherent case 0x3f: peek_byte(cpu, REG_PC); stack_irq_registers(cpu, 1); instruction_posthook(cpu); take_interrupt(cpu, 0, MC6809_INT_VEC_SWI2); cpu->state = mc6809_state_label_a; continue; // 0x1083, 0x1093, 0x10a3, 0x10b3 CMPD // 0x108c, 0x109c, 0x10ac, 0x10bc CMPY case 0x83: case 0x93: case 0xa3: case 0xb3: case 0x8c: case 0x9c: case 0xac: case 0xbc: { unsigned tmp1, tmp2; tmp1 = !(op & 0x08) ? REG_D : REG_Y; switch ((op >> 4) & 3) { case 0: tmp2 = word_immediate(cpu); break; case 1: tmp2 = word_direct(cpu); break; case 2: tmp2 = word_indexed(cpu); break; case 3: tmp2 = word_extended(cpu); break; default: tmp2 = 0; break; } (void)op_sub16(cpu, tmp1, tmp2); NVMA_CYCLE; } break; // 0x108e, 0x109e, 0x10ae, 0x10be LDY // 0x10ce, 0x10de, 0x10ee, 0x10fe LDS case 0x8e: case 0x9e: case 0xae: case 0xbe: case 0xce: case 0xde: case 0xee: case 0xfe: { unsigned tmp1, tmp2; switch ((op >> 4) & 3) { case 0: tmp2 = word_immediate(cpu); break; case 1: tmp2 = word_direct(cpu); break; case 2: tmp2 = word_indexed(cpu); break; case 3: tmp2 = word_extended(cpu); break; default: tmp2 = 0; break; } tmp1 = op_ld16(cpu, 0, tmp2); if (!(op & 0x40)) { REG_Y = tmp1; } else { REG_S = tmp1; cpu->nmi_armed = 1; } } break; // 0x109f, 0x10af, 0x10bf STY // 0x10df, 0x10ef, 0x10ff STS case 0x9f: case 0xaf: case 0xbf: case 0xdf: case 0xef: case 0xff: { unsigned ea, tmp1; tmp1 = !(op & 0x40) ? REG_Y : REG_S; switch ((op >> 4) & 3) { case 1: ea = ea_direct(cpu); break; case 2: ea = ea_indexed(cpu); break; case 3: ea = ea_extended(cpu); break; default: ea = 0; break; } CLR_NZV; SET_NZ16(tmp1); store_byte(cpu, ea, tmp1 >> 8); store_byte(cpu, ea+1, tmp1); } break; // Illegal instruction default: NVMA_CYCLE; break; } cpu->state = mc6809_state_label_a; goto done_instruction; } case mc6809_state_instruction_page_3: { unsigned op; op = byte_immediate(cpu); switch (op) { // 0x10, 0x11 Page 3 case 0x10: case 0x11: cpu->state = mc6809_state_instruction_page_3; continue; // 0x113F SWI3 inherent case 0x3f: peek_byte(cpu, REG_PC); stack_irq_registers(cpu, 1); instruction_posthook(cpu); take_interrupt(cpu, 0, MC6809_INT_VEC_SWI3); cpu->state = mc6809_state_label_a; continue; // 0x1183, 0x1193, 0x11a3, 0x11b3 CMPU // 0x118c, 0x119c, 0x11ac, 0x11bc CMPS case 0x83: case 0x93: case 0xa3: case 0xb3: case 0x8c: case 0x9c: case 0xac: case 0xbc: { unsigned tmp1, tmp2; tmp1 = !(op & 0x08) ? REG_U : REG_S; switch ((op >> 4) & 3) { case 0: tmp2 = word_immediate(cpu); break; case 1: tmp2 = word_direct(cpu); break; case 2: tmp2 = word_indexed(cpu); break; case 3: tmp2 = word_extended(cpu); break; default: tmp2 = 0; break; } (void)op_sub16(cpu, tmp1, tmp2); NVMA_CYCLE; } break; // Illegal instruction default: NVMA_CYCLE; break; } cpu->state = mc6809_state_label_a; goto done_instruction; } // Certain illegal instructions cause the CPU to lock up: case mc6809_state_hcf: NVMA_CYCLE; continue; } done_instruction: instruction_posthook(cpu); continue; } while (cpu->running); }