static void debug_action( int action ) { stop_emulation(); switch( action ) { case kDbgNOP: break; case kDbgGo: resume_emulation(); break; case kDbgGoRFI: set_break_flag( BREAK_RFI ); resume_emulation(); break; case kDbgGoUser: set_break_flag( BREAK_USER ); resume_emulation(); break; case kDbgStep: set_break_flag( BREAK_SINGLE_STEP ); restore_breakpoints(); resume_emulation(); break; case kDbgStop: stop_emulation(); break; case kDbgExit: // quit_emulation(); break; } }
static int rvec_debugger( int dummy_rvec, int num ) { printm("RVEC-DEBUGGER <%x>\n", num ); stop_emulation(); return 0; }
static int rvec_unusual_prog_excep( int dummy_rvec, ulong opcode, ulong srr1 ) { printm("Unusual program exception occured (SRR1 = %08lX)\n", srr1 ); stop_emulation(); return 0; }
static int rvec_spr_write( int dummy_rvec, int sprnum, ulong value ) { switch( sprnum ) { case S_THRM1: /* Thermal 1 */ case S_THRM2: /* Thermal 2 */ case S_THRM3: /* Thermal 3 */ mregs->spr[sprnum] = value; fix_thrm_spr(); break; case S_MSSCR0: value &= ~MOL_BIT(8); /* 7400 DL1HWF, L1 data cache hw flush */ break; case S_L2CR: /* L2 Cache Control Register */ /* 750 doesn't clear L2I but 7455 does */ value &= ~(MOL_BIT(10) | MOL_BIT(31)); /* Clear L2I and L2IP */ break; case S_L3CR: /* L3 Cache Control Register */ value &= ~(MOL_BIT(20) | MOL_BIT(21)); /* Clear L3HWF and L3I */ mregs->spr[sprnum] = value; break; default: printm("Write to unimplemented SPR #%d (%08lX)\n", sprnum, value ); mregs->spr[sprnum] = value; stop_emulation(); } mregs->nip += 4; return 0; }
static int rvec_priv_inst( int dummy_rvec, ulong inst ) { int op, op_ext, b1, b2, b3; /* unhandled privileged instruction in supervisor mode */ /* IMPORTANT: The GPRs are not available here! */ op = OPCODE_PRIM( inst ); op_ext = OPCODE_EXT( inst ); b1 = B1( inst ); /* bit 6-10 */ b2 = B2( inst ); /* bit 11-15 */ b3 = B3( inst ); /* bit 16-20 */ switch( OPCODE(op,op_ext) ) { case OPCODE( 31, 370 ): /* tlbia (opt.) */ /* not implemented on the 601,603,604,G3 (G4?) */ break; case OPCODE( 31, 470 ): /* dcbi rA,rB -- rA=b2 rB=b3 */ printm("dcbi treated as nop\n"); mregs->nip += 4; return 0; default: printm("Unknown privileged instruction, opcode %lX\n", inst); stop_emulation(); break; } mac_exception( 0x700, MOL_BIT(13) ); return 0; }
static int __dbg rvec_break( int dummy_rvec, int break_flag ) { switch( break_flag ) { case BREAK_RFI: if( (molcpu.break_flags & BREAK_USER) ) { if( !(mregs->msr & MSR_PR) ) return 0; clear_break_flag( BREAK_USER ); } printm("BREAK-RFI (%08lX)\n", mregs->nip ); break; case BREAK_EA_PAGE: /* breakpoint might not have been written */ printm("ea-break at %08lX\n", mregs->nip ); restore_breakpoints(); setup_breakpoints(); break; case BREAK_SINGLE_STEP: if( molcpu.break_flags & BREAK_SINGLE_STEP_CONT ) { if( !is_stop_breakpoint( mregs->nip ) ) return 0; clear_break_flag( BREAK_SINGLE_STEP_CONT ); } //setup_breakpoints(); break; default: printm("rvec_break: Unknown break flag %d\n", break_flag ); break; } stop_emulation(); clear_break_flag( break_flag ); return 0; }
static int rvec_illegal_inst( int dummy_rvec, ulong inst ) { /* IMPORTANT: The GPRs are not available here! */ if( inst == BREAKPOINT_OPCODE ) { int val = is_stop_breakpoint( mregs->nip ); if( val > 0 ) stop_emulation(); if( val ) { /* conditional breakpoint */ return 0; } /* no breakpoint - take an exception */ } /* printm("ILLEGAL INSTRUCTION %08lX\n", inst ); */ mac_exception( 0x700, MOL_BIT(12) ); return 0; }
int _rvec_spr_read( int dummy_rvec, int sprnum, int gprnum ) { switch( sprnum ) { case S_THRM1: /* Thermal 1 */ case S_THRM2: /* Thermal 2 */ case S_THRM3: /* Thermal 3 */ fix_thrm_spr(); /* fall through */ case S_L2CR: case S_L3CR: case S_MSSCR0: break; default: printm("Read from unimplemented SPR #%d\n", sprnum ); stop_emulation(); } mregs->gpr[gprnum] = mregs->spr[sprnum]; mregs->nip += 4; return 0; }
static int rvec_unexpected_mmu_cond( int rvec, int param1, int param2 ) { switch( rvec ) { case RVEC_UNUSUAL_DSISR_BITS: /* dar, dsisr */ printm("RVEC_UNUSUAL_DSISR_BITS: dar %08X, dsisr %08X\n", param1, param2 ); break; case RVEC_MMU_IO_SEG_ACCESS: printm("RVEC_MMU_IO_SEG_ACCESS\n"); break; case RVEC_BAD_NIP: /* nip_phys */ printm("Instruction Pointer not in ROM/RAM (nip %08lX, nip_phys %08X)\n", mregs->nip, param1 ); if( !debugger_enabled() ) quit_emulation(); stop_emulation(); break; default: printm("rvec_unexpected_mmu_cond, unimplemented vector %d\n", rvec ); break; } return 0; }
/* returns 1 if GPRs have been modified */ int _rvec_io_write( int dummy_rvec, ulong mphys_ioaddr, void *usr_data ) { int op, op_ext, rS, rA, rB, d, flag=0, ret=0; ulong ea, cont, len, inst=mregs->inst_opcode; enum { byte=1, half=2, word=4, len_mask=7, indexed=8, update=16, reverse=32, nop=64, fpinst=128 }; /* do_io_write() is considered FPU-unsafe */ shield_fpu( mregs ); /* break instruction into parts */ op = OPCODE_PRIM( inst ); op_ext = OPCODE_EXT( inst ); rS = B1( inst ); /* bit 6-10 */ rA = B2( inst ); /* bit 11-15 */ rB = B3( inst ); /* bit 16-20 */ d = BD( inst ); /* bit 16-31 sign extended */ switch( op ) { case 38: /* stb rS,d(rA) */ flag = byte ; break; case 39: /* stbu rS,d(rA) */ flag = byte | update; break; case 44: /* sth rS,d(rA) */ flag = half ; break; case 45: /* sthu rS,d(rA) */ flag = half | update; break; case 36: /* stw rS,d(rA) */ flag = word ; break; case 37: /* stwud rS,d(rA) */ flag = word | update; break; case 54: /* stfd frS,d(rA) */ /* FPU */ flag = word | fpinst; break; case 55: /* stfdu frS,d(rA) */ /* FPU */ flag = word | fpinst | update; break; } if( !flag && op==31 ) { switch( op_ext ) { case 215: /* stbx rS,rA,rB */ flag = byte | indexed ; break; case 247: /* stbux rS,rA,rB */ flag = byte | indexed | update; break; case 407: /* sthx rS,rA,rB */ flag = half | indexed ; break; case 439: /* sthux rS,rA,rB */ flag = half | indexed | update; break; case 151: /* stwx rS,rA,rB */ flag = word | indexed ; break; case 183: /* stwux rS,rA,rB */ flag = word | indexed | update; break; case 918: /* sthbrx rS,rA,rB */ flag = half | indexed | reverse; break; case 662: /* stwbrx rS,rA,rB */ flag = word | indexed | reverse; break; case 727: /* stfdx frS,rA,rB */ /* printm("FPU store inst\n"); */ flag = word | indexed | fpinst; break; case 759: /* stfdux frS,rA,rB */ /* printm("FPU store inst\n"); */ flag = word | indexed | update | fpinst; break; } } if( flag & len_mask ) { /* instruction found */ if( flag & indexed ) { /* stxxx rS,rA,rB */ ea = mregs->gpr[rB]; ea += rA ? mregs->gpr[rA] : 0; } else { /* stxxx rS,d(rA) */ ea = rA ? mregs->gpr[rA] : 0; ea += d; } if( !(flag & fpinst ) ) cont = mregs->gpr[rS]; else { save_fpu_completely( mregs ); cont = mregs->fpr[rS].h; } len = flag & len_mask; if( flag & byte ) { cont &= 0xff; } else if( flag & half ) { if( !(flag & reverse) ) cont &= 0xffff; else cont = bswap_16( cont ); } else if( flag & reverse ) cont = ld_le32(&cont); /* ea is the mac untranslated address, * mregs->mmu_ioaddr holds the translated address */ do_io_write( usr_data, mphys_ioaddr, cont, len ); if( flag & fpinst ) { if( ((mphys_ioaddr+4) & 0xfff) < 4 ) printm("emulate store data inst: Possible MMU translation error\n"); do_io_write( usr_data, mphys_ioaddr+4, mregs->fpr[rS].l, 4 ); } if( (flag & update) && rA ) { mregs->gpr[rA] = ea; ret = 1; } } if( flag ) mregs->nip += 4; else { printm("Unimplemented store instruction %08lX\n", inst ); stop_emulation(); } return ret; }
/* returns 1 if GPRs have been modified */ int _rvec_io_read( int dummy_rvec, ulong mphys_ioaddr, void *usr_data ) { ulong ea, cont, inst=mregs->inst_opcode; int op, op_ext, rD, rA, rB, d; int flag=0, ret=1; enum { byte=1, half=2, word=4, len_mask=7, indexed=8, update=16, zero=32, reverse=64, nop=128, fpinst=256 }; /* do_io_read() is considered FPU-unsafe */ shield_fpu( mregs ); /* break instruction into parts */ op = OPCODE_PRIM( inst ); /* bit 0-5 */ op_ext = OPCODE_EXT( inst ); rD = B1( inst ); /* bit 6-10 */ rA = B2( inst ); /* bit 11-15 */ rB = B3( inst ); /* bit 16-20 */ d = BD( inst ); /* bit 16-31 sign extended */ switch( op ) { case 34: /* lbz rD,d(rA) */ flag = byte | zero; break; case 35: /* lbzu rD,d(rA) */ flag = byte | zero | update; break; case 40: /* lhz rD,d(rA) */ flag = half | zero; break; case 41: /* lhzu rD,d(rA) */ flag = half | zero | update; break; case 42: /* lha rD,d(rA) */ flag = half; break; case 43: /* lhau rD,d(rA) */ flag = half | update; break; case 32: /* lwz rD,d(rA) */ flag = word | zero; break; case 33: /* lwzu, rD,d(rA) */ flag = word | zero | update; break; case 50: /* lfd frD,d(rA) */ /* FPU */ flag = word | fpinst | zero; break; case 51: /* lfdu frD, d(rA) */ /* FPU */ flag = word | fpinst | update | zero; break; } if( !flag && op==31 ) { switch( op_ext ) { /* lxxx rD,rA,rB */ case 87: /* lbzx rD,rA,rB */ flag = byte | indexed | zero; break; case 119: /* lbzux rD,rA,rB */ flag = byte | indexed | zero | update; break; case 279: /* lhzx rD,rA,rB */ flag = half | indexed | zero; break; case 311: /* lhzux rD,rA,rB */ flag = half | indexed | zero | update; break; case 343: /* lhax rD,rA,rB */ flag = half | indexed; break; case 375: /* lhaux rD,rA,rB */ flag = half | indexed | update; break; case 23: /* lwzx rD,rA,rB */ flag = word | indexed | zero; break; case 55: /* lwzux rD,rA,rB */ flag = word | indexed | zero | update; break; case 790: /* lhbrx rS,rA,rB */ flag = half | indexed | zero | reverse; break; case 534: /* lwbrx rS,rA,rB */ flag = word | indexed | zero | reverse; break; case 599: /* lfdx frD,rA,rB */ /* FPU */ flag = word | indexed | zero | fpinst; break; case 631: /* lfdux frD,rA,rB */ /* FPU */ flag = word | indexed | zero | update | fpinst; break; case 86: /* dcbf rA,rB - cache instruction*/ /* treat as nop if data-translation is off */ flag = (mregs->msr & MSR_DR) ? 0 : nop; break; } } if( flag & len_mask) { /* instruction found */ if( flag & indexed ) { /* lxxx rD,rA,rB */ ea = mregs->gpr[rB]; ea += rA ? mregs->gpr[rA] : 0; } else { /* lxxx rD,d(rA) */ ea = rA ? mregs->gpr[rA] : 0; ea += d; } /* ea is the mac untranslated address, */ /* mphys_ioaddr is the mac-physical address */ cont = 0; do_io_read( usr_data, mphys_ioaddr, (flag & len_mask), &cont ); if( flag & byte ){ cont &= 0xff; } else if( flag & half ) { cont &= 0xffff; if( !(flag & zero) ) /* algebraic */ cont |= (cont & 0x8000)? 0xffff0000 : 0; if( flag & reverse ) cont = bswap_16( cont ); } else if( flag & reverse) cont = ld_le32(&cont); if( !(flag & fpinst) ) mregs->gpr[rD] = cont; else { /* FPU instruction */ save_fpu_completely( mregs ); ret = 0; mregs->fpr[rD].h = cont; /* check for 4K boundary crossings... */ if( ((mphys_ioaddr+4) & 0xfff) < 4 ) printm("emulate_load_data_inst: MMU translation might be bad\n"); do_io_read( usr_data, mphys_ioaddr+4, 4, &cont ); mregs->fpr[rD].l = cont; reload_tophalf_fpu( mregs ); } if( (flag & update) && rA && (rA!=rD || (flag & fpinst)) ) { ret = 1; mregs->gpr[rA] = ea; } } if( flag ) mregs->nip += 4; else { printm("Unimplemented load instruction %08lX\n", inst ); stop_emulation(); } return ret; }
void DCPUToolchain::Stop(DebuggingSession* session) { gl->killWidgets(); paused = true; stop_emulation(); }