summaryrefslogtreecommitdiff
path: root/sux.c
diff options
context:
space:
mode:
Diffstat (limited to 'sux.c')
-rw-r--r--sux.c405
1 files changed, 92 insertions, 313 deletions
diff --git a/sux.c b/sux.c
index f064cee..4ccd2d5 100644
--- a/sux.c
+++ b/sux.c
@@ -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++;