diff --git a/3B2/3b2_cpu.c b/3B2/3b2_cpu.c index 9d5f2fd0..b55a8b4f 100644 --- a/3B2/3b2_cpu.c +++ b/3B2/3b2_cpu.c @@ -74,7 +74,7 @@ int8 cpu_etype = -1; /* Currently set expanded datatype */ t_bool cpu_nmi = FALSE; /* If set, there has been an NMI */ -uint8 cpu_ilen = 0; /* Length (in bytes) of instruction +int32 pc_incr = 0; /* Length (in bytes) of instruction currently being executed */ t_bool cpu_ex_halt = FALSE; /* Flag to halt on exceptions / traps */ @@ -133,6 +133,7 @@ static DEBTAB cpu_deb_tab[] = { { "IRQ", IRQ_MSG, "Interrupt Handling" }, { "IO", IO_D_MSG, "I/O Dispatch" }, { "TRACE", TRACE_MSG, "Call Trace" }, + { "ERROR", ERR_MSG, "Error" }, { NULL, 0 } }; @@ -202,7 +203,7 @@ mnemonic hword_ops[HWORD_OP_COUNT] = { /* Lookup table of operand types. */ mnemonic ops[256] = { - {0x00, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, + {0x00, 0, OP_NONE, NA, "halt", -1, -1, -1, -1}, {0x01, -1, OP_NONE, NA, "???", -1, -1, -1, -1}, {0x02, 2, OP_COPR, WD, "SPOPRD", -1, -1, -1, -1}, {0x03, 3, OP_COPR, WD, "SPOPD2", -1, -1, -1, -1}, @@ -1314,10 +1315,6 @@ t_bool cpu_on_interrupt(uint8 ipl) uint32 new_pcbp; uint16 id = ipl; /* TODO: Does this need to be uint16? */ - sim_debug(IRQ_MSG, &cpu_dev, - "[%08x] [cpu_on_interrupt] ipl=%d\n", - R[NUM_PC], ipl); - /* * "If a nonmaskable interrupt request is received, an auto-vector * interrupt acknowledge cycle is performed (as if an autovector @@ -1330,7 +1327,7 @@ t_bool cpu_on_interrupt(uint8 ipl) cpu_km = TRUE; - if ((R[NUM_PSW] & PSW_QIE_MASK) >> PSW_QIE) { + if (R[NUM_PSW] & PSW_QIE_MASK) { /* TODO: Maybe implement quick interrupts at some point, but the 3B2 ROM and SVR3 don't appear to use them. */ assert(0); @@ -1363,7 +1360,7 @@ t_bool cpu_on_interrupt(uint8 ipl) t_stat sim_instr(void) { - uint8 et, isc; + uint8 et, isc, trap; /* Temporary register used for overflow detection */ t_uint64 result; @@ -1396,10 +1393,10 @@ t_stat sim_instr(void) return STOP_EX; } - if (abort_reason == ABORT_EXC) { - et = R[NUM_PSW] & PSW_ET_MASK; - isc = (R[NUM_PSW] & PSW_ISC_MASK) >> PSW_ISC; + et = R[NUM_PSW] & PSW_ET_MASK; + isc = (R[NUM_PSW] & PSW_ISC_MASK) >> PSW_ISC; + if (abort_reason == ABORT_EXC) { switch(abort_context) { case C_NORMAL_GATE_VECTOR: cpu_on_normal_exception(N_GATE_VECTOR); @@ -1442,13 +1439,12 @@ t_stat sim_instr(void) } break; } - } else { - /* TODO: Handle traps */ - stop_reason = STOP_EX; } + /* Traps are handled at the end of instruction execution */ } while (stop_reason == 0) { + trap = 0; abort_context = C_NONE; if (sim_brk_summ && sim_brk_test(R[NUM_PC], SWMASK ('E'))) { @@ -1469,7 +1465,6 @@ t_stat sim_instr(void) /* Process DMA requests */ dmac_service_drqs(); - /* * Post-increment IU mode pointers (if needed). * @@ -1490,7 +1485,6 @@ t_stat sim_instr(void) cpu_on_interrupt(cpu_ipl()); cpu_nmi = FALSE; cpu_in_wait = FALSE; - continue; } if (cpu_in_wait) { @@ -1501,7 +1495,6 @@ t_stat sim_instr(void) } /* Reset the TM bits */ - R[NUM_PSW] &= ~PSW_TM; R[NUM_PSW] |= PSW_TM_MASK; /* Record the instruction for history */ @@ -1513,8 +1506,8 @@ t_stat sim_instr(void) } /* Decode the instruction */ - memset(cpu_instr, 0, sizeof(instr)); - cpu_ilen = decode_instruction(cpu_instr); + clear_instruction(cpu_instr); + pc_incr = decode_instruction(cpu_instr); /* Make sure to update the valid bit for history keeping (if * enabled) */ @@ -1590,63 +1583,53 @@ t_stat sim_instr(void) case BEH: case BEH_D: if (cpu_z_flag() == 1) { - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); } break; case BEB: case BEB_D: if (cpu_z_flag() == 1) { - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); } break; case BGH: if ((cpu_n_flag() | cpu_z_flag()) == 0) { - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); } break; case BGB: if ((cpu_n_flag() | cpu_z_flag()) == 0) { - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); } break; case BGEH: if ((cpu_n_flag() == 0) | (cpu_z_flag() == 1)) { - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); } break; case BGEB: if ((cpu_n_flag() == 0) | (cpu_z_flag() == 1)) { - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); } break; case BGEUH: if (cpu_c_flag() == 0) { - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); } break; case BGEUB: if (cpu_c_flag() == 0) { - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); } break; case BGUH: if ((cpu_c_flag() | cpu_z_flag()) == 0) { - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); } break; case BGUB: if ((cpu_c_flag() | cpu_z_flag()) == 0) { - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); } break; case BITW: @@ -1661,118 +1644,104 @@ t_stat sim_instr(void) break; case BLH: if ((cpu_n_flag() == 1) && (cpu_z_flag() == 0)) { - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); } break; case BLB: if ((cpu_n_flag() == 1) && (cpu_z_flag() == 0)) { - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); } break; case BLEH: if ((cpu_n_flag() | cpu_z_flag()) == 1) { - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); } break; case BLEB: if ((cpu_n_flag() | cpu_z_flag()) == 1) { - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); } break; case BLEUH: if ((cpu_c_flag() | cpu_z_flag()) == 1) { - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); } break; case BLEUB: if ((cpu_c_flag() | cpu_z_flag()) == 1) { - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); } break; case BLUH: if (cpu_c_flag() == 1) { - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); } break; case BLUB: if (cpu_c_flag() == 1) { - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); } break; case BNEH: case BNEH_D: if (cpu_z_flag() == 0) { - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); } break; case BNEB: case BNEB_D: if (cpu_z_flag() == 0) { - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); } break; case BPT: - /* TODO: Confirm that a breakpoint trap will increment the - PC. Otherwise, change 'break' to 'continue' */ - cpu_abort(NORMAL_EXCEPTION, BREAKPOINT_TRAP); + case HALT: + trap = BREAKPOINT_TRAP; break; case BRH: - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); + break; case BRB: - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); + break; case BSBH: - cpu_push_word(R[NUM_PC] + cpu_ilen); - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + cpu_push_word(R[NUM_PC] + pc_incr); + pc_incr = sign_extend_h(dst->embedded.h); + break; case BSBB: - cpu_push_word(R[NUM_PC] + cpu_ilen); - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + cpu_push_word(R[NUM_PC] + pc_incr); + pc_incr = sign_extend_b(dst->embedded.b); + break; case BVCH: if (cpu_v_flag() == 0) { - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); } break; case BVCB: if (cpu_v_flag() == 0) { - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); } break; case BVSH: if (cpu_v_flag() == 1) { - R[NUM_PC] += sign_extend_h(dst->embedded.h); - continue; + pc_incr = sign_extend_h(dst->embedded.h); } break; case BVSB: if (cpu_v_flag() == 1) { - R[NUM_PC] += sign_extend_b(dst->embedded.b); - continue; + pc_incr = sign_extend_b(dst->embedded.b); } break; case CALL: a = cpu_effective_address(src1); b = cpu_effective_address(dst); write_w(R[NUM_SP] + 4, R[NUM_AP]); - write_w(R[NUM_SP], R[NUM_PC] + cpu_ilen); + write_w(R[NUM_SP], R[NUM_PC] + pc_incr); R[NUM_SP] += 8; R[NUM_PC] = b; R[NUM_AP] = a; - continue; + pc_incr = 0; + break; case CFLUSH: break; case CALLPS: @@ -1808,7 +1777,8 @@ t_stat sim_instr(void) abort_context = C_NONE; cpu_km = FALSE; - continue; + pc_incr = 0; + break; case CLRW: case CLRH: case CLRB: @@ -1975,7 +1945,8 @@ t_stat sim_instr(void) } mmu_enable(); R[NUM_PC] = R[0]; - continue; + pc_incr = 0; + break; case DISVJMP: if (cpu_execution_level() != EX_LVL_KERN) { cpu_abort(NORMAL_EXCEPTION, PRIVILEGED_OPCODE); @@ -1983,7 +1954,8 @@ t_stat sim_instr(void) } mmu_disable(); R[NUM_PC] = R[0]; - continue; + pc_incr = 0; + break; case EXTFW: case EXTFH: case EXTFB: @@ -2039,27 +2011,21 @@ t_stat sim_instr(void) break; case JMP: R[NUM_PC] = cpu_effective_address(dst); - continue; + pc_incr = 0; + break; case JSB: - cpu_push_word(R[NUM_PC] + cpu_ilen); + cpu_push_word(R[NUM_PC] + pc_incr); R[NUM_PC] = cpu_effective_address(dst); - continue; + pc_incr = 0; + break; case LLSW3: - result = (t_uint64)cpu_read_op(src2) << (cpu_read_op(src1) & 0x1f); - cpu_write_op(dst, (uint32)(result & WORD_MASK)); - cpu_set_nz_flags((uint32)(result & WORD_MASK), dst); - break; case LLSH3: - a = cpu_read_op(src2) << (cpu_read_op(src1) & 0x1f); - cpu_write_op(dst, a); - cpu_set_nz_flags(a, dst); - break; case LLSB3: - a = cpu_read_op(src2) << (cpu_read_op(src1) & 0x1f); - cpu_write_op(dst, a); - cpu_set_nz_flags(a, dst); + result = (t_uint64)cpu_read_op(src2) << (cpu_read_op(src1) & 0x1f); + cpu_write_op(dst, result); + cpu_set_nz_flags(result, dst); cpu_set_c_flag(0); - cpu_set_v_flag_op(a, dst); + cpu_set_v_flag_op(result, dst); break; case ARSW3: case ARSH3: @@ -2135,10 +2101,11 @@ t_stat sim_instr(void) /* Finish push of PC and PSW */ R[NUM_SP] += 8; - continue; + pc_incr = 0; + break; case MCOMW: case MCOMH: - case MCOMB: + case MCOMB: /* One's complement */ a = ~(cpu_read_op(src1)); cpu_write_op(dst, a); cpu_set_nz_flags(a, dst); @@ -2147,7 +2114,7 @@ t_stat sim_instr(void) break; case MNEGW: case MNEGH: - case MNEGB: + case MNEGB: /* Two's complement */ a = ~cpu_read_op(src1) + 1; cpu_write_op(dst, a); cpu_set_nz_flags(a, dst); @@ -2220,7 +2187,7 @@ t_stat sim_instr(void) /* However, if a move to PSW set the O bit, we have to generate an overflow exception trap */ if (op_is_psw(dst) && (R[NUM_PSW] & PSW_OE_MASK)) { - cpu_abort(NORMAL_EXCEPTION, INTEGER_OVERFLOW); + trap = INTEGER_OVERFLOW; } break; case MODW2: @@ -2347,10 +2314,10 @@ t_stat sim_instr(void) case NOP: break; case NOP2: - cpu_ilen += 1; + pc_incr += 1; break; case NOP3: - cpu_ilen += 2; + pc_incr += 2; break; case ORW2: case ORH2: @@ -2399,26 +2366,26 @@ t_stat sim_instr(void) case RGEQ: if (cpu_n_flag() == 0 || cpu_z_flag() == 1) { R[NUM_PC] = cpu_pop_word(); - continue; + pc_incr = 0; } break; case RGEQU: if (cpu_c_flag() == 0) { R[NUM_PC] = cpu_pop_word(); - continue; + pc_incr = 0; } break; case RGTR: if ((cpu_n_flag() | cpu_z_flag()) == 0) { R[NUM_PC] = cpu_pop_word(); - continue; + pc_incr = 0; } break; case RNEQ: case RNEQU: if (cpu_z_flag() == 0) { R[NUM_PC] = cpu_pop_word(); - continue; + pc_incr = 0; } break; case RET: @@ -2428,7 +2395,8 @@ t_stat sim_instr(void) R[NUM_AP] = b; R[NUM_PC] = c; R[NUM_SP] = a; - continue; + pc_incr = 0; + break; case RETG: abort_context = C_STACK_FAULT; a = read_w(R[NUM_SP] - 4, ACC_AF); /* PSW */ @@ -2465,7 +2433,8 @@ t_stat sim_instr(void) R[NUM_PC] = b; R[NUM_SP] -= 8; - continue; + pc_incr = 0; + break; case RETPS: if (cpu_execution_level() != EX_LVL_KERN) { cpu_abort(NORMAL_EXCEPTION, PRIVILEGED_OPCODE); @@ -2512,12 +2481,21 @@ t_stat sim_instr(void) /* Un-force kernel memory access */ cpu_km = FALSE; - continue; + pc_incr = 0; + break; case SPOP: + case SPOPD2: + case SPOPS2: + case SPOPT2: case SPOPRD: case SPOPRS: + case SPOPRT: + case SPOPWD: + case SPOPWS: + case SPOPWT: /* Memory fault is signaled when no support processor is active */ + csr_data |= CSRTIMO; cpu_abort(NORMAL_EXCEPTION, EXTERNAL_MEMORY_FAULT); break; case SUBW2: @@ -2550,36 +2528,37 @@ t_stat sim_instr(void) case RLEQ: if ((cpu_n_flag() | cpu_z_flag()) == 1) { R[NUM_PC] = cpu_pop_word(); - continue; + pc_incr = 0; } break; case RLEQU: if ((cpu_c_flag() | cpu_z_flag()) == 1) { R[NUM_PC] = cpu_pop_word(); - continue; + pc_incr = 0; } break; case RLSS: if ((cpu_n_flag() == 1) & (cpu_z_flag() == 0)) { R[NUM_PC] = cpu_pop_word(); - continue; + pc_incr = 0; } break; case REQL: if (cpu_z_flag() == 1) { R[NUM_PC] = cpu_pop_word(); - continue; + pc_incr = 0; } break; case REQLU: if (cpu_z_flag() == 1) { R[NUM_PC] = cpu_pop_word(); - continue; + pc_incr = 0; } break; case RSB: R[NUM_PC] = cpu_pop_word(); - continue; + pc_incr = 0; + break; case SAVE: /* Save the FP register */ write_w(R[NUM_SP], R[NUM_FP]); @@ -2626,6 +2605,10 @@ t_stat sim_instr(void) cpu_set_v_flag(0); break; case WAIT: + if (cpu_execution_level() != EX_LVL_KERN) { + cpu_abort(NORMAL_EXCEPTION, PRIVILEGED_OPCODE); + break; + } cpu_in_wait = TRUE; break; case XORW2: @@ -2652,7 +2635,21 @@ t_stat sim_instr(void) }; /* Increment the PC appropriately */ - R[NUM_PC] += cpu_ilen; + R[NUM_PC] += pc_incr; + + /* If TE and TM are both set, generate a trace trap */ + if ((R[NUM_PSW] & PSW_TE_MASK) && (R[NUM_PSW] & PSW_TM_MASK)) { + trap = TRACE_TRAP; + } + + /* Handle traps */ + if (trap) { + R[NUM_PSW] &= ~(PSW_ET_MASK); + R[NUM_PSW] &= ~(PSW_ISC_MASK); + R[NUM_PSW] |= NORMAL_EXCEPTION; + R[NUM_PSW] |= (uint32) (trap << PSW_ISC); + cpu_on_normal_exception(trap); + } } return stop_reason; @@ -2661,6 +2658,9 @@ t_stat sim_instr(void) static SIM_INLINE void cpu_on_process_exception(uint8 isc) { /* TODO: Handle */ + sim_debug(ERR_MSG, &cpu_dev, + "[%08x] CPU_ON_PROCESS_EXCEPTION not yet implemented.\n", + R[NUM_PC]); stop_reason = STOP_EX; return; } @@ -2751,13 +2751,14 @@ static SIM_INLINE void cpu_on_normal_exception(uint8 isc) /* Set context for STACK (FAULT) */ abort_context = C_STACK_FAULT; + /* Save address of next instruction to stack */ write_w(R[NUM_SP], R[NUM_PC]); /* Write 0, 3 to TM, ET fields of PSW */ R[NUM_PSW] &= ~(PSW_TM_MASK|PSW_ET_MASK); R[NUM_PSW] |= (3 << PSW_ET); - /* Save address of next instruction and PSW to stack */ + /* Save PSW to stack */ write_w(R[NUM_SP] + 4, R[NUM_PSW]); /* Set context for RESET (GATE VECTOR) */ @@ -2865,7 +2866,7 @@ static uint32 cpu_effective_address(operand *op) return read_w(R[op->reg] + sign_extend_b(op->embedded.b), ACC_AF); } - assert(0); + stop_reason = STOP_OPCODE; return 0; } @@ -3405,11 +3406,13 @@ void cpu_abort(uint8 et, uint8 isc) { /* We don't trap Integer Overflow if the OE bit is not set */ if ((R[NUM_PSW] & PSW_OE_MASK) || isc != INTEGER_OVERFLOW) { - R[NUM_PSW] &= ~(PSW_ISC_MASK); /* Clear ISC */ R[NUM_PSW] &= ~(PSW_ET_MASK); /* Clear ET */ - R[NUM_PSW] |= et; /* Set ET */ + R[NUM_PSW] &= ~(PSW_ISC_MASK); /* Clear ISC */ + R[NUM_PSW] |= et; /* Set ET */ R[NUM_PSW] |= (uint32) (isc << PSW_ISC); /* Set ISC */ + /* TODO: We no longer use ABORT_TRAP or ABORT_EXC, so + * it would be nice to clean this up. */ if (et == 3 && (isc == BREAKPOINT_TRAP || isc == INTEGER_OVERFLOW || isc == TRACE_TRAP)) { diff --git a/3B2/3b2_cpu.h b/3B2/3b2_cpu.h index e2a382c0..2640a1f5 100644 --- a/3B2/3b2_cpu.h +++ b/3B2/3b2_cpu.h @@ -85,6 +85,7 @@ * Opcodes */ typedef enum { + HALT = 0x00, /* Undocumented instruction */ SPOPRD = 0x02, SPOPD2 = 0x03, MOVAW = 0x04, diff --git a/3B2/3b2_defs.h b/3B2/3b2_defs.h index c9b55acd..cfa235c6 100644 --- a/3B2/3b2_defs.h +++ b/3B2/3b2_defs.h @@ -124,14 +124,15 @@ noret __libc_longjmp (jmp_buf buf, int val); #define C_STACK_FAULT 9 /* Debug flags */ -#define READ_MSG 0x01 -#define WRITE_MSG 0x02 -#define DECODE_MSG 0x04 -#define EXECUTE_MSG 0x08 -#define INIT_MSG 0x10 -#define IRQ_MSG 0x20 -#define IO_D_MSG 0x40 -#define TRACE_MSG 0x80 +#define READ_MSG 0x001 +#define WRITE_MSG 0x002 +#define DECODE_MSG 0x004 +#define EXECUTE_MSG 0x008 +#define INIT_MSG 0x010 +#define IRQ_MSG 0x020 +#define IO_D_MSG 0x040 +#define TRACE_MSG 0x080 +#define ERR_MSG 0x100 /* Data types operated on by instructions. NB: These integer values have meaning when decoding instructions, so this is not just an diff --git a/3B2/3b2_iu.c b/3B2/3b2_iu.c index 357ad4d0..51737b77 100644 --- a/3B2/3b2_iu.c +++ b/3B2/3b2_iu.c @@ -302,7 +302,7 @@ t_stat contty_reset(DEVICE *dtpr) memset(&iu_state, 0, sizeof(IU_STATE)); memset(&iu_contty, 0, sizeof(IU_PORT)); - tmxr_set_config_line(&contty_ldsc[0], "115200-8N1"); + tmxr_set_config_line(&contty_ldsc[0], "9600-8N1"); /* Start the CONTTY polling loop */ if (!sim_is_active(contty_rcv_unit)) {