	.TITLE	EXECUTE
	.IDENT	"V1.9"
	.NLIST	BEX,CND
;
;   Author:	D. Mischler	26-JUN-87
;
;   This module contains the routines used for target task
;   communication and execution.
;
; V1.1	D. Mischler  29-NOV-87	Restore breakpoints after error SST.
; V1.2	D. Mischler  14-JAN-88	Rewrite for new MEMORY and TSKCOM.
; V1.3	D. Mischler  05-FEB-88	Support instruction simulation.
; V1.4	D. Mischler  26-MAY-88	Display next instruction at halt points.
; V1.5	D. Mischler  01-JUL-88	Clear SIMVLD as required.
; V1.6	D. Mischler  27-JUL-88	Display next instruction for strange halts.
; V1.7	D. Mischler  16-NOV-88	Conditionalize simulation support on I$MTPS.
; V1.8	D. Mischler  20-NOV-88	Always single-step if history is enabled.
; V1.9	D. Mischler  30-NOV-88	Display MMU status registers for MPV packets,
;				 use T$IPKT for unexpected packets.
;
.BPT	=	BPT		; Breakpoint trap opcode.

;
;   Macro to copy a null-terminated string.
;   The arguments must be registers.
;
	.MACRO	STRCPY	SRCREG,DSTREG,?LOOP
LOOP:	MOVB	(SRCREG)+,(DSTREG)+
	BNE	LOOP
	DEC	DSTREG
	.ENDM	STRCPY
	.PAGE
	.PSECT	RODATA,D,RO
;
;   Halt / tracepoint messages.
;
BRKMSG:	.ASCIZ	"Breakpoint Reached"
DEBMSG:	.ASCIZ	"MCR DEBUG Command "
NXTMSG:	.ASCIZ	" Next Instruction "
STPMSG:	.ASCIZ	"Zero Step Count   "
TRCMSG:	.ASCIZ	"Tracepoint Reached"
WCHMSG:	.ASCIZ	"Location "
	.ASCIZ	" modified.  Old value: "
	.ASCIZ	", new value: "
;
;   Messages associated with unexpected halt packets.
;
BPTMSG:	.ASCIZ	"Unexpected BPT Instruction"
EMTMSG:	.ASCIZ	"Non-RSX EMT Instruction"
FPXMSG:	.ASCIZ	"PDP-11/40 Floating Point Exception"
ILLMSG:	.ASCIZ	"Illegal Instruction"
IOTMSG:	.ASCIZ	"IOT Instruction"
MPVMSG:	.ASCIZ	"Memory Protection Violation. MMR0="
	.ASCIZ	" MMR1="
	.ASCIZ	" MMR2="
ODDMSG:	.ASCIZ	"Odd Address or other Trap 4"
TRPMSG:	.ASCIZ	"TRAP Instruction"
	.EVEN
;
;   Table of halt response packet types and associated messages.
;
HRTTBL:	.WORD	ODDMSG,RT.ODD	; Odd address trap packet.
	.WORD	ILLMSG,RT.ILL	; Illegal instruction.
	.WORD	IOTMSG,RT.IOT	; IOT instruction.
	.WORD	TRPMSG,RT.TRP	; TRAP instruction.
	.WORD	EMTMSG,RT.EMT	; Non-RSX EMT instruction.
	.WORD	FPXMSG,RT.FPX	; PDP-11/40 FP exception.
HRTLEN	=	<.-HRTTBL>/4	; Number of table entries.
	.PAGE
	.PSECT	CODE,I,RO
;
;   GO continues task execution.
;
GO::	CALL	X$RWPT		; Get current values of all watchpoints.
	CALL	U$FNXT		; Has a continuation address been specifed?
	BCS	10$		; No, use the current PC.
	CALL	XPRESS		; Evaluate continuation address, OK?
	BCS	XPERR		; No, complain.
	CALL	M$W.PC		; Modify target task PC, OK?
	BCS	XPERR		; No, complain.
10$:	CALL	X$STEP		; Execute a single instruction, OK to continue?
	BCS	20$		; No, stop right away.
	TST	PROLST		; Have any profile ranges been set?
	BNE	10$		; Yes, continue to step.
	TST	WCHLST		; Have any watchpoints been set?
	BNE	10$		; Yes, continue to step.
	.IF DF	I$MTPS
	TST	HSTPTR		; Is instruction history enabled?
	BNE	10$		; Yes, continue to step.
	CLR	SIMVLD		; Simulated registers are no longer valid.
	.IFTF
	CALL	X$SBPT		; Put a BPT instruction in every breakpoint.
	CALL	X$PROC		; Allow task to run free. Reached halt point?
	BCC	10$		; No, assume tracepoint and keep going.
20$:
	.IFT
	CLR	SIMVLD		; Simulated registers are not valid.
	.ENDC	; DF I$MTPS
	RETURN

;
;   STEP the target task through one or more instructions.
;
STEP::	CALL	X$RWPT		; Get current values of all watchpoints.
	MOV	#1,STPCNT	; Set default step count.
	CALL	U$FNXT		; Has a step count been specified?
	BCS	10$		; No, use the default.
	CALL	XPRESS		; Evaluate step count expression, OK?
	BCS	XPERR		; No, complain.
	MOV	R1,STPCNT	; Save step count.
10$:	CALL	X$STEP		; Execute a single instruction, OK to continue?
	BCS	20$		; No, terminate early.
	DEC	STPCNT		; Executed all requested instructions?
	BNE	10$		; No, keep going.
	MOV	#STPMSG,R5	; Point to completion message.
	CALL	DSTMSG		; Display step completion message.
	.IF DF	I$MTPS
20$:	CLR	SIMVLD		; Simulated registers are no longer valid.
	RETURN
	.IFF
20$:	RETURN
	.ENDC	; DF I$MTPS
;   Step count expression had an error in it.
XPERR:	CALLR	ERROR		; Complain about error and return.
	.PAGE
;
;   Subroutine to execute a single instruction.
;   The carry will be set if stepping should not continue.
;
X$STEP:
	.IF DF	I$MTPS
	CALL	SIM11		; Simulate one instruction, OK?
	BCS	10$		; No, single step the target task.
	CALL	X$CKPT		; Set carry if halt or trace point reached.
	ROL	R5		; Save carry for later.
	MOV	SIM.PC,R1	; Get simulated PC.
	BR	20$		; Enter common code.
;   Instruction cannot be simulated: single step the task.
;   R0 contains the instruction opcode word and SIMVLD contains zero.
10$:	CMP	#.BPT,R0	; Is the next instruction a BPT?
	BEQ	UNXBPT		; Yes, it must be unexpected.
	.IFF	; DF I$MTPS
	CALL	M$R.PC		; Get target task PC.
	MOV	R1,R5		; Put it in place.
	CALL	M$RI5P		; Read opcode word, OK?
	BCS	10$		; No, step through it to get an error.
	CMP	#.BPT,R1	; Is the next instruction a BPT?
	BEQ	UNXBPT		; Yes, it must be unexpected.
10$:
	.ENDC	; DF I$MTPS
	CALL	M$M.PS		; Map the PSW, OK?
	BCS	XPERR		; No, complain.
	BIS	#PS.TRC,(R1)	; Set trace bit in PSW.
	MOV	SP,TRCTRP	; Indicate trace trap is enabled.
	CALL	X$PROC		; Execute a single instruction.
	ROL	R5		; Preserve the carry (halt stepping) flag.
	CALL	M$R.PC		; Read task PC.
;   Low bit of R5 indicates stepping should cease, R1 contains target task PC.
20$:	MOV	#PROLST,R4	; Point to profile range list head.
30$:	MOV	(R4),R4		; Point to next profile range, zero?
	BEQ	40$		; Yes, return to caller.
	MOV	R1,R3		; Copy task PC.
	SUB	PR.BAS(R4),R3	; Is PC too low to be in this range?
	BLO	30$		; Yes, check next range.
	CMP	PR.RNG(R4),R3	; Is PC too high?
	BLO	30$		; Yes, check next range.
	CLR	R2		; Zero extend address offset.
	DIV	PR.CMP(R4),R2	; Divide offset by compression factor.
	BIC	#1,R2		; Make sure result is even.
	ASL	R2		; Double result (counters are 32-bits).
	ADD	R4,R2		; Add profile block address.
	ADD	#PR.CNT+2,R2	; Point to low word of appropriate counter.
	ADD	#1,(R2)		; Increment counter.
	ADC	-(R2)
40$:	ROR	R5		; Restore carry (halt stepping) flag.
	RETURN
;   Here for unexpected BPT discovered while stepping.
UNXBPT:	CALL	M$R.PC		; Get target task PC.
	ADD	#2,R1		; Advance it over the BPT instruction.
	CALL	M$W.PC		; Write back target task PC.
	MOV	#BPTMSG,R1	; Point to message.
HLTMSG:	CALL	LINOUT		; Display it.
	MOV	#NXTMSG,R5	; Point to next instruction message.
	CALL	DSTMSG		; Display next instruction.
	SEC			; Indicate halt point reached.
	RETURN
	.PAGE
;
;   Subroutine to proceed with task execution and handle traps.
;   If execution may continue after the task responds then the
;   carry will be clear on exit.
;
X$PROC:	CALL	T$PRO			; Send proceed command and get response.
X$STRT::
	MOV	R.TYP(R0),R2		; Get response packet type.
	CMP	#RT.TRC,R2		; Does packet indicate a trace trap?
	BEQ	30$			; Yes, take care of it.
	CMP	#RT.BPT,R2		; Is it a break point trap?
	BEQ	50$			; Yes, check it.
	CMP	#RT.MPV,R2		; Memory protection violation?
	BEQ	60$			; Yes, display message with MMU status.
	CALL	X$RBPT			; Restore breakpoint locations.
	MOV	#HRTTBL,R3		; Point to halt response type table.
	MOV	#HRTLEN,R4		; Get number of entries in table.
10$:	MOV	(R3)+,R1		; Set up possible message type.
	CMP	(R3)+,R2		; Found response packet type?
	BEQ	20$			; Yes, display message.
	SOB	R4,10$			; Check all table entries.
;   Response packet type was undecodeable. Debugging aid is confused.
	CALL	T$IPKT			; Take care of illegal packet.
	BR	75$			; Exit with carry set.
;   Display halt packet message.
20$:	CALL	HLTMSG			; Display appropriate message.
	SEC				; Indicate failure.
	RETURN
;
;   Packet indicates a trace trap occurred.
;
30$:	CALL	M$M.PS		; Map processor status, OK?
	BCS	70$		; No, complain.
	BIC	#PS.TRC,(R1)	; Turn off trace trap.
	MOV	TRCTRP,R0	; Get trace trap enable flag.
	CLR	TRCTRP		; Reflect actual PSW setting.
	TST	R0		; Was trace trap caused by MCR DEBUG?
	BEQ	40$		; Yes, restore breakpoint locations.
	CALLR	X$CKPT		; Exit with halt point status in carry.
;
;   Execution stopped by MCR DEBUG command (packet indicates trace trap).
;
40$:	CALL	X$RBPT		; Restore breakpoint locations in memory.
	MOV	#DEBMSG,R5	; Point to MCR DEBUG message.
	CALL	DSTMSG		; Display MCR DEBUG message.
	CALL	X$CKPT		; Check halt points.
	SEC			; Always stop execution.
	RETURN
	.PAGE
;
;   Packet indicates a breakpoint trap occurred.
;
50$:	CALL	X$RBPT		; Restore breakpoint locations.
	CALL	M$R.PC		; Read task PC, OK?
	BCS	70$		; No, complain.
	SUB	#2,R1		; Back up to start of BPT instruction.
	CALL	M$W.PC		; Write back task PC, OK?
	BCS	70$		; No, complain.
	CALL	X$CKPT		; Has a halt or tracepoint been reached?
	BLOS	80$		; Yes, just go away for a while.
	JMP	UNXBPT		; Take care of unexpected breakpoint.
;
;   Memory protection violation occurred.
;   Display message with status, etc.
;
60$:	MOV	R.VDAT+2(R0),-(SP)	; Push MMR2 value.
	MOV	R.VDAT(R0),-(SP)	; Push MMR1 value.
	MOV	R.VDAT+4(R0),R1		; Get MMR0 value.
	MOV	#TRMBUF,R0		; Point to start of terminal buffer.
	MOV	#MPVMSG,R5		; Point to MP violation message.
	STRCPY	R5,R0			; Copy start of message into place.
	CALL	C$NUM			; Convert MMR0 to a number.
	STRCPY	R5,R0			; Copy MMR1 label into place.
	MOV	(SP)+,R1		; Get MMR1 value.
	CALL	C$NUM			; Convert MMR1 to a number.
	STRCPY	R5,R0			; Copy MMR2 label into place.
	MOV	(SP)+,R1		; Get MMR2 value.
	CALL	C$VALU			; Convert MMR2 to an address.
	CALL	DSPMSG			; Terminate buffer and display message.
	CALL	X$RBPT			; Restore breakpoint locations.
	MOV	#NXTMSG,R5		; Point to next instruction message.
	CALL	DSTMSG			; Display it.
	BR	75$			; Halt execution.
;   Display an error and return with carry set.	
70$:	CALL	ERROR		; Display error message.
75$:	SEC			; Indicate halt point reached.
80$:	RETURN
	.PAGE
;
;   Subroutine to check if a halt point has been reached.
;   On exit:	Carry flag set if execution should stop.
;		Zero flag set if a tracepoint is reached.
;
X$CKPT:
	.IF DF	I$MTPS
	TST	SIMVLD		; Are simulated registers valid?
	BEQ	1$		; No, get PC with M$R.PC.
	MOV	SIM.PC,-(SP)	; Push target task PC for comparison.
	BR	2$		; Re-enter common code.
	.ENDC	; DF I$MTPS
1$:	CALL	M$R.PC		; Get target task PC.
	MOV	R1,-(SP)	; Save it for comparison.
2$:	MOV	SP,R0		; Set up for exit (ROR R0 clears C and Z).
;   Check all tracepoints to see if one has been reached.
	MOV	TRCLST,R4	; Are any tracepoints set?
	BEQ	30$		; No, check watchpoints.
10$:	CMP	(SP),P.ADDR(R4)	; Has this tracepoint been reached?
	BNE	20$		; No, check next.
	CLR	R0		; Cause Z flag to be set on exit.
	MOV	#TRCMSG,R5	; Point to tracepoint message.
	CALL	DSTMSG		; Display it.
20$:	MOV	(R4),R4		; Any more tracepoints to check?
	BNE	10$		; Yes, look at the next one.
;   Check all watchpoints to see if any have changed.
30$:	MOV	WCHLST,R4	; Are any watchpoints set?
	BEQ	60$		; No, check breakpoints.
40$:	MOV	P.ADDR(R4),R5	; Get watchpoint address.
	CALL	M$RD5P		; Get watchpoint location contents.
	CMP	P.VALU(R4),R1	; Has this watchpoint changed?
	BEQ	50$		; No, check next.
	CALL	DWPMSG		; Display watchpoint message.
	BIS	#1,R0		; Cause carry to be set on exit.
	MOV	R1,P.VALU(R4)	; Update watched location value.
50$:	MOV	(R4),R4		; Any more watchpoints to check?
	BNE	40$		; Yes, look at the next one.
;   Check all breakpoints to see if one has been reached.
60$:	MOV	BRKLST,R4	; Are any breakpoints set?
	BEQ	90$		; No, check for MCR DEBUG.
70$:	CMP	(SP),P.ADDR(R4)	; Has this breakpoint been reached?
	BNE	80$		; No, check next.
	BIS	#1,R0		; Cause carry to be set on exit.
	MOV	#BRKMSG,R5	; Point to breakpoint message.
	CALL	DSTMSG		; Display it.
80$:	MOV	(R4),R4		; Any more breakpoints to check?
	BNE	70$		; Yes, look at the next one.
;   Check for an MCR DEBUG command.
90$:	TST	MCRDEB		; Has an MCR DEBUG command been received?
	BEQ	100$		; No, time to leave.
	MOV	R0,-(SP)	; Preserve status flags.
	MOV	#DEBMSG,R5	; Point to MCR DEBUG message.
	CALL	DSTMSG		; Display MCR DEBUG message.
	MOV	(SP)+,R0	; Recover status flags.
	BIS	#1,R0		; Cause carry to be set on exit.
100$:	TST	(SP)+		; Pop target task PC.
	ROR	R0		; Set flags appropriately.
	RETURN
	.PAGE
;
;   Subroutine to display a watchpoint message.
;   On entry:	R1 contains new watchpoint value,
;		R4 points to watchpoint block.
;
DWPMSG:	CALL	$SAVAL		; Preserve all registers.
	MOV	#TRMBUF,R0	; Point to start of terminal buffer.
	MOV	#WCHMSG,R5	; Point to watchpoint message.
	STRCPY	R5,R0		; Copy first part of message into place.
	MOV	R1,-(SP)	; Preserve new watchpoint value.
	MOV	P.ADDR(R4),R1	; Get watchpoint address.
	CALL	C$VALU		; Append it to the message.
	STRCPY	R5,R0		; Append label for old contents.
	MOV	P.VALU(R4),R1	; Get old watchpoint contents.
	CALL	C$NUM		; Append it to the message.
	STRCPY	R5,R0		; Append label for new contents.
	MOV	(SP)+,R1	; Get new watchpoint contents.
	CALL	C$NUM		; Append it to the message.
	CALL	DSPMSG		; Terminate buffer and display message.
	MOV	#NXTMSG,R5	; Point to next instruction message.
;
;   Subroutine to display a message with a disassembled instruction.
;   On entry:	R5 points to message text.
;
DSTMSG:	CALL	$SAVAL		; Preserve all registers.
	CALL	M$R.PC		; Get target task PC value.
	MOV	#TRMBUF,R0	; Point to start of terminal buffer.
	STRCPY	R5,R0		; Copy message text.
	MOVB	#' ,(R0)+	; Delimit address.
	MOVB	#'-,(R0)+
	MOVB	#' ,(R0)+
	MOV	R1,R5		; Set up task PC address.
	CALL	U$ADDR		; Append target task PC to the message.
	CALL	DISASM		; Disassemble next instruction.
DSPMSG:	CLRB	(R0)		; Terminate message.
	MOV	#TRMBUF,R1	; Point to message buffer.
	CALLR	LINOUT		; Display message and return.
	.PAGE
;
;   Subroutine to store a BPT in the task for every breakpoint and tracepoint.
;
X$SBPT:	MOV	#BRKLST,R4	; Point to head of breakpoint list.
	CALL	10$		; Save breakpoint locations.
;   Replace tracepoints with BPT instructions.
	MOV	#TRCLST,R4	; Point to head of tracepoint list.
10$:	MOV	(R4),R4		; Get address of next halt point block, zero?
	BEQ	20$		; Yes, all finished.
	MOV	P.ADDR(R4),R5	; Get halt point address.
	INC	P.ADDR(R4)	; Indicate breakpoint has been set.
	CALL	M$RI5P		; Get instruction opcode.
	MOV	R1,P.VALU(R4)	; Save it for later.
	SUB	#2,R5		; Restore halt point address.
	MOV	#.BPT,R1	; Get a BPT opcode.
	CALL	M$WI5		; Save it in the task, OK?
	BCC	10$		; Yes, go on.
	MOV	#E.HPWF,R1	; Point to halt point write failure message.
	CALL	ERROR		; Display it.
	BIC	#1,P.ADDR(R4)	; Indicate breakpoint has not been set.
	BR	10$		; Process next halt point.
20$:	RETURN
;
;   Subroutine to restore all tracepoint and breakpoint locations.
;   Note that breakpoints are set first, so they must be restored last.
;
X$RBPT:	MOV	#TRCLST,R4	; Point to head of tracepoint list.
	CALL	10$		; Restore tracepoint locations.
	MOV	#BRKLST,R4	; Point to head of breakpoint list.
10$:	MOV	(R4),R4		; Get address of next breakpoint block, zero?
	BEQ	20$		; Yes, all finished.
	MOV	P.ADDR(R4),R5	; Get breakpoint address.
	BIT	#1,R5		; Has this breakpoint actually been set?
	BEQ	10$		; No, skip it.
	DEC	R5		; Repair breakpoint location.
	MOV	R5,P.ADDR(R4)	; Save corrected breakpoint address.
	MOV	P.VALU(R4),R1	; Get proper location contents.
	CALL	M$WI5		; Restore instruction opcode.
	BR	10$		; Process next breakpoint.
20$:	RETURN

;
;   Routine to read the contents of every watchpoint.
;
X$RWPT:	MOV	#WCHLST,R4	; Point to head of watchpoint list.
10$:	MOV	(R4),R4		; Get address of next watchpoint block, zero?
	BEQ	20$		; Yes, all finished.
	MOV	P.ADDR(R4),R5	; Get watchpoint address.
	CALL	M$RD5P		; Get watched location contents.
	MOV	R1,P.VALU(R4)	; Save it for later.
	BR	10$		; Do all watchpoints.
20$:	RETURN

	.END
