3b2: Allow handling of TRACE and BREAKPOINT traps
The 3B2 emulator did not have support for traps, rendering debugging under the simulator fairly useless. This change adds support for trap handling. The 'sdb' UNIX debugger under SVR3 should now work correctly.
This commit is contained in:
parent
8494112ee4
commit
651faa78ae
4 changed files with 138 additions and 133 deletions
251
3B2/3b2_cpu.c
251
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)) {
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
* Opcodes
|
||||
*/
|
||||
typedef enum {
|
||||
HALT = 0x00, /* Undocumented instruction */
|
||||
SPOPRD = 0x02,
|
||||
SPOPD2 = 0x03,
|
||||
MOVAW = 0x04,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)) {
|
||||
|
|
Loading…
Add table
Reference in a new issue