

BRKCT0		equ	$0020
BRKCT1		equ	$0021
BRKAH		equ	$0022
BRKAL		equ	$0023
BRKDH		equ	$0024
BRKDL		equ	$0025

bp_enable	equ	$4c7f





*******
* > step <addr>
* begins execution line by line on a program at <addr>
*******

***
;step_sub: "m_step.asm"
;	Called from the command line with "> step <addr>" and it begins
;	Steps through a program beginning at <addr> using the space bar
;	To go to the next line and enter to stop stepping.
;	Reg Input:
;		None
;	Reg Output:
;		none
***

step_sub:
		pshy				; store buffer pointer
		jsr	parse_address		; parse address from command buffer
						; X = address to go to
		jsr	disasm			; X = instruction after first

		jsr	set_bp_0		; stores starting address into the first breakpoint register

		jsr	hwbp_enable_sub		; enable hardware breakpoints (Dual Address SWI)
						
		bset	hw_step_byte, #$ff	; sets the hw_step_byte to a non-zero value
						; which is important to the swi_handler

		ldy	#newline		; loads newline pointer
		jsr	print_string		; prints newline
		ldy	#strace_instr		; loads steptrace instructions pointer
		jsr 	print_string		; prints instructions

		puly				; restore buffer pointer
		jsr	go_addr_sub		; let the go subroutine take over to start the program

hwbp_enable_sub:
		pshd				; saves state of D
		ldd	#bp_enable		; loads D with the bits to set for breakpoint control
		std	BRKCT0			; stores them enabling dual address swi mode
		puld				; restores state of D
		rts				; returns from subroutine
hwbp_disable_sub:
		pshd				; saves state of D
		clr	BRKCT0			; clears the breakpoint control 1
		clr	BRKCT1			; clears the breakpoint control 2
		puld				; restores state of D
		rts				; returns from subroutine

; input x = address to set breakpoint_0
set_bp_0:
		stx	BRKAH			; stores x in the address breakpoint register
		rts				; returns from subroutine
clr_bp_0:
		clr	BRKAH			; clears the address register high byte
		clr	BRKAL			; clears the address register low byte
		rts				; returns from subroutine
; output x = address in breakpoint_0
get_bp_0:
		pshd				; stores state of d
		ldaa	BRKAH			; loads the upper address byte
		ldab	BRKAL			; loads the lower address byte
		xgdx				; puts D in x
		puld				; restores state of d
		rts				; return from subroutine



; input x = address to set breakpoint_1
set_bp_1:
		stx	BRKDH			; stores x in the data(used as address) breakpoint register
		rts				; returns from subroutine
clr_bp_1:
		clr	BRKDH			; clears the data( used as address ) high byte
		clr	BRKDL			; clears the data( used as address ) low byte
		rts				; returns from subroutine
; output x = address in breakpoint_1
get_bp_1:
		pshd				; stores state of d
		ldaa	BRKDH			; loads the upper data( used as address ) byte
		ldab	BRKDL			; loads the lower data( used as address ) byte
		xgdx				; puts D in x
		puld				; restores state of d
		rts				; returns from subroutine

; called from the swi handler. looks for instructions that change the PC
; RTI, RTS, BSR, JMP, JSR, BRCLR, BRSET, branches, and long branches supported
; only direct and extended addressing modes for the above are supported
; indexed needs to be added
; input y = address of instruction to check for branch, jump, etc
check_PC_mod:
		pshx				; stores all of the state
		pshd
		pshy
		ldd	0,y			; loads two bytes of the instruction pointed to by
						; the address in the y register

		cmpa	#$0b			; checks for RTI
		bne	skip_RTI		; skip if it's not RTI
		ldy	SP_SAVE			; loads user stack pointer
		ldx	16,y			; loads in return address
		jsr	set_bp_1		; sets it in the right breakpoint register
		lbra	end_mod_PC_check	; ends this routine


skip_RTI	cmpa	#$3d			; checks for RTS
		bne	skip_RTS		; skip if it's not RTS
		ldy	SP_SAVE			; loads user stack pointer
		ldx	9,y			; loads in return address
		jsr	set_bp_1		; sets it in the right breakpoint register
		lbra	end_mod_PC_check	; ends this routine


skip_RTS	cmpa	#$07			; checks for BSR
		bne	skip_BSR		; skip if it's not BSR
		iny
		iny				; sets y to the next instruction
		sex	b,x			; sign extends the relative offset to x
		stx	tempw			; stores value of x in a temporary variable
		xgdy				; puts y, the address of next instruction into d
		addd	tempw			; adds the offset to d
		xgdx				; puts the address to branch to in x
		jsr	set_bp_1		; puts it in the right breakpoint register	
		bra	end_mod_PC_check	; ends this routine

skip_BSR	cmpa	#$06			; checks for JMP
		bne 	skip_JMP		; skip if it's not JMP
		ldd	1,y			; loads the effective address
		xgdx				; puts it in x
		jsr	set_bp_1		; puts it in the right breakpoint register	
		bra	end_mod_PC_check	; ends this routine

skip_JMP	cmpa	#$17			; checks for direct JSR
		bne	skip_dJSR		; skip if it's not dJSR
		clra				; clears the first byte in d(opcode)
		xgdx				; puts the address in x
		jsr	set_bp_1		; puts it in the right breakpoint register	
		bra	end_mod_PC_check	; ends this routine

skip_dJSR	cmpa	#$16			; checks for extended JSR
		bne	skip_eJSR		; skip if it's not eJSR
		ldd	1,y			; loads the effective address
		xgdx				; puts the address in x
		jsr	set_bp_1		; puts it in the right breakpoint register	
		bra	end_mod_PC_check	; ends this routine			

skip_eJSR	oraa	#%00000001		; sets the last bit of the byte
		cmpa	#$4f			; looking for immediate BRCLR and BRSET
		bne	skip_iBR		; skip if it's not BRCLR or BRSET
		ldab	3,y			; loads in relative address
		iny
		iny				; sets y to the next instruction
		sex	b,x			; sign extends the relative offset to x
		stx	tempw			; stores value of x in a temporary variable
		xgdy				; puts y, the address of next instruction into d
		addd	tempw			; adds the offset to d
		xgdx				; puts the address to branch to in x
		jsr	set_bp_1		; puts it in the right breakpoint register	
		bra	end_mod_PC_check	; ends this routine
	

skip_iBR	cmpa	#$1e			; looking for direct BRCLR and BRSET
		bne	skip_eBR		; skip if it's not BRCLR or BRSET
		ldab	4,y			; loads in relative address
		iny
		iny				; sets y to the next instruction
		sex	b,x			; sign extends the relative offset to x
		stx	tempw			; stores value of x in a temporary variable
		xgdy				; puts y, the address of next instruction into d
		addd	tempw			; adds the offset to d
		xgdx				; puts the address to branch to in x
		jsr	set_bp_1		; puts it in the right breakpoint register	
		bra	end_mod_PC_check	; ends this routine

						; checks for any branch instruction
skip_eBR	anda	#%11110000		; clears lower nibble
		cmpa	#$20			; checks for branches
		bne	skip_BRANCH		; skip if it's not a branch
		iny
		iny				; sets y to the next instruction
		sex	b,x			; sign extends the relative offset to x
		stx	tempw			; stores value of x in a temporary variable
		xgdy				; puts y, the address of next instruction into d
		addd	tempw			; adds the offset to d
		xgdx				; puts the address to branch to in x
		jsr	set_bp_1		; puts it in the right breakpoint register	
		bra	end_mod_PC_check	; ends this routine

						; check for any long branch instruction
skip_BRANCH	ldd	0,y			; loads two bytes of the instruction pointed to by
						; the address in the y register

		cmpa	#$18			; checks for long branch prefix
		bne	end_mod_PC_check	; nothing found, goes to the end
		andb	#%11110000		; clears lower nibble
		cmpb	#$20			; checks for long branches
		bne	end_mod_PC_check	; nothing found, goes to the end



end_mod_PC_check:
		puly				; restores all of the state
		puld
		pulx
		rts

