//! 2.2.8.2 Execute a Single Step //! //! @param dnNrInstructions //! USBDM_GDI_API DiReturnT DiExecSingleStep ( DiUInt32T dnNrInstructions ) { USBDM_ErrorCode BDMrc; Logging::print("DiExecSingleStep(%d)\n", dnNrInstructions); CHECK_ERROR_STATE(); #if (TARGET == MC56F80xx) BDMrc = DSC_TargetStepN(dnNrInstructions); #else if (dnNrInstructions>1) { Logging::print("DiExecSingleStep() - Only a single step is supported!\n"); return setErrorState(DI_ERR_PARAM, ("Only a single step is allowed")); } BDMrc = USBDM_TargetStep(); #endif if (BDMrc != BDM_RC_OK) { return setErrorState(DI_ERR_NONFATAL, BDMrc); } return setErrorState(DI_OK); }
//! 2.2.8.2 Execute a Single Step //! //! @param dnNrInstructions //! USBDM_GDI_DECLSPEC DiReturnT DiExecSingleStep ( DiUInt32T dnNrInstructions ) { LOGGING_Q; log.print("(%d)\n", dnNrInstructions); USBDM_ErrorCode BDMrc; long unsigned ccrValue; long unsigned pcValue; unsigned char currentOpcode; const int interruptMask = (1<<3); const int tapOpcode = 0x84; const int tpaOpcode = 0x85; const int seiOpcode = 0x9B; const int cliOpcode = 0x9A; const int waitOpcode = 0x8F; const int rtiOpcode = 0x80; const int swiOpcode = 0x83; const int stopOpcode = 0x8E; CHECK_ERROR_STATE(); #if (TARGET == MC56F80xx) BDMrc = DSC_TargetStepN(dnNrInstructions); #else if (dnNrInstructions>1) { log.print("DiExecSingleStep() - Only a single step is supported!\n"); return setErrorState(DI_ERR_PARAM, ("Only a single step is allowed")); } /* * Cases to consider when masking interrupts during step * * +--------+-----------+---------+-----------------------------------------------------+ * | Opcode | Initial I | Final I | Problem - action | * +--------+-----------+---------+-----------------------------------------------------+ * | --- | 1 | X | None - no action (interrupts already masked) | * +--------+-----------+---------+-----------------------------------------------------+ * | CLI | 0 | ? | It may be possible for an interrupt to occur, | * | WAIT | | | setting I-flag which is then incorrectly cleared. | * | STOP | | | (I don't think it applies to CLI but be safe.) | * | SWI | | | - don't 'fix' CCR | * +--------+-----------+---------+-----------------------------------------------------+ * | RTI | 0 | 1 | Contrived but possible situation. I flag | * | | | | incorrectly cleared - don't 'fix' CCR | * +--------+-----------+---------+-----------------------------------------------------+ * | SEI | 0 | 1 | The instruction may set I-flag which is then | * | TAP | 0 | 1 | incorrectly cleared - don't 'fix' CCR | * +--------+-----------+---------+-----------------------------------------------------+ * | TPA | 0 | X | The wrong value is transferred to A - fix A | * +--------+-----------+---------+-----------------------------------------------------+ * | --- | 0 | 0 | CCR change - clear I-flag in new CCR | * +--------+-----------+---------+-----------------------------------------------------+ */ if (bdmOptions.maskInterrupts) { log.print("DiExecSingleStep() - checking if interrupt masking needed\n"); USBDM_ReadReg(HCS08_RegCCR, &ccrValue); if ((ccrValue&interruptMask) != 0) { // Interrupts already masked - just step BDMrc = USBDM_TargetStep(); } else { // Mask interrupts log.print("DiExecSingleStep() - masking interrupts\n"); USBDM_WriteReg(HCS08_RegCCR, ccrValue|interruptMask); // Get current instruction opcode USBDM_ReadReg(HCS08_RegPC, &pcValue); USBDM_ReadMemory(1,1,pcValue,¤tOpcode); // Do a step BDMrc = USBDM_TargetStep(); switch(currentOpcode) { case cliOpcode : case waitOpcode : case seiOpcode : case tapOpcode : case rtiOpcode : case swiOpcode : // Not ever stepped - treated as subroutine? case stopOpcode : log.print("DiExecSingleStep() - skipping CCR restore\n"); // Don't 'fix' CCR as updated by instruction or int ack break; case tpaOpcode : // Fix A & CCR (clear I flag) log.print("DiExecSingleStep() - fixing A & CCR reg\n"); USBDM_WriteReg(HCS08_RegA, ccrValue&~interruptMask); USBDM_WriteReg(HCS08_RegCCR, ccrValue&~interruptMask); break; default : // Fix CCR (clear I flag) // Unmask interrupts log.print("DiExecSingleStep() - fixing CCR reg\n"); USBDM_ReadReg(HCS08_RegCCR, &ccrValue); USBDM_WriteReg(HCS08_RegCCR, ccrValue&~interruptMask); break; } } } else BDMrc = USBDM_TargetStep(); #endif if (BDMrc != BDM_RC_OK) { return setErrorState(DI_ERR_NONFATAL, BDMrc); } return setErrorState(DI_OK); }