diff options
Diffstat (limited to 'sux.c')
-rw-r--r-- | sux.c | 405 |
1 files changed, 92 insertions, 313 deletions
@@ -70,11 +70,45 @@ void start_timer(int sec, int usec) { } #endif +uint8_t is_extop(uint8_t opcode, uint8_t dbg) { + switch (opcode) { + case ADC_E: + case SBC_E: + case AND_E: + case ORA_E: + case XOR_E: + case LSL_E: + case LSR_E: + case ROL_E: + case ROR_E: + case MUL_E: + case DIV_E: + case ASR_E: + case CMP_E: + case LDY_E: + case LDA_E: + case LDB_E: + case CPB_E: + case CPX_E: + case CPY_E: + case LDX_E: + case DEC_E: + case INC_E: + case STY_E: + case STA_E: + case STB_E: + case STX_E: return 0; + } + return 1; +} + void *run(void *args) { struct suxthr *thr = (void *)args; struct sux *cpu = &thr->sx; uint8_t thread = thr->th; uint8_t prefix = 0; + uint8_t ext_prefix = 0; + uint8_t prefix2 = 0; uint8_t opcode = 0; union reg address; union reg value; @@ -141,13 +175,58 @@ void *run(void *args) { pthread_mutex_unlock(&mutex); #endif #endif - uint16_t instr = read_value(cpu, 0, cpu->pc, 1, 1, 0); + uint32_t instr = read_value(cpu, 0, cpu->pc, 3, 1, 0); uint8_t *tmp_inst = (uint8_t *)&instr; prefix = ((instr & 3) == 3) ? *tmp_inst++ : 0; + ext_prefix = ((*tmp_inst & 0xD) == 0xD) ? *tmp_inst++ : 0; opcode = *tmp_inst; - cpu->pc += ((instr & 3) == 3)+1; + cpu->pc += ((instr & 3) == 3)+((ext_prefix & 0xD) == 0xD)+1; address.u64 = cpu->pc; - uint8_t am = optype[opcode]; + uint8_t am; + uint8_t ext_id = 0; + uint8_t tmp_opcode = opcode; + uint8_t tmp_ext_prefix = ext_prefix; + if (ext_prefix) { + ext_id = ((ext_prefix >> 4) & 0xF); + switch (ext_id) { + case 0x0: + am = ext_optype[opcode]; + if (!is_extop(opcode, 0)) { + tmp_ext_prefix = 0; + switch (opcode) { + case ADC_E: tmp_opcode = ADC_IMM; break; + case SBC_E: tmp_opcode = SBC_IMM; break; + case AND_E: tmp_opcode = AND_IMM; break; + case ORA_E: tmp_opcode = ORA_IMM; break; + case XOR_E: tmp_opcode = XOR_IMM; break; + case LSL_E: tmp_opcode = LSL_IMM; break; + case LSR_E: tmp_opcode = LSR_IMM; break; + case ROL_E: tmp_opcode = ROL_IMM; break; + case ROR_E: tmp_opcode = ROR_IMM; break; + case MUL_E: tmp_opcode = MUL_IMM; break; + case DIV_E: tmp_opcode = DIV_IMM; break; + case ASR_E: tmp_opcode = ASR_IMM; break; + case CMP_E: tmp_opcode = CMP_IMM; break; + case LDY_E: tmp_opcode = LDY_IMM; break; + case LDA_E: tmp_opcode = LDA_IMM; break; + case LDB_E: tmp_opcode = LDB_IMM; break; + case CPB_E: tmp_opcode = CPB_IMM; break; + case CPX_E: tmp_opcode = CPX_IMM; break; + case CPY_E: tmp_opcode = CPY_IMM; break; + case LDX_E: tmp_opcode = LDX_IMM; break; + case DEC_E: tmp_opcode = DEC_Z; break; + case INC_E: tmp_opcode = INC_Z; break; + case STY_E: tmp_opcode = STY_Z; break; + case STA_E: tmp_opcode = STA_Z; break; + case STB_E: tmp_opcode = STB_Z; break; + case STX_E: tmp_opcode = STX_Z; break; + } + } + break; + } + } else { + am = optype[opcode]; + } uint8_t rs = (prefix >> 4) & 3; uint8_t size = (/***/1 << rs) - 1; uint8_t check_io = (am != IMM); @@ -155,14 +234,14 @@ void *run(void *args) { #if keypoll pthread_mutex_lock(&mutex); #endif - disasm(cpu, lines, opcode, prefix, thread); + disasm(cpu, lines, opcode, prefix, ext_prefix, prefix2, thread); lines+=1; #if keypoll pthread_mutex_unlock(&mutex); #endif #endif if (am != IMPL && am != BREG) { - address.u64 = get_addr(cpu, opcode, prefix, 1, 1, thread); + address.u64 = get_addr(cpu, opcode, prefix, ext_prefix, 1, 1, thread); /*if (address.u64 > mem_size-1) { addr[STEP_ADDR] = 1; step = 1; @@ -172,314 +251,14 @@ void *run(void *args) { } } /*decode_microinst(&uc, &uc_test, prefix, 0);*/ - switch (opcode) { - case CPS_IMP: /* Clear Processor Status. */ - cpu->ps.u64 = 0; - break; - case ADC_B: /* ADC B register. */ - value.u64 = cpu->b; /* Falls Through. */ - case ADC_IMM: /* ADC Immediate. */ - case ADC_AB: /* ADC Absolute. */ - case ADC_Z: /* ADC Zero Matrix. */ - cpu->a = adc(cpu, cpu->a, value.u64, thread); - break; - case PHP_IMP: push(cpu, cpu->ps.u8[thread], 0, thread); break; /* PusH Processor status to stack. */ - case PHA_IMP: push(cpu, cpu->a , size, thread); break; /* PusH Accumulator to stack. */ - case PHB_IMP: push(cpu, cpu->b , size, thread); break; /* PusH B register to stack. */ - case PHY_IMP: push(cpu, cpu->y , size, thread); break; /* PusH Y register to stack. */ - case PHX_IMP: push(cpu, cpu->x , size, thread); break; /* PusH X register to stack. */ - case TAY_IMP: cpu->y = transfer(cpu, cpu->a , value.u64, thread); break; /* Transfer Accumulator to Y. */ - case TAX_IMP: cpu->x = transfer(cpu, cpu->a , value.u64, thread); break; /* Transfer Accumulator to Y. */ - case TYX_IMP: cpu->x = transfer(cpu, cpu->y , value.u64, thread); break; /* Transfer Y to X. */ - case TYA_IMP: cpu->a = transfer(cpu, cpu->y , value.u64, thread); break; /* Transfer Y to Accumulator. */ - case TXA_IMP: cpu->a = transfer(cpu, cpu->x , value.u64, thread); break; /* Transfer X to Accumulator. */ - case TXY_IMP: cpu->y = transfer(cpu, cpu->x , value.u64, thread); break; /* Transfer X to Y. */ - case TAB_IMP: cpu->b = transfer(cpu, cpu->a , value.u64, thread); break; /* Transfer Accumulator to B. */ - case TSX_IMP: cpu->x = transfer(cpu, cpu->sp, value.u64, thread); break; /* Transfer Stack pointer to X. */ - case TBA_IMP: cpu->a = transfer(cpu, cpu->b , value.u64, thread); break; /* Transfer B to Accumulator. */ - case TXS_IMM: cpu->sp = transfer(cpu, cpu->x , value.u64, thread); break; /* Transfer X to Stack pointer. */ - case BRA_REL: /* BRA Relative. */ - case JMP_AB: /* JMP Absolute. */ - case JMP_Z: /* JMP Zero Matrix. */ - case JMP_IN: /* JMP Indirect. */ - cpu->pc = address.u64; - break; - case SBC_B: /* SBC B register. */ - value.u64 = cpu->b; /* Falls Through. */ - case SBC_IMM: /* SBC Immediate. */ - case SBC_AB: /* SBC Absolute. */ - case SBC_Z: /* SBC Zero Matrix. */ - cpu->a = adc(cpu, cpu->a, ~value.u64, thread); - break; - case PLP_IMP: cpu->ps.u8[thread] = pull(cpu, 0, thread); break; /* PuLl Processor status from stack. */ - case PLA_IMP: cpu->a = pull(cpu, size, thread); break; /* PuLl Accumulator from stack. */ - case PLB_IMP: cpu->b = pull(cpu, size, thread); break; /* PuLl B register from stack. */ - case PLY_IMP: cpu->y = pull(cpu, size, thread); break; /* PuLl Y register from stack. */ - case PLX_IMP: cpu->x = pull(cpu, size, thread); break; /* PuLl X register from stack. */ - break; - case AND_B: /* AND B register. */ - value.u64 = cpu->b; /* Falls Through. */ - case AND_IMM: /* AND Immediate. */ - case AND_AB: /* AND Absolute. */ - case AND_Z: /* AND Zero Matrix. */ - cpu->a = and(cpu, cpu->a, value.u64, thread); - break; - case BPO_REL: /* BPO Relative. */ - if (!getflag(N)) { - cpu->pc = address.u64; - } - break; - case ORA_B: /* ORA B register. */ - value.u64 = cpu->b; /* Falls Through. */ - case ORA_IMM: /* ORA Immediate. */ - case ORA_AB: /* ORA Absolute. */ - case ORA_Z: /* ORA Zero Matrix. */ - cpu->a = or(cpu, cpu->a, value.u64, thread); - break; - case SEI_IMP: /* SEt Interrupt. */ - setflag(1, I); - break; - case BNG_REL: /* BNG Relative. */ - if (getflag(N)) { - cpu->pc = address.u64; - } - break; - case XOR_B: /* XOR B register. */ - value.u64 = cpu->b; /* Falls Through. */ - case XOR_IMM: /* XOR Immediate. */ - case XOR_AB: /* XOR Absolute. */ - case XOR_Z: /* XOR Zero Matrix. */ - cpu->a = xor(cpu, cpu->a, value.u64, thread); - break; - case CLI_IMP: /* CLear Interrupt. */ - setflag(0, I); - break; - case BCS_REL: /* BCS Relative. */ - if (getflag(C)) { - cpu->pc = address.u64; - } - break; - case LSL_B: /* LSL B register. */ - value.u64 = cpu->b; /* Falls Through. */ - case LSL_IMM: /* LSL Immediate. */ - case LSL_AB: /* LSL Absolute. */ - case LSL_Z: /* LSL Zero Matrix. */ - cpu->a = lsl(cpu, cpu->a, value.u64, thread); - break; - case SEC_IMP: /* SEt Carry flag.*/ - setflag(1, C); - break; - case STA_AB: /* STA Absolute. */ - case STA_Z: /* STA Zero Matrix. */ - case STA_ZX: /* STA Zero Matrix, Indexed with X. */ - case STA_ZY: /* STA Zero Matrix, Indexed with Y. */ - case STA_IN: /* STA Indirect. */ - case STA_IX: /* STA Indexed Indirect. */ - case STA_IY: /* STA Indirect Indexed. */ - store(cpu, address.u64, cpu->a, prefix, thread); - break; - case STY_AB: /* STY Absolute. */ - case STY_Z: /* STY Zero Matrix. */ - case STY_IN: /* STY Indirect. */ - store(cpu, address.u64, cpu->y, prefix, thread); - break; - case STX_AB: /* STX Absolute. */ - case STX_Z: /* STX Zero Matrix. */ - case STX_IN: /* STX Indirect. */ - store(cpu, address.u64, cpu->x, prefix, thread); - break; - case STB_AB: /* STB Absolute. */ - case STB_Z: /* STB Zero Matrix. */ - case STB_ZX: /* STB Zero Matrix, Indexed with X. */ - case STB_ZY: /* STB Zero Matrix, Indexed with Y. */ - case STB_IN: /* STB Indirect. */ - case STB_IX: /* STB Indexed Indirect. */ - case STB_IY: /* STB Indirect Indexed. */ - store(cpu, address.u64, cpu->b, prefix, thread); - break; - case BCC_REL: /* BCC Relative. */ - if (!getflag(C)) { - cpu->pc = address.u64; - } - break; - case LSR_B: /* LSR B register. */ - value.u64 = cpu->b; /* Falls Through. */ - case LSR_IMM: /* LSR Immediate. */ - case LSR_AB: /* LSR Absolute. */ - case LSR_Z: /* LSR Zero Matrix. */ - cpu->a = lsr(cpu, cpu->a, value.u64, thread); - break; - case ASR_B: /* ASR B register. */ - value.u64 = cpu->b; /* Falls Through. */ - case ASR_IMM: /* ASR Immediate. */ - case ASR_AB: /* ASR Absolute. */ - case ASR_Z: /* ASR Zero Matrix. */ - cpu->a = asr(cpu, cpu->a, value.u64, thread); - break; - case CLC_IMP: /* CLear Carry flag. */ - setflag(0, C); - break; - case LDB_IMM: /* LDB Immediate. */ - case LDB_AB: /* LDB Absolute. */ - case LDB_Z: /* LDB Zero Matrix. */ - case LDB_ZX: /* LDB Zero Matrix, Indexed with X. */ - case LDB_ZY: /* LDB Zero Matrix, Indexed with Y. */ - case LDB_IN: /* LDB Indirect. */ - case LDB_IX: /* LDB Indexed Indirect. */ - case LDB_IY: /* LDB Indirect Indexed. */ - cpu->b = load(cpu, cpu->b, address.u64, size, thread); - break; - case LDA_IMM: /* LDA Immediate. */ - case LDA_AB: /* LDA Absolute. */ - case LDA_Z: /* LDA Zero Matrix. */ - case LDA_ZX: /* LDA Zero Matrix, Indexed with X. */ - case LDA_ZY: /* LDA Zero Matrix, Indexed with Y. */ - case LDA_IN: /* LDA Indirect. */ - case LDA_IX: /* LDA Indexed Indirect. */ - case LDA_IY: /* LDA Indirect Indexed. */ - cpu->a = load(cpu, cpu->a, address.u64, size, thread); - break; - case LDY_IMM: /* LDY Immediate. */ - case LDY_AB: /* LDY Absolute. */ - case LDY_Z: /* LDY Zero Matrix. */ - case LDY_IN: /* LDY Indirect. */ - cpu->y = load(cpu, cpu->y, address.u64, size, thread); - break; - case LDX_IMM: /* LDX Immediate. */ - case LDX_AB: /* LDX Absolute. */ - case LDX_Z: /* LDX Zero Matrix. */ - case LDX_IN: /* LDX Indirect. */ - cpu->x = load(cpu, cpu->x, address.u64, size, thread); - break; - case BEQ_REL: /* BEQ Relative. */ - if (getflag(Z)) { - cpu->pc = address.u64; - } - break; - case ROL_B: /* ROL B register. */ - value.u64 = cpu->b; /* Falls Through. */ - case ROL_IMM: /* ROL Immediate. */ - case ROL_AB: /* ROL Absolute. */ - case ROL_Z: /* ROL Zero Matrix. */ - cpu->a = rol(cpu, cpu->a, value.u64, thread); - break; - case BNE_REL: /* BNE Relative. */ - if (!getflag(Z)) { - cpu->pc = address.u64; - } - break; - case ROR_B: /* ROR B register. */ - value.u64 = cpu->b; /* Falls Through. */ - case ROR_IMM: /* ROR Immediate. */ - case ROR_AB: /* ROR Absolute. */ - case ROR_Z: /* ROR Zero Matrix. */ - cpu->a = ror(cpu, cpu->a, value.u64, thread); - break; - case BVS_REL: /* BVS Relative. */ - if (getflag(V)) { - cpu->pc = address.u64; - } - break; - case MUL_B: /* MUL B register. */ - value.u64 = cpu->b; /* Falls Through. */ - case MUL_IMM: /* MUL Immediate. */ - case MUL_AB: /* MUL Absolute. */ - case MUL_Z: /* MUL Zero Matrix. */ - cpu->a = mul(cpu, cpu->a, value.u64, thread); - break; - case BVC_REL: /* BVC Relative. */ - if (!getflag(V)) { - cpu->pc = address.u64; - } - break; - case DIV_B: /* DIV B register. */ - case DIV_IMM: /* DIV Immediate. */ - case DIV_AB: /* DIV Absolute. */ - case DIV_Z: /* DIV Zero Matrix. */ - rem = (opcode != DIV_B) ? &cpu->b : &cpu->x; - cpu->a = divd(cpu, cpu->a, value.u64, rem, thread); - break; - case CLV_IMP: /* CLear oVerflow flag. */ - setflag(0, V); - break; - case CPB_IMM: /* CPB Immediate. */ - case CPB_AB: /* CPB Absolute. */ - case CPB_Z: /* CPB Zero Matrix. */ - case CPB_IN: /* CPB Indirect. */ - case CPB_IX: /* CPB Indexed Indirect. */ - case CPB_IY: /* CPB Indirect Indexed. */ - cmp(cpu, value.u64, cpu->b, thread); - break; - case CMP_B: /* CMP B register. */ - value.u64 = cpu->b; /* Falls Through. */ - case CMP_IMM: /* CMP Immediate. */ - case CMP_AB: /* CMP Absolute. */ - case CMP_Z: /* CMP Zero Matrix. */ - case CMP_IN: /* CMP Indirect. */ - case CMP_IX: /* CMP Indexed Indirect. */ - case CMP_IY: /* CMP Indirect Indexed. */ - cmp(cpu, value.u64, cpu->a, thread); - break; - case CPY_IMM: /* CPY Immediate. */ - case CPY_AB: /* CPY Absolute. */ - case CPY_Z: /* CPY Zero Matrix. */ - cmp(cpu, value.u64, cpu->y, thread); - break; - case CPX_IMM: /* CPX Immediate. */ - case CPX_AB: /* CPX Absolute. */ - case CPX_Z: /* CPX Zero Matrix. */ - cmp(cpu, value.u64, cpu->x, thread); - break; - case INC_IMP: cpu->a = idr(cpu, cpu->a, 1, thread); break; - case INB_IMP: cpu->b = idr(cpu, cpu->b, 1, thread); break; - case INY_IMP: cpu->y = idr(cpu, cpu->y, 1, thread); break; - case INX_IMP: cpu->x = idr(cpu, cpu->x, 1, thread); break; - case DEC_IMP: cpu->a = idr(cpu, cpu->a, 0, thread); break; - case DEB_IMP: cpu->b = idr(cpu, cpu->b, 0, thread); break; - case DEY_IMP: cpu->y = idr(cpu, cpu->y, 0, thread); break; - case DEX_IMP: cpu->x = idr(cpu, cpu->x, 0, thread); break; - case JSR_IN: /* JSR Indirect. */ - case JSR_AB: /* Jump to SubRoutine. */ - case JSR_Z: /* JSR Zero Matrix. */ - push(cpu, cpu->pc, (size) ? size : 7, thread); - cpu->pc = address.u64; - break; - case INC_AB: /* INC Absolute. */ - case INC_Z: /* INC Zero Matrix. */ - idm(cpu, address.u64, prefix, 1, thread); - break; - case NOP_IMP: /* No OPeration. */ - break; - case RTI_IMP: /* ReTurn from Interrupt routine. */ - cpu->ps.u8[thread] = pull(cpu, 0, thread); - size = 0; - case RTS_IMP: /* ReTurn from Subroutine. */ - cpu->pc = pull(cpu, (size) ? size : 7, thread); - break; - case DEC_AB: /* DEC Absolute. */ - case DEC_Z: /* DEC Zero Matrix. */ - idm(cpu, address.u64, prefix, 0, thread); - break; - case BRK_IMP: /* BReaK. */ - case WAI_IMP: /* WAit for Interrupt. */ - if (opcode == WAI_IMP) { - pthread_mutex_lock(&main_mutex); - pthread_cond_signal(&main_cond); - pthread_mutex_unlock(&main_mutex); - pthread_mutex_lock(&mutex); - pthread_cond_wait(&cond, &mutex); - pthread_mutex_unlock(&mutex); - } - push(cpu, cpu->pc, 7, thread); - push(cpu, cpu->ps.u8[thread], 0, thread); - setflag(1, I); - setreg(value.u8, +, 0, addr, +, (opcode == BRK) ? 0xFFE0 : 0xFFA0, 7); - if (opcode == WAI_IMP) { - kbd_rdy &= (uint8_t)~(1 << thread); - } - cpu->pc = value.u64; - default: - break; + ext_prefix = tmp_ext_prefix; + opcode = tmp_opcode; + if (ext_prefix) { + switch (ext_id) { + case 0x0: exec_ext_inst(cpu, opcode, prefix, value, address, size, thread); break; + } + } else { + exec_base_inst(cpu, opcode, prefix, value, address, size, thread); } #if !IO ins++; |