static UINT32 process_rop(UINT32 src, UINT32 dst, UINT32 pat, const char* rop, UINT32 format) { DWORD stack[10] = { 0 }; DWORD stackp = 0; while (*rop != '\0') { char op = *rop++; switch (op) { case '0': stack[stackp++] = FreeRDPGetColor(format, 0, 0, 0, 0xFF); break; case '1': stack[stackp++] = FreeRDPGetColor(format, 0xFF, 0xFF, 0xFF, 0xFF); break; case 'D': stack[stackp++] = dst; break; case 'S': stack[stackp++] = src; break; case 'P': stack[stackp++] = pat; break; case 'x': op_xor(stack, &stackp); break; case 'a': op_and(stack, &stackp); break; case 'o': op_or(stack, &stackp); break; case 'n': op_not(stack, &stackp); break; default: break; } } return stack[0]; }
static int op_oplevel(int level) { int precision; bwx_DEBUG(__FUNCTION__); /* set the precision */ if ((precision = op_getprecision(level)) == OP_ERROR) { op_pulldown(2); sprintf(bwb_ebuf, "exp_operation(): failed to set precision."); bwb_error(bwb_ebuf); return FALSE; } /* precision is set correctly */ else { switch (CURTASK exps[level].operation) { case OP_ADD: op_add(level, precision); break; case OP_SUBTRACT: op_subtract(level, precision); break; case OP_MULTIPLY: op_multiply(level, precision); break; case OP_DIVIDE: op_divide(level, precision); break; case OP_ASSIGN: op_assign(level, precision); break; case OP_EQUALS: op_equals(level, precision); break; case OP_LESSTHAN: op_lessthan(level, precision); break; case OP_GREATERTHAN: op_greaterthan(level, precision); break; case OP_LTEQ: op_lteq(level, precision); break; case OP_GTEQ: op_gteq(level, precision); break; case OP_NOTEQUAL: op_notequal(level, precision); break; case OP_MODULUS: op_modulus(level, precision); break; case OP_INTDIVISION: op_intdiv(level, precision); break; case OP_OR: op_or(level, precision); break; case OP_AND: op_and(level, precision); break; case OP_NOT: op_not(level, precision); break; case OP_XOR: op_xor(level, precision); break; case OP_IMPLIES: op_imp(level, precision); break; case OP_EQUIV: op_eqv(level, precision); break; case OP_EXPONENT: op_exponent(level, precision); break; case OP_NEGATION: /* JBV */ op_negation(level, precision); break; case OP_POSATION: op_posation(level, precision); break; default: sprintf(bwb_ebuf, "PROGRAMMING ERROR: operator <%d> not (yet) supported.", CURTASK exps[level].operation); op_pulldown(2); bwb_error(bwb_ebuf); return FALSE; break; } /* end of case statement for operators */ } /* end of else statement, precision set */ return TRUE; } /* end of function op_oplevel() */
void Step() { Opcodes OP = (Opcodes)Fetch8(); //printf("%08X:%08X\n", Registers[sp], Registers[pc]); switch (OP) { case O_NOP: op_nop(); break; case O_MOV: op_mov(); break; case O_ADD: op_add(); break; case O_SUB: op_sub(); break; case O_MUL: op_mul(); break; case O_DIV: op_div(); break; case O_LI: op_li(); break; case O_MOVF: op_movf(); break; case O_ADDF: op_addf(); break; case O_SUBF: op_subf(); break; case O_MULF: op_mulf(); break; case O_DIVF: op_divf(); break; case O_LIF: op_lif(); break; case O_XOR: op_xor(); break; case O_AND: op_and(); break; case O_MOD: op_mod(); break; case O_OR: op_or(); break; case O_NOT: op_not(); break; case O_SHR: op_shr(); break; case O_SHL: op_shl(); break; case O_PUSH: op_push(); break; case O_POP: op_pop(); break; case O_STB: op_stb(); break; case O_LDB: op_ldb(); break; case O_STH: op_sth(); break; case O_LDH: op_ldh(); break; case O_STW: op_stw(); break; case O_LDW: op_ldw(); break; case O_LDF: op_ldf(); break; case O_STF: op_stf(); break; case O_CMP: op_cmp(); break; case O_B: op_b(0); break; case O_BC: op_b(1); break; case O_BEQ: op_bcond(ctr0_eq); break; case O_BNE: op_bcond(ctr0_ne); break; case O_BGT: op_bcond(ctr0_gt); break; case O_BLT: op_bcond(ctr0_lt); break; case O_BTC: op_btc(); break; case O_INC: op_inc(); break; case O_DEC: op_dec(); break; default: Error("Error: Unknown Opcode PC = %d OP = %08X\n", Registers[pc], OP); } Ticks++; }
void doop(Mips * emu, uint32_t op) { switch(op & 0xfc000000) { case 0x8000000: op_j(emu,op); return; case 0xc000000: op_jal(emu,op); return; case 0x10000000: op_beq(emu,op); return; case 0x14000000: op_bne(emu,op); return; case 0x18000000: op_blez(emu,op); return; case 0x1c000000: op_bgtz(emu,op); return; case 0x20000000: op_addi(emu,op); return; case 0x24000000: op_addiu(emu,op); return; case 0x28000000: op_slti(emu,op); return; case 0x2c000000: op_sltiu(emu,op); return; case 0x30000000: op_andi(emu,op); return; case 0x34000000: op_ori(emu,op); return; case 0x38000000: op_xori(emu,op); return; case 0x3c000000: op_lui(emu,op); return; case 0x50000000: op_beql(emu,op); return; case 0x54000000: op_bnel(emu,op); return; case 0x58000000: op_blezl(emu,op); return; case 0x80000000: op_lb(emu,op); return; case 0x84000000: op_lh(emu,op); return; case 0x88000000: op_lwl(emu,op); return; case 0x8c000000: op_lw(emu,op); return; case 0x90000000: op_lbu(emu,op); return; case 0x94000000: op_lhu(emu,op); return; case 0x98000000: op_lwr(emu,op); return; case 0xa0000000: op_sb(emu,op); return; case 0xa4000000: op_sh(emu,op); return; case 0xa8000000: op_swl(emu,op); return; case 0xac000000: op_sw(emu,op); return; case 0xb8000000: op_swr(emu,op); return; case 0xbc000000: op_cache(emu,op); return; case 0xc0000000: op_ll(emu,op); return; case 0xcc000000: op_pref(emu,op); return; case 0xe0000000: op_sc(emu,op); return; } switch(op & 0xfc00003f) { case 0x0: op_sll(emu,op); return; case 0x2: op_srl(emu,op); return; case 0x3: op_sra(emu,op); return; case 0x4: op_sllv(emu,op); return; case 0x6: op_srlv(emu,op); return; case 0x7: op_srav(emu,op); return; case 0x8: op_jr(emu,op); return; case 0x9: op_jalr(emu,op); return; case 0xc: op_syscall(emu,op); return; case 0xf: op_sync(emu,op); return; case 0x10: op_mfhi(emu,op); return; case 0x11: op_mthi(emu,op); return; case 0x12: op_mflo(emu,op); return; case 0x13: op_mtlo(emu,op); return; case 0x18: op_mult(emu,op); return; case 0x19: op_multu(emu,op); return; case 0x1a: op_div(emu,op); return; case 0x1b: op_divu(emu,op); return; case 0x20: op_add(emu,op); return; case 0x21: op_addu(emu,op); return; case 0x22: op_sub(emu,op); return; case 0x23: op_subu(emu,op); return; case 0x24: op_and(emu,op); return; case 0x25: op_or(emu,op); return; case 0x26: op_xor(emu,op); return; case 0x27: op_nor(emu,op); return; case 0x2a: op_slt(emu,op); return; case 0x2b: op_sltu(emu,op); return; case 0x2d: op_addu(emu,op); //daddu return; case 0x36: op_tne(emu,op); return; } switch(op & 0xfc1f0000) { case 0x4000000: op_bltz(emu,op); return; case 0x4010000: op_bgez(emu,op); return; case 0x4020000: op_bltzl(emu,op); return; case 0x4030000: op_bgezl(emu,op); return; case 0x4100000: op_bltzal(emu,op); return; case 0x4110000: op_bgezal(emu,op); return; case 0x5c000000: op_bgtzl(emu,op); return; } switch(op & 0xffffffff) { case 0x42000002: op_tlbwi(emu,op); return; case 0x42000006: op_tlbwr(emu,op); return; case 0x42000008: op_tlbp(emu,op); return; case 0x42000018: op_eret(emu,op); return; } switch(op & 0xfc0007ff) { case 0xa: op_movz(emu,op); return; case 0xb: op_movn(emu,op); return; case 0x70000002: op_mul(emu,op); return; } switch(op & 0xffe00000) { case 0x40000000: op_mfc0(emu,op); return; case 0x40800000: op_mtc0(emu,op); return; } switch(op & 0xfe00003f) { case 0x42000020: op_wait(emu,op); return; } // printf("unhandled opcode at %x -> %x\n",emu->pc,op); setExceptionCode(emu,EXC_RI); emu->exceptionOccured = 1; return; }
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); }
static int parse_posix_basic(struct ParseCtx *ctx, const char *re) { int err = 0; unsigned c; int glevel = 0; loop: if (err) return err; c = *re++; switch (c) { case 0: return (glevel == 0) ? 0 : REG_EPAREN; case '*': if (ctx->last_elem && ctx->last_elem->type != OP_BOL) err = op_count_simple(ctx, 0, MAX_COUNT); else err = op_char(ctx, '*'); break; case '.': err = op_simple(ctx, OP_ANY); break; case '[': err = op_class(ctx, &re); break; case '^': if (!ctx->last_elem) err = op_simple(ctx, OP_BOL); else err = op_char(ctx, c); break; case '$': if (!*re || (re[0] == '\\' && re[1] == ')')) err = op_simple(ctx, OP_EOL); else err = op_char(ctx, c); break; case '\\': goto escaped; default: err = op_char(ctx, c); } goto loop; escaped: c = *re++; switch (c) { case 0: return REG_EESCAPE; case '(': glevel++; err = op_gstart(ctx); break; case ')': glevel--; if (glevel < 0) return REG_EPAREN; err = op_gend(ctx); break; case '{': err = op_count_full(ctx, &re); break; case '.': case '^': case '$': case '*': case '[': case ']': case '\\': err = op_char(ctx, c); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': err = op_bref(ctx, c); break; case '|': err = STRICT ? REG_BADPAT : op_or(ctx); break; default: err = parse_relaxed_escapes(ctx, c); } goto loop; }
static int parse_posix_ext(struct ParseCtx *ctx, const char *re) { int err = 0; unsigned c; int glevel = 0; loop: if (err) return err; c = *re++; switch (c) { case 0: return (glevel == 0) ? 0 : REG_EPAREN; case '(': glevel++; err = op_gstart(ctx); break; case ')': if (glevel > 0) { glevel--; err = op_gend(ctx); } else { err = op_char(ctx, c); /* POSIX bug */ } break; case '|': err = op_or(ctx); break; case '*': err = op_count_simple(ctx, 0, MAX_COUNT); break; case '?': err = op_count_simple(ctx, 0, 1); break; case '+': err = op_count_simple(ctx, 1, MAX_COUNT); break; case '[': err = op_class(ctx, &re); break; case '{': err = op_count_full(ctx, &re); break; case '.': err = op_simple(ctx, OP_ANY); break; case '^': err = op_simple(ctx, OP_BOL); break; case '$': err = op_simple(ctx, OP_EOL); break; case '\\': goto escaped; default: err = op_char(ctx, c); } goto loop; escaped: c = *re++; if (c == 0) err = REG_EESCAPE; else if (c >= '0' && c <= '9') err = STRICT ? REG_BADPAT : op_bref(ctx, c); else if (isalpha(c)) err = parse_relaxed_escapes(ctx, c); else err = op_char(ctx, c); goto loop; }