

; -----------------= SWI SUBROUTINE! =----------------------
; this is where the SWI interrupt gets processed
; breakpoint stuff here?
; we need to do several things here:
; 1. save user stack and start using the monitor's stack
; 2. replace the SWI at the addr with the code that was 
;    there. This means we need to search the bkpt table
;    for that address
; 3. place an SWI at the next instruction and save its
;    code. 
; 4. jmp to monitor beginning
;
; remember we need to make a state variable and check it
; at the entry to this subroutine.
; There are two states:
; 1. First SWI just happened
;       Need to do the above
; 2. Second SWI just happened
;       put the first SWI back
;       replace this SWI with original code
;
; I was thinking about what happens if a USER puts SWIs 
; manually into their code (this is actully a really good
; debugging idea). My monitor code would confuse it with 
; the first SWI of a breakpoint. However, if, during the
; first SWI handler it doesn't find a breakpoint in the 
; table corresponding to this location, it will now 
; assume its a user-supplied SWI.
; ----------------------------------------------------------
***
;swi_handler: "swi.asm"
;	is not a subroutine, but an interrupt service routine. Happens with swi
;	Reg Input:
;		None
;	Reg Output:
;		none
***

swi_handler:					; copy the SP (user's SP) to the RAM location for it

	sts		SP_save			; save it there

						; change SP to the monitor's SP	
	lds		SP_save_mon		; loads the monitors SP

***** added for hwbp



	ldaa		hw_step_byte		; loads the hw_step_byte
	beq		norm_swi		; if it's zero, then this isn't steptracing so skip ahead
	jsr		reg_view_sub		; prints out the registers
	ldy		SP_save			; load in user stack pointer, so we can eventually get the PC
	jsr		get_bp_0		; loads first hardware breakpoint in X
	cpx		7,y			; compares the first hardware breakpoint with the return address
	beq		bp_found		; if they are equal, it's a hardware breakpoint in the first slot
	jsr		get_bp_1		; loads the second hardware breakpoint in X
	cpx		7,y			; compares the second hardware breakpoint with the return address
	beq		bp_found		; if they are equal, it's a hardware breakpoint in the first slot

end_step:
	clr		hw_step_byte		; clears the step byte so that the steptracing ends
	jsr		hwbp_disable_sub	; disables hardware breakpoint mode
	jsr		clr_bp_0		; clears the first breakpoint
	jsr		clr_bp_1		; clears the second breakpoint
	lbra		norm_swi		; if nothing was found, it's a normal in program swi


						
bp_found:					
	pshx					; X = return address    store X
	jsr		disasm			; X = address of next instruction after disassembly
	puly					; Y = return address
	jsr		set_bp_0		; sets X as the breakpoint for the next instruction
	jsr		clr_bp_1		; in case it was bp_1 that triggered the swi, clear it

	jsr		check_PC_mod		; looks to see if the instruction going to execute is a branch, jump
						; or another kind of instruction that has a different
						; location to go to. this will set bp_1 to this location
						; if the next instruction changes the PC

	pshy					; stores return address
	ldy		#newline		; loads new line pointer
	jsr		print_string		; prints new line

c_waiting:	
	jsr		get_char_wait_noecho	; waits for a character input
	cmpa		#13			; compare with 13, enter key
	beq		end_step		; if it is enter, end steptracing
	cmpa		#' '			; if it is a space, continue on
	bne		c_waiting		; if it's not either space or enter, keep waiting
	puly					; reloads return address

	sts		SP_save_mon		; save the monitor's stack
	lds		SP_save			; SP = [SP_save] (SP gets the user's stack ptr)

	rti					; rti will resume the user's code
						; this is under the assumption that you will be resuming
						; from a software interupt/breakpoint




***** end of added for hwbp
norm_swi:

					
	ldaa		bkpt_state		; check the state variable if its zero, this is the first SWI
	beq		sh_first_swi		; if not, its the second

						; if code is here, its the second SWI 
						; (the one that restores the original)
	ldx		bkpt_addr		; addr of where to put the SWI back
	ldaa		#$3f			; loads the swi instruction
	staa		0,x			; stores it in the address specified by bkpt_addr
	ldx		SP_save			; loads the user stack pointer
	ldd		7,x			; RTN addr in the user stack
	subd		#$01			; subtract 1 so go to the right spot
	std		7,x			; put it back
	xgdx					; X <-> D
	ldaa		bkpt_code		; A get's the breakpoint code
	staa		0,x			; the breakpoint code goes back into the place it should
	clra					; A is cleared
	staa		bkpt_state		; and sets the breakpoint state to 0
	
	lds		SP_save			; restore the users stack
	rti					; go back to user code

sh_first_swi:
	; this is the first SWI so we need to figure out which of the breakpoints
	; it was. the way to do this is by getting the PC off the user's stack
	; and searching for that addr-1 in the bkpt table
	ldx		SP_save			; X=ptr to user's stack
	ldab		#$07
	abx					; the RTN addr is 7th byte on the stack!

*						* why doesn't he do 7, x like he did above?
	ldd		0,x			; RTN addr is 2 bytes on stack
	subd		#$01			; subtract 1. decrements the return address
	pshd					; save it for a bit -- need it again later

						; now search for that addr in D in the bkpt table
	jsr		sh_search_addr		; returns offset into table in A (bkpt number)
	cpx		#$0000			; if this is returned, the addr wasn't found
	beq		sh_user_bkpt		; and its a user SWI

	ldx		#bkpt_tbl_code		; loads the table with what used to be where the swi happened
*						* use tab here
	psha
	pulb					; the offset is put into b
	abx					; addr+offset = location of code
	ldaa		0,x			; get the code
	pulx					; X=loc of SWI in code
	staa		0,x			; save the old code
	


						; now we need to make it such that the return addr on the user's
						; stack goes to addr-1 (currently in X)
	xgdx					; put the address in D
	ldx		SP_save			; load the user stack pointer
	pshb					; saves state of B, which is part of the address
	ldab		#$07			; loads 7
	abx					; adds it to the user stack pointer to get the PC address
	pulb					; restores lower byte of the address
	std		0,x			; put the modified return addr in 



						; now we need to put an SWI at the beginning of the 
						; next instruction after
						; the current one (addr of which is in D)
	xgdx					; move addr into X
	stx		bkpt_addr		; save that addr (to put the first SWI back)
	jsr		disasm			; moves X to beginning of next instr. see "disasm.asm"
	ldaa		0,x			; get code there
	stx		bkpt_addr2		; save the loc of the second swi (for break -)
	staa		bkpt_code		; save it
	ldaa		#$3f			; loads swi instruction
	staa		0,x			; put an SWI there
	staa		bkpt_state		; put anything > 0 there	
	
						; jump to the monitor code
	jmp		begin_1

sh_user_bkpt:
	puld					; we had saved the return address above
	jmp		begin_1			; so jump to the monitor code

***
;sh_search_addr: "swi.asm"
;	Used to search the breakpoint table looking for a matching address
;	Reg Input:
;		D = address to find in the table
;	Reg Output:
;		X = address in breakpoint table
;		X = $0 if not found
;		A = offset from other breakpoint table
***


						; used by the swi handler and in the breakpoint code
						; in: D = addr to find in bkpt table
						; out: X = addr of addr in bkpt table
						; out: A = offset into bkpt table (number of bkpt)
sh_search_addr:
	pshd					; save state of D
	clr		tempw			; used as a counter (just a memory location )
	puld					; restores state of D ( the address to find )
	ldx		#bkpt_table		; loads X with the starting address of the breakpoint table
sh_loop1:
	cpd		0,x			; does D==[X]?
	beq		sh_foundit		; if it is, it has been found
	inx					; else go to the next position
	inx
	inc		tempw			; increment our counter
	psha					; save state of A
	ldaa		#$05			; 5 bkpt entries
	cmpa		tempw			; see if the counter is equal to 5
	beq		sh_done_notfound	; if it is, then the breakpoint wasn't found
	pula					; restore state of A
	bra		sh_loop1
sh_foundit:
	ldaa		tempw			; count of offset into bkpt table where 
						; the addr was found
	rts					; return
sh_done_notfound:
	pula					; restores state of A
	ldx		#$0000			; error code
	rts					; return with error
	