tuple<int, vi> strongly_connected_components(const vvi& graph) { const int N = graph.size(); int C = 0, V = 0, top = 0; vi comp(N, -1), inx(N, -1), stack(N + 1, -1); auto tarjan = [&](auto&& self, int loc) -> int { stack[top++] = loc; int low = inx[loc] = V++; for (int nbr : graph[loc]) { if (inx[nbr] == -1) low = min(low, self(self, nbr)); else if (comp[nbr] == -1) low = min(low, inx[nbr]); } if (low == inx[loc]) { while (stack[top] != loc) comp[stack[--top]] = C; C++; } return low; }; for (int i = 0; i < N; i++) { if (inx[i] == -1) tarjan(tarjan, i); } return { C, comp }; }
static char * INX2() { CPU *c = getCPU(); OP_CODE_INFO *o = getOP_CODE_INFO(0,0,modeImmediate); setRegByte(c,IND_X,-103); inx(c,o); int8_t xVal = getRegByte(c,IND_X); mu_assert("INX2 err, IND_X reg != -102", xVal == -102); mu_run_test_with_args(testRegStatus,c,"10100000", " NVUBDIZC NVUBDIZC\nINX2 err, %s != %s"); freeOP_CODE_INFO(o); free(c); return 0; }
// run appropriate function for opcode in memory void execute_cpu(machine* mch) { uint8_t *opcode = &mch->memory[mch->pc++]; uint8_t *memory = mch->memory; fprintf(stdout, "opcode: %x\n", opcode[0]); switch(*opcode) { case 0x02: exit(123); case 0x12: exit(123); case 0x22: exit(123); case 0x32: exit(123); case 0x42: exit(123); case 0x52: exit(123); case 0x62: exit(123); case 0x72: exit(123); case 0x92: exit(123); case 0xB2: exit(123); case 0xD2: exit(123); case 0xF2: exit(123); case 0xEA: return nop(mch, 1); case 0x1A: return nop(mch, 2); // illegal instruction (nop with 2 cycles) case 0x7A: return nop(mch, 2); // same as above case 0x69: return adc_imm(opcode[1], mch); case 0x65: return adc_zp(opcode[1], mch); case 0x75: return adc_zpx(opcode[1], mch); case 0x6D: return adc_abs(opcode[2], opcode[1], mch); case 0x7D: return adc_absx(opcode[2], opcode[1], mch); case 0x79: return adc_absy(opcode[2], opcode[1], mch); case 0x61: return adc_indx(opcode[2], opcode[1], mch); case 0x71: return adc_indy(opcode[2], opcode[1], mch); case 0x29: return and_imm(opcode[1], mch); case 0x25: return and_zp(opcode[1], mch); case 0x35: return and_zpx(opcode[1], mch); case 0x2D: return and_abs(opcode[2], opcode[1], mch); case 0x3D: return and_absx(opcode[2], opcode[1], mch); case 0x39: return and_absy(opcode[2], opcode[1], mch); case 0x21: return and_indx(opcode[2], opcode[1], mch); case 0x31: return and_indy(opcode[2], opcode[1], mch); case 0x0A: return asl_acc(mch); case 0x06: return asl_zp(opcode[1], mch); case 0x16: return asl_zpx(opcode[1], mch); case 0x0E: return asl_abs(opcode[2], opcode[1], mch); case 0x1E: return asl_absx(opcode[2], opcode[1], mch); case 0x90: return branch_clear(opcode[2], opcode[1], mch, 0b00000001); case 0xB0: return branch_set(opcode[2], opcode[1], mch, 0b00000001); case 0xF0: return branch_set(opcode[2], opcode[1], mch, 0b00000010); case 0x24: return bit_zp(opcode[1], mch); case 0x2C: return bit_abs(opcode[2], opcode[1], mch); case 0x30: return branch_set(opcode[2], opcode[1], mch, 0b10000000); case 0xD0: return branch_clear(opcode[2], opcode[1], mch, 0b00000010); case 0x10: return branch_clear(opcode[2], opcode[1], mch, 0b10000000); case 0x00: return brk(mch); case 0x50: return branch_clear(opcode[2], opcode[1], mch, 0b01000000); case 0x70: return branch_set(opcode[2], opcode[1], mch, 0b01000000); case 0x18: return clc(mch); case 0x58: return cli(mch); case 0xB8: return clv(mch); case 0xC9: return cmp_imm(opcode[1], mch); case 0xC5: return cmp_zp(opcode[1], mch); case 0xD5: return cmp_zpx(opcode[1], mch); case 0xCD: return cmp_abs(opcode[2], opcode[1], mch, 0, 0); case 0xDD: return cmp_abs(opcode[2], opcode[1], mch, 1, mch->X); case 0xD9: return cmp_abs(opcode[2], opcode[1], mch, 1, mch->Y); case 0xC1: return cmp_indy(opcode[2], opcode[1], mch); case 0xD1: return cmp_indx(opcode[2], opcode[1], mch); case 0xE0: return cpx_imm(opcode[1], mch); case 0xE4: return cpx_zp(opcode[1], mch); case 0xEC: return cpx_abs(opcode[2], opcode[1], mch); case 0xC0: return cpy_imm(opcode[1], mch); case 0xC4: return cpy_zp(opcode[1], mch); case 0xCC: return cpy_abs(opcode[2], opcode[1], mch); case 0xC6: return dec_zp(opcode[1], mch); case 0xD6: return dec_zpx(opcode[1], mch); case 0xCE: return dec_abs(opcode[2], opcode[1], mch); case 0xDE: return dec_absx(opcode[2], opcode[1], mch); case 0xCA: return dex(mch); case 0x88: return dey(mch); case 0x49: return eor_imm(opcode[1], mch); case 0x45: return eor_zp(opcode[1], mch); case 0x55: return eor_zpx(opcode[1], mch); case 0x4D: return eor_abs(opcode[2], opcode[1], mch); case 0x5D: return eor_absx(opcode[2], opcode[1], mch); case 0x59: return eor_absy(opcode[2], opcode[1], mch); case 0x41: return eor_indx(opcode[2], opcode[1], mch); case 0x51: return eor_indy(opcode[2], opcode[1], mch); case 0xE6: return inc_zp(opcode[1], mch, 0, 0); case 0xF6: return inc_zp(opcode[1], mch, 1, mch->X); case 0xEE: return inc_abs(opcode[2], opcode[1], mch, 0, 0); case 0xFE: return inc_abs(opcode[2], opcode[1], mch, 1, mch->X); case 0xE8: return inx(mch); case 0xC8: return iny(mch); case 0x4C: return jmp_abs(opcode[2], opcode[1], mch); case 0x6C: return jmp_ind(opcode[2], opcode[1], mch); case 0x20: return jsr(opcode[2], opcode[1], mch); case 0xA9: return lda_imm(opcode[1], mch); case 0xA5: return lda_zp(opcode[1], mch, 0, 0); case 0xB5: return lda_zp(opcode[1], mch, 1, mch->X); case 0xAD: return lda_abs(opcode[2], opcode[1], mch, 0, 0); case 0xBD: return lda_abs(opcode[2], opcode[1], mch, 1, mch->X); case 0xB9: return lda_abs(opcode[2], opcode[1], mch, 1, mch->Y); case 0xA1: return lda_indx(opcode[2], opcode[1], mch); case 0xB1: return lda_indy(opcode[2], opcode[1], mch); case 0xA2: return ldx_imm(opcode[1], mch); case 0xA6: return ldx_zp(opcode[1], mch, 0, 0); case 0xB6: return ldx_zp(opcode[1], mch, 1, mch->X); case 0xAE: return ldx_abs(opcode[2], opcode[1], mch, 0, 0); case 0xBE: return ldx_abs(opcode[2], opcode[1], mch, 1, mch->X); case 0xA0: return ldy_imm(opcode[1], mch); case 0xA4: return ldy_zp(opcode[1], mch, 0, 0); case 0xB4: return ldy_zp(opcode[1], mch, 1, mch->X); case 0xAC: return ldy_abs(opcode[2], opcode[1], mch, 0, 0); case 0xBC: return ldy_abs(opcode[2], opcode[1], mch, 1, mch->X); case 0x4A: return lsr_acc(mch); case 0x46: return lsr_zp(opcode[1], mch); case 0x56: return lsr_zpx(opcode[1], mch); case 0x4E: return lsr_abs(opcode[2], opcode[1], mch); case 0x5E: return lsr_absx(opcode[2], opcode[1], mch); case 0x09: return or_imm(opcode[1], mch); case 0x05: return or_zp(opcode[1], mch); case 0x15: return or_zpx(opcode[1], mch); case 0x0D: return or_abs(opcode[2], opcode[1], mch); case 0x1D: return or_absx(opcode[2], opcode[1], mch); case 0x19: return or_absy(opcode[2], opcode[1], mch); case 0x01: return or_indx(opcode[2], opcode[1], mch); case 0x11: return or_indy(opcode[2], opcode[1], mch); case 0x48: return pha(mch); case 0x08: return php(mch); case 0x68: return pla(mch); case 0x28: return plp(mch); case 0x40: return rti(mch); case 0x60: return rts(mch); case 0x78: return sei(mch); case 0x38: return sec(mch); case 0xAA: return tax(mch); case 0xA8: return tay(mch); case 0x8A: return txa(mch); case 0x98: return tya(mch); default: fprintf(stdout, "unimplemented opcode!\n"); fprintf(stdout, "opcode in question: %x\n", opcode[0]); exit(1); break; } }
static void hglin(void) { // F53A pha(); c=1; sbc(ram[HGR_X]); pha(); a=x; sbc(ram[HGR_X+1]); ram[HGR_QUADRANT]=a; // F544 if (c==1) goto hglin_1; pla(); a=a^0xff; adc(1); pha(); lda_const(0); sbc(ram[HGR_QUADRANT]); // F550 hglin_1: ram[HGR_DX+1]=a; ram[HGR_E+1]=a; pla(); ram[HGR_DX]=a; ram[HGR_E]=a; pla(); ram[HGR_X]=a; ram[HGR_X+1]=x; a=y; c=0; sbc(ram[HGR_Y]); if (c==0) goto hglin_2; a=a^0xff; adc(0xfe); hglin_2: // F568 ram[HGR_DY]=a; ram[HGR_Y]=y; ror_mem(HGR_QUADRANT); c=1; sbc(ram[HGR_DX]); x=a; lda_const(0xff); sbc(ram[HGR_DX+1]); ram[HGR_COUNT]=a; ldy(HGR_HORIZ); goto movex2; // always? // f57c movex: asl(); move_left_or_right(); c=1; // f581 movex2: lda(HGR_E); adc(ram[HGR_DY]); ram[HGR_E]=a; lda(HGR_E+1); sbc(0); movex2_1: ram[HGR_E+1]=a; lda(y_indirect(GBASL,y)); a=a^ram[HGR_BITS]; a=a&ram[HMASK]; a=a^ram[y_indirect(GBASL,y)]; ram[y_indirect(GBASL,y)]=a; inx(); if (z!=1) goto movex2_2; ram[HGR_COUNT]++; if (ram[HGR_COUNT]==0) return; // F59e movex2_2: lda(HGR_QUADRANT); if (c==1) goto movex; move_up_or_down(); c=0; lda(HGR_E); adc(ram[HGR_DX]); ram[HGR_E]=a; lda(HGR_E+1); adc(ram[HGR_DX+1]); goto movex2_1; }
/** * @brief emulate instruction * @return returns false if something goes wrong (e.g. illegal instruction) * * Current limitations: * * - Illegal instructions are not implemented * - Excess cycles due to page boundary crossing are not calculated * - Some known architectural bugs are not emulated */ bool Cpu::emulate() { /* fetch instruction */ uint8_t insn = fetch_op(); bool retval = true; /* emulate instruction */ switch(insn) { /* BRK */ case 0x0: brk(); break; /* ORA (nn,X) */ case 0x1: ora(load_byte(addr_indx()),6); break; /* ORA nn */ case 0x5: ora(load_byte(addr_zero()),3); break; /* ASL nn */ case 0x6: asl_mem(addr_zero(),5); break; /* PHP */ case 0x8: php(); break; /* ORA #nn */ case 0x9: ora(fetch_op(),2); break; /* ASL A */ case 0xA: asl_a(); break; /* ORA nnnn */ case 0xD: ora(load_byte(addr_abs()),4); break; /* ASL nnnn */ case 0xE: asl_mem(addr_abs(),6); break; /* BPL nn */ case 0x10: bpl(); break; /* ORA (nn,Y) */ case 0x11: ora(load_byte(addr_indy()),5); break; /* ORA nn,X */ case 0x15: ora(load_byte(addr_zerox()),4); break; /* ASL nn,X */ case 0x16: asl_mem(addr_zerox(),6); break; /* CLC */ case 0x18: clc(); break; /* ORA nnnn,Y */ case 0x19: ora(load_byte(addr_absy()),4); break; /* ORA nnnn,X */ case 0x1D: ora(load_byte(addr_absx()),4); break; /* ASL nnnn,X */ case 0x1E: asl_mem(addr_absx(),7); break; /* JSR */ case 0x20: jsr(); break; /* AND (nn,X) */ case 0x21: _and(load_byte(addr_indx()),6); break; /* BIT nn */ case 0x24: bit(addr_zero(),3); break; /* AND nn */ case 0x25: _and(load_byte(addr_zero()),3); break; /* ROL nn */ case 0x26: rol_mem(addr_zero(),5); break; /* PLP */ case 0x28: plp(); break; /* AND #nn */ case 0x29: _and(fetch_op(),2); break; /* ROL A */ case 0x2A: rol_a(); break; /* BIT nnnn */ case 0x2C: bit(addr_abs(),4); break; /* AND nnnn */ case 0x2D: _and(load_byte(addr_abs()),4); break; /* ROL nnnn */ case 0x2E: rol_mem(addr_abs(),6); break; /* BMI nn */ case 0x30: bmi(); break; /* AND (nn,Y) */ case 0x31: _and(load_byte(addr_indy()),5); break; /* AND nn,X */ case 0x35: _and(load_byte(addr_zerox()),4); break; /* ROL nn,X */ case 0x36: rol_mem(addr_zerox(),6); break; /* SEC */ case 0x38: sec(); break; /* AND nnnn,Y */ case 0x39: _and(load_byte(addr_absy()),4); break; /* AND nnnn,X */ case 0x3D: _and(load_byte(addr_absx()),4); break; /* ROL nnnn,X */ case 0x3E: rol_mem(addr_absx(),7); break; /* RTI */ case 0x40: rti(); break; /* EOR (nn,X) */ case 0x41: eor(load_byte(addr_indx()),6); break; /* EOR nn */ case 0x45: eor(load_byte(addr_zero()),3); break; /* LSR nn */ case 0x46: lsr_mem(addr_zero(),5); break; /* PHA */ case 0x48: pha(); break; /* EOR #nn */ case 0x49: eor(fetch_op(),2); break; /* BVC */ case 0x50: bvc(); break; /* JMP nnnn */ case 0x4C: jmp(); break; /* EOR nnnn */ case 0x4D: eor(load_byte(addr_abs()),4); break; /* LSR A */ case 0x4A: lsr_a(); break; /* LSR nnnn */ case 0x4E: lsr_mem(addr_abs(),6); break; /* EOR (nn,Y) */ case 0x51: eor(load_byte(addr_indy()),5); break; /* EOR nn,X */ case 0x55: eor(load_byte(addr_zerox()),4); break; /* LSR nn,X */ case 0x56: lsr_mem(addr_zerox(),6); break; /* CLI */ case 0x58: cli(); break; /* EOR nnnn,Y */ case 0x59: eor(load_byte(addr_absy()),4); break; /* EOR nnnn,X */ case 0x5D: eor(load_byte(addr_absx()),4); break; /* LSR nnnn,X */ case 0x5E: lsr_mem(addr_absx(),7); break; /* RTS */ case 0x60: rts(); break; /* ADC (nn,X) */ case 0x61: adc(load_byte(addr_indx()),6); break; /* ADC nn */ case 0x65: adc(load_byte(addr_zero()),3); break; /* ROR nn */ case 0x66: ror_mem(addr_zero(),5); break; /* PLA */ case 0x68: pla(); break; /* ADC #nn */ case 0x69: adc(fetch_op(),2); break; /* ROR A */ case 0x6A: ror_a(); break; /* JMP (nnnn) */ case 0x6C: jmp_ind(); break; /* ADC nnnn */ case 0x6D: adc(load_byte(addr_abs()),4); break; /* ROR nnnn */ case 0x6E: ror_mem(addr_abs(),6); break; /* BVS */ case 0x70: bvs(); break; /* ADC (nn,Y) */ case 0x71: adc(load_byte(addr_indy()),5); break; /* ADC nn,X */ case 0x75: adc(load_byte(addr_zerox()),4); break; /* ROR nn,X */ case 0x76: ror_mem(addr_zerox(),6); break; /* SEI */ case 0x78: sei(); break; /* ADC nnnn,Y */ case 0x79: adc(load_byte(addr_absy()),4); break; /* ADC nnnn,X */ case 0x7D: adc(load_byte(addr_absx()),4); break; /* ROR nnnn,X */ case 0x7E: ror_mem(addr_absx(),7); break; /* STA (nn,X) */ case 0x81: sta(addr_indx(),6); break; /* STY nn */ case 0x84: sty(addr_zero(),3); break; /* STA nn */ case 0x85: sta(addr_zero(),3); break; /* STX nn */ case 0x86: stx(addr_zero(),3); break; /* DEY */ case 0x88: dey(); break; /* TXA */ case 0x8A: txa(); break; /* STY nnnn */ case 0x8C: sty(addr_abs(),4); break; /* STA nnnn */ case 0x8D: sta(addr_abs(),4); break; /* STX nnnn */ case 0x8E: stx(addr_abs(),4); break; /* BCC nn */ case 0x90: bcc(); break; /* STA (nn,Y) */ case 0x91: sta(addr_indy(),6); break; /* STY nn,X */ case 0x94: sty(addr_zerox(),4); break; /* STA nn,X */ case 0x95: sta(addr_zerox(),4); break; /* STX nn,Y */ case 0x96: stx(addr_zeroy(),4); break; /* TYA */ case 0x98: tya(); break; /* STA nnnn,Y */ case 0x99: sta(addr_absy(),5); break; /* TXS */ case 0x9A: txs(); break; /* STA nnnn,X */ case 0x9D: sta(addr_absx(),5); break; /* LDY #nn */ case 0xA0: ldy(fetch_op(),2); break; /* LDA (nn,X) */ case 0xA1: lda(load_byte(addr_indx()),6); break; /* LDX #nn */ case 0xA2: ldx(fetch_op(),2); break; /* LDY nn */ case 0xA4: ldy(load_byte(addr_zero()),3); break; /* LDA nn */ case 0xA5: lda(load_byte(addr_zero()),3); break; /* LDX nn */ case 0xA6: ldx(load_byte(addr_zero()),3); break; /* TAY */ case 0xA8: tay(); break; /* LDA #nn */ case 0xA9: lda(fetch_op(),2); break; /* TAX */ case 0xAA: tax(); break; /* LDY nnnn */ case 0xAC: ldy(load_byte(addr_abs()),4); break; /* LDA nnnn */ case 0xAD: lda(load_byte(addr_abs()),4); break; /* LDX nnnn */ case 0xAE: ldx(load_byte(addr_abs()),4); break; /* BCS nn */ case 0xB0: bcs(); break; /* LDA (nn,Y) */ case 0xB1: lda(load_byte(addr_indy()),5); break; /* LDY nn,X */ case 0xB4: ldy(load_byte(addr_zerox()),3); break; /* LDA nn,X */ case 0xB5: lda(load_byte(addr_zerox()),3); break; /* LDX nn,Y */ case 0xB6: ldx(load_byte(addr_zeroy()),3); break; /* CLV */ case 0xB8: clv(); break; /* LDA nnnn,Y */ case 0xB9: lda(load_byte(addr_absy()),4); break; /* TSX */ case 0xBA: tsx(); break; /* LDY nnnn,X */ case 0xBC: ldy(load_byte(addr_absx()),4); break; /* LDA nnnn,X */ case 0xBD: lda(load_byte(addr_absx()),4); break; /* LDX nnnn,Y */ case 0xBE: ldx(load_byte(addr_absy()),4); break; /* CPY #nn */ case 0xC0: cpy(fetch_op(),2); break; /* CMP (nn,X) */ case 0xC1: cmp(load_byte(addr_indx()),6); break; /* CPY nn */ case 0xC4: cpy(load_byte(addr_zero()),3); break; /* CMP nn */ case 0xC5: cmp(load_byte(addr_zero()),3); break; /* DEC nn */ case 0xC6: dec(addr_zero(),5); break; /* INY */ case 0xC8: iny(); break; /* CMP #nn */ case 0xC9: cmp(fetch_op(),2); break; /* DEX */ case 0xCA: dex(); break; /* CPY nnnn */ case 0xCC: cpy(load_byte(addr_abs()),4); break; /* CMP nnnn */ case 0xCD: cmp(load_byte(addr_abs()),4); break; /* DEC nnnn */ case 0xCE: dec(addr_abs(),6); break; /* BNE nn */ case 0xD0: bne(); break; /* CMP (nn,Y) */ case 0xD1: cmp(load_byte(addr_indy()),5); break; /* CMP nn,X */ case 0xD5: cmp(load_byte(addr_zerox()),4); break; /* DEC nn,X */ case 0xD6: dec(addr_zerox(),6); break; /* CLD */ case 0xD8: cld(); break; /* CMP nnnn,Y */ case 0xD9: cmp(load_byte(addr_absy()),4); break; /* CMP nnnn,X */ case 0xDD: cmp(load_byte(addr_absx()),4); break; /* DEC nnnn,X */ case 0xDE: dec(addr_absx(),7); break; /* CPX #nn */ case 0xE0: cpx(fetch_op(),2); break; /* SBC (nn,X) */ case 0xE1: sbc(load_byte(addr_indx()),6); break; /* CPX nn */ case 0xE4: cpx(load_byte(addr_zero()),3); break; /* SBC nn */ case 0xE5: sbc(load_byte(addr_zero()),3); break; /* INC nn */ case 0xE6: inc(addr_zero(),5); break; /* INX */ case 0xE8: inx(); break; /* SBC #nn */ case 0xE9: sbc(fetch_op(),2); break; /* NOP */ case 0xEA: nop(); break; /* CPX nnnn */ case 0xEC: cpx(load_byte(addr_abs()),4); break; /* SBC nnnn */ case 0xED: sbc(load_byte(addr_abs()),4); break; /* INC nnnn */ case 0xEE: inc(addr_abs(),6); break; /* BEQ nn */ case 0xF0: beq(); break; /* SBC (nn,Y) */ case 0xF1: sbc(load_byte(addr_indy()),5); break; /* SBC nn,X */ case 0xF5: sbc(load_byte(addr_zerox()),4); break; /* INC nn,X */ case 0xF6: inc(addr_zerox(),6); break; /* SED */ case 0xF8: sed(); break; /* SBC nnnn,Y */ case 0xF9: sbc(load_byte(addr_absy()),4); break; /* SBC nnnn,X */ case 0xFD: sbc(load_byte(addr_absx()),4); break; /* INC nnnn,X */ case 0xFE: inc(addr_absx(),7); break; /* Unknown or illegal instruction */ default: D("Unknown instruction: %X at %04x\n", insn,pc()); retval = false; } return retval; }