/*  Debug the CT60
 * 
 * Didier Mequignon, 2003-2006, e-mail: aniplay@wanadoo.fr
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
	.chip 68040
	.globl	exception
	
#ifdef COLDFIRE
	.globl	null
	
#include "fire.h"
#endif

#include "vars.h"

#define DEBUG

#ifdef DEBUG
	.global display_string,hex_long,hex_word,hex_byte,display_char,wait_key,_debug
#endif

	.text
	
#ifdef COLDFIRE

null:
	clr.l 0x380        // not valid
	move.l SP,0x3C0
	move.l A6,0x3BC
	lea 0x384,A6
	movem.l D0-D7/A0-A5,(A6)
	clr.l 0x3C8        // USP
	moveq #-1,D1
#endif

exception:

	clr.l memvalid
	lea.l mess1(PC),A0
	bsr display_string
#ifdef COLDFIRE
	ext.l D1
	addq.l #1,D1
	move.l D1,D7       // vector number
#else
	addq.w #1,D1
	move.w D1,D7       // vector number
#endif
	moveq #0,D0
	move.w D7,D0
#ifdef COLDFIRE
	.chip 68060
	divu #10,D0
	.chip 5200
	move.l D0,D1
	and.l #7,D0
	beq.s .ex1
	or.l #0x30,D0
	bsr display_char
.ex1:
	swap D1
	move.w D1,D0
	or.l #0x30,D0
#else
	divu #10,D0
	and.w #7,D0
	beq.s .ex1
	or.w #0x30,D0
	bsr display_char
.ex1:
	swap d0
	or.w #0x30,D0
#endif
	bsr display_char
	moveq #0x3A,D0
	bsr display_char
	moveq #0x20,D0
	bsr display_char
	lea.l tab_mess_exc(PC),A0
	move.w D7,D0
	bsr display_tab
	moveq #13,D0
	bsr display_char
	moveq #10,D0
	bsr display_char
#ifdef COLDFIRE
	tst.w D7
	beq .ex0
#endif
	lea.l mess2(PC),A0 // SR
	bsr display_string
#ifdef COLDFIRE
	move.w save_sr,D0  // SR
#else
	move.l 0x3C0,A0    //SSP
	move.w (A0),D0
#endif
	bsr hex_word       // SR
	lea.l mess3(PC),A0
	bsr display_string
#ifdef COLDFIRE
	move.w save_sr,D2  // SR
	and.l #0xB71F,D2
#else
	move.l 0x3C0,A0    //SSP
	move.w (A0),D2     // SR
	and.w #0xB71F,D2
#endif
	lea.l tab_status(PC),A1
	moveq #15,D1
.ex5:
		btst.l D1,D2
		beq.s .ex6
		moveq #0,D0
		move.b (A1,D1),D0
		move.w D0,D3
#ifdef COLDFIRE
		and.l #0xF8,D3
		cmp.l #0x30,D3
#else
		and.w #0xF8,D3
		cmp.w #0x30,D3
#endif
		bne.s .ex4
		move.w D0,-(SP)
		moveq #0x49,D0 // I
		bsr display_char
		move.w (SP)+,D0
.ex4:
		bsr display_char
		moveq #0x20,D0
		bsr display_char
.ex6:
#ifdef COLDFIRE
	subq.l #1,D1
	bpl.s .ex5
.ex0:
#else
	dbf D1,.ex5
#endif
	lea.l mess4(PC),A0 // PC
	bsr display_string
#ifdef COLDFIRE
	move.l save_pc,D0  // PC
#else
	move.l 0x3C0,A0    // SSP
	move.l 2(A0),D0    // PC
#endif
	bsr hex_long
	lea.l mess10(PC),A0 // Basepage
	bsr display_string
	move.l 0x6EE4,D0
	bsr hex_long
#ifdef COLDFIRE
	tst.w D7
	beq .ex2
#endif
	lea.l mess5(PC),A0 // CACR
	bsr display_string  
#ifdef COLDFIRE
	.chip 68060
	movec.l CACR,D0    // from value stored in the CF68KLIB
	.chip 5200
	bsr hex_long
	cmp.l #2,D7
	bne.s .ex2
	lea.l mess6(PC),A0 // address fault
	bsr display_string
	move.l address_fault,D0 // from value stored in the CF68KLIB
	bsr hex_long
#else /* ATARI - CT60 */
	movec.l CACR,D0
	bsr hex_long
	cmp.w #2,D7
	beq.s .ex3         // Acces Fault
	cmp.w #3,D7
	beq.s .ex3         // Adress Error
	cmp.w #5,D7
	beq.s .ex3         // Zero Divide
	cmp.w #9,D7
	bne .ex2           // <> Trace
.ex3:
	lea.l mess6(PC),A0 // address fault
	bsr display_string
	move.l 0x3C0,A0    // SSP
	move.l 8(A0),D0    // address fault
	bsr hex_long
	cmp.w #2,D7
	bne .ex2           // <> Acces Fault
	lea.l mess7(PC),A0 // FSLW
	bsr display_string
	move.l 0x3C0,A0    // SSP
	move.l 12(A0),D0   // FSLW
	bsr hex_long
	lea.l mess3(PC),A0
	bsr display_string
	moveq #13,D0
	bsr display_char
	moveq #10,D0
	bsr display_char
	move.l 0x3C0,A0  // SSP
	move.l 12(A0),D2 // FSLW
	and.l #0x0BFFFFFD,D2
	lea.l tab_fslw1(PC),A1
	lea.l tab_fslw2(PC),A2
	lea.l tab_fslw3(PC),A3
	moveq #31,D1
	moveq #0,D3
.ex13:
		btst.l D1,D2
		beq.s .ex14
		moveq #0,D0
		move.b (A1,D3),D0
		bsr display_char
		moveq #0,D0
		move.b (A2,D3),D0
		cmp.b #0x20,D0
		beq.s .ex12
		bsr display_char
		moveq #0,D0
		move.b (A3,D3),D0
		cmp.b #0x20,D0
		beq.s .ex12
		bsr display_char
.ex12:
		moveq #0x20,D0
		bsr display_char
.ex14:
		addq.w #1,D3
	dbf D1,.ex13
#endif /* COLDFIRE */
.ex2:
	lea.l mess8(PC),A0 // SSP
	bsr display_string
	move.l 0x3C0,D0    // SSP
	bsr hex_long
	lea.l mess9(PC),A0 // USP
	bsr display_string
	move.l 0x3C8,D0    // USP
	bsr hex_long
	lea.l 0x384,A1     // registers
	lea.l 32(A1),A2
	moveq #7,D1
.ex8:
		moveq #13,D0
		bsr display_char
		moveq #10,D0
		bsr display_char
		moveq #0x44,D0
		bsr display_char
		moveq #7,D0
#ifdef COLDFIRE
		sub.l D1,D0
		or.l #0x30,D0
#else
		sub.w D1,D0
		or.w #0x30,D0
#endif
		move.w D0,-(SP)
		bsr display_nb
		move.l (A1),D0
		bsr hex_long // data registers
		moveq #0x20,D0
		bsr display_char
		tst.w D1
		beq.s .ex9
		moveq #0x41,D0
		bsr display_char
		move.w (SP),D0
		bsr display_nb
		move.l (A2),D0
		bsr hex_long // address registers
		moveq #0x20,D0
		bsr display_char
.ex9:		
		addq.l #2,SP
		addq.l #4,A1
		addq.l #4,A2
#ifdef COLDFIRE
	subq.l #1,D1
	bpl.s .ex8
#else
	dbf D1,.ex8
#endif
	moveq #13,D0
	bsr display_char
.loop_wait_key:
#ifdef COLDFIRE
#ifdef DEBUG
		move.w #1,-(SP)          // AUX
#else
		move.w #2,-(SP)          // CON
#endif
#else
		move.w #2,-(SP)          // CON
#endif
		move.w #2,-(SP)          // Bconin
		trap #13
		addq.l #4,SP
		ext.l D0
		move.l D0,-(SP)
		move.l #0x5F504349,D0 
		lea 0xED0000,A0          // 128 KB
		cmp.l (A0),D0            // _PCI
		beq.s .pci_drivers
		lea 0xEC0000,A0          // 192 KB
		cmp.l (A0),D0            // _PCI
		beq.s .pci_drivers
		lea 0xEB0000,A0          // 256 KB
		cmp.l (A0),D0            // _PCI
		beq.s .pci_drivers
		lea 0xEA0000,A0          // 320 KB
		cmp.l (A0),D0            // _PCI
		bne.s .no_pci_drivers
.pci_drivers:
		jsr 40(A0)               // drivers PCI in flash, add dbug (68k disassembler)
		move.l D0,(SP)
		bne .no_pci_drivers
		addq.l #4,SP
		bra.s .loop_wait_key
.no_pci_drivers:
		move.l (SP)+,D0
#ifdef COLDFIRE
		and.l #0xFF,D0
		cmp.l #0x6D,D0     // m
#else
		cmp.b #0x6D,D0     // m
#endif
		beq.s .memory_dump
#ifdef COLDFIRE
		cmp.l #0x70,D0     // p
#else
		cmp.b #0x70,D0     // p
#endif
		beq.s .patch_memory
#ifdef DEBUG
#ifdef COLDFIRE
		cmp.l #0x20,D0
#else
		cmp.b #0x20,D0
#endif	
		bne .loop_wait_key
		lea mess14(PC),A0
		bsr display_string
#endif
		rts
.memory_dump:
		lea mess11(PC),A0  // memory dump
		bsr display_string
		bsr get_hex_value	
		move.l D0,A0
		bsr dump
		bra .loop_wait_key
.patch_memory:
		lea mess12(PC),A0  // patch memory
		bsr display_string
		bsr get_hex_value
		move.l D0,A1
		lea mess13(PC),A0  // value
		bsr display_string		
		bsr get_hex_value
		cmp.l #0x100,D0
		bcc.s .word_value
		move.b D0,(A1)
		lea crlf(PC),A0
		bsr display_string
		move.l A1,D0
		bsr hex_long
		moveq #0x20,D0
		bsr display_char
		move.b (A1),D0
		bsr hex_byte
		bra .loop_wait_key
.word_value:
		cmp.l #0x10000,D0
		bcc.s .long_value
		move.w D0,(A1)
		lea crlf(PC),A0
		bsr display_string
		move.l A1,D0
		bsr hex_long
		moveq #0x20,D0
		bsr display_char
		move.w (A1),D0
		bsr hex_word	
		bra .loop_wait_key
.long_value:
		move.l D0,(A1)
		lea crlf(PC),A0
		bsr display_string
		move.l A1,D0
		bsr hex_long
		moveq #0x20,D0
		bsr display_char
		move.l (A1),D0
		bsr hex_long
	bra .loop_wait_key
	
display_nb:

	bsr display_char
	moveq #0x3A,D0
	bsr display_char
	moveq #0x24,D0
	bsr display_char
	rts
	
display_tab:

#ifdef COLDFIRE
	move.l D1,-(SP)
#endif
	move.w D0,-(SP)
	moveq #0,D0
.dt1:
#ifdef COLDFIRE
		move.b (A0),D1
		extb.l D1
		cmp.l #-1,D1
		beq.s .dt3
		moveq #0,D1
		move.w (SP),D1
		cmp.l D1,D0
#else
		cmp.b #-1,(A0)
		beq.s .dt3
		cmp.w (SP),D0
#endif
		beq.s .dt4
.dt2:
		tst.b (A0)+
		bne.s .dt2
#ifdef COLDFIRE
		addq.l #1,D0
#else
		addq.w #1,D0
#endif
	bra.s .dt1
.dt4:
	bsr display_string
.dt3:

	addq.l #2,SP
#ifdef COLDFIRE
	move.l (SP)+,D1
#endif
	rts
		
hex_long:
	move.l D0,-(SP)
	swap D0
	bsr.s hex_word
	move.l (SP)+,D0
hex_word:
	move.w D0,-(SP)
#ifdef COLDFIRE
	lsr.l #8,D0          
	bsr.s hex_byte     
	move.w (SP)+,D0
hex_byte:
	move.w D0,-(SP)
	lsr.l #4,D0
	bsr.s hex_char      
	move.w (SP)+,D0      
hex_char:
	and.l #0xF,D0      
	or.l #0x30,D0      
	cmp.l #0x3A,D0     
	bcs.s display_char  
	addq.l #7,D0
	    
display_char:
	and.l #0xFF,D0
#ifdef DEBUG /* warning !!! If serial mouse */
	move.l D1,-(SP)
.wait_uart:
	move.b MCF_UART_USR0,D1
	and.l  #MCF_UART_USR_TXRDY,D1
	beq.s .wait_uart
	move.b D0,MCF_UART_UTB0 // send the character
	move.l (SP)+,D1
#else
	lea -24(SP),SP     
	movem.l D0-D2/A0-A2,(SP)
	move.w D0,-(sp)
	move.w #2,-(SP)
	move.w #3,-(SP)       // Bconout
	trap #13
	addq.l #6,SP
	movem.l (SP),D0-D2/A0-A2
	lea 24(SP),SP
#endif /* DEBUG */
	rts
#else  /* ATARI */
	lsr.w #8,D0          
	bsr.s hex_byte     
	move.w (SP)+,D0
hex_byte:
	move.w D0,-(SP)
	lsr.b #4,D0        
	bsr.s hex_char      
	move.w (SP)+,D0      
hex_char:
	and.b #0xF,D0      
	or.b #0x30,D0      
	cmp.b #0x3A,D0     
	bcs.s display_char  
	addq.b #7,D0   
	    
display_char:
	and.w #0xFF,D0  
	movem.l D0-D2/A0-A2,-(SP)
	move.w D0,-(sp)
	move.w #2,-(SP)
	move.w #3,-(SP)       // Bconout
	trap #13
	addq.l #6,SP
	movem.l (SP)+,D0-D2/A0-A2
	rts
#endif /* COLDFIRE */
	
display_string:

#ifdef COLDFIRE
	move.l D0,-(SP)
	move.l A0,-(SP)
#else
	movem.l D0/A0,-(SP)
#endif
.os2:
	move.b (A0)+,D0
	beq.s .os1
	bsr display_char
	bra.s .os2
.os1:
#ifdef COLDFIRE
	move.l (SP)+,A0
	move.l (SP)+,D0
#else
	movem.l (SP)+,D0/A0
#endif
	rts
	
get_hex_value:

#ifdef COLDFIRE
	lea -56(SP),SP
	movem.l D1-A5,(SP)
	link A6,#-8
	moveq #0,D7
.loop_get_value:
#ifdef DEBUG
		move.w #1,-(SP)          // AUX
#else
		move.w #2,-(SP)          // CON
#endif
		move.w #2,-(SP)          // Bconin
		trap #13
		addq.l #4,SP
		and.l #0xFF,D0
		cmp.l #13,D0
		beq.s .conv_get_value
		cmp.l #8,D0
		bne.s .not_backspace
		tst.w D7
		ble.s .loop_get_value
		bsr display_char
		subq.l #1,D7
		bra.s .loop_get_value
.not_backspace:
		cmp.l #0x30,D0
		bcs.s .loop_get_value
		cmp.l #0x39,D0
		bls.s .number_value
		cmp.l #0x41,D0
		bcs.s .loop_get_value
		cmp.l #0x46,D0
		bls.s .letter_value
		cmp.l #0x61,D0
		bcs.s .loop_get_value
		cmp.l #0x66,D0
		bhi.s .loop_get_value
.letter_value:
		bsr display_char
		and.l #0x0F,D0
		add.l #9,D0
		bra.s .store_value		
.number_value:
		bsr display_char
		and.l #0x0F,D0
.store_value:
		move.b D0,-8(A6,D7)
		addq.l #1,D7
	cmp.l #8,D7
	bcs .loop_get_value
.conv_get_value:
	moveq #0,D0
	subq.l #1,D7
	bmi.s .end_get_value
	moveq #0,D6
.loop_value:
		asl.l #4,D0
		moveq #0,D1
		move.b -8(A6,D6),D1 
		or.l D1,D0
		addq.l #1,D6
	subq.l #1,D7
	bpl.s  .loop_value		
.end_get_value:	
	tst.l D0
	unlk A6
	movem.l (SP),D1-A5
	lea 56(SP),SP
#else /* ATARI */
	movem.l D1-A5,-(SP)
	link A6,#-8
	moveq #0,D7
.loop_get_value:
		move.w #2,-(SP)          // CON
		move.w #2,-(SP)          // Bconin
		trap #13
		addq.l #4,SP
		cmp.b #13,D0
		beq.s .conv_get_value
		cmp.b #8,D0
		bne.s .not_backspace
		tst.w D7
		ble.s .loop_get_value
		bsr display_char
		subq.w #1,D7
		bra.s .loop_get_value
.not_backspace:
		cmp.b #0x30,D0
		bcs.s .loop_get_value
		cmp.b #0x39,D0
		bls.s .number_value
		cmp.b #0x41,D0
		bcs.s .loop_get_value
		cmp.b #0x46,D0
		bls.s .letter_value
		cmp.b #0x61,D0
		bcs.s .loop_get_value
		cmp.b #0x66,D0
		bhi.s .loop_get_value
.letter_value:
		bsr display_char
		and.b #0x0F,D0
		add.b #9,D0
		bra.s .store_value		
.number_value:
		bsr display_char
		and.b #0x0F,D0
.store_value:
		move.b D0,-8(A6,D7)
		addq.w #1,D7
	cmp.w #8,D7
	bcs.s .loop_get_value
.conv_get_value:
	moveq #0,D0
	subq.w #1,D7
	bmi.s .end_get_value
	moveq #0,D6
.loop_value:
		asl.l #4,D0
		or.b -8(A6,D6),D0
		addq.w #1,D6
	dbf D7,.loop_value		
.end_get_value:	
	tst.l D0
	unlk A6
	movem.l (SP)+,D1-A5
#endif /* COLDFIRE */
	rts
	
dump:

#ifdef COLDFIRE
	lea -20(SP),SP
	movem.l D0-D2/A0-A1,(SP)
#else
	movem.l D0-D2/A0-A1,-(SP)
#endif
	move.l A0,A1
	moveq #3,D1
.loop_dump1:
		lea crlf(PC),A0
		bsr display_string
		move.l A1,D0
		bsr hex_long
		moveq #0x20,D0
		bsr display_char		
		moveq #15,D2
.loop_dump2:
			move.b (A1)+,D0
			bsr hex_byte
			moveq #0x20,D0
			bsr display_char
#ifdef COLDFIRE
		subq.l #1,D2
		bpl.s .loop_dump2
#else
		dbf D2,.loop_dump2
#endif
		lea -16(A1),A1
		moveq #15,D2
.loop_dump3:
			move.b (A1)+,D0
#ifdef COLDFIRE
			and.l #0xFF,D0
			cmp.l #0x20,D0
			bcs.s .dump_bad_char
			cmp.l #0x7F,D0
#else
			cmp.b #0x20,D0
			bcs.s .dump_bad_char
			cmp.b #0x7F,D0
#endif
			bcs.s .dump_ok
.dump_bad_char:
			moveq #0x2E,D0
.dump_ok:
			bsr display_char
#ifdef COLDFIRE
		subq.l #1,D2
		bpl.s .loop_dump3
	subq.l #1,D1
	bpl.s .loop_dump1
	movem.l (SP),D0-D2/A0-A1
	lea 20(SP),SP
#else
		dbf D2,.loop_dump3
	dbf D1,.loop_dump1
	movem.l (SP)+,D0-D2/A0-A1
#endif
	rts
	
crlf:	.byte 13,10,0
mess1:	.byte 13,10
	.asciz "EXCEPTION PROCESSING "
mess2:	.byte 13,10
	.asciz "Status Register (SR): $"
mess3:	.asciz ", bits to 1: "
mess4:	.byte 13,10
	.asciz "Program Counter (PC): $"
mess5:	.byte 13,10
	.asciz "Cache Register (CACR): $"
mess6:	.byte 13,10
	.asciz "Address Fault: $"	
mess7:	.byte 13,10
	.asciz "Fault Status Word (FSLW): "
mess8:	.byte 13,10
	.asciz "Supervisor Stack (SSP): $"
mess9:	.byte 13,10
	.asciz "User Stack (USP): $"
mess10:	.byte 13,10
	.asciz "Basepage: $"
mess11:	.byte 13,10	
	.asciz "Memory dump (hex) ? "
mess12:	.byte 13,10	
	.asciz "Patch memory (hex) ? "
mess13:	.byte 13,10	
	.asciz "Value (hex) ? "
mess14:	.byte 13,10	
	.ascii "Pterm"
	.byte 13,10,0
 
tab_mess_exc:
#ifdef COLDFIRE
	.asciz "Null (jump or call)"
#else
	.byte 0
#endif
	.byte 0
	.asciz "Access Fault"
	.asciz "Address Error"
	.asciz "Illegal Instruction"
	.asciz "Integer Zero Divide"
	.byte 0
	.byte 0
	.asciz "Privilege Violation"
	.asciz "Trace"
	.asciz "Line A"
	.asciz "Line F"
	.asciz "Emulator Interrupt"
	.byte 0
	.asciz "Format Error"
	.asciz "Uninitialised Interrupt"
	.byte 0
	.byte 0
	.byte 0
	.byte 0
	.byte 0
	.byte 0
	.byte 0
	.byte 0
	.asciz "Spurious Interrupt"
	.asciz "Interrupt level 1"
	.asciz "Interrupt level 2" 
	.asciz "Interrupt level 3" 
	.asciz "Interrupt level 4"
	.asciz "Interrupt level 5" 
	.asciz "Interrupt level 6"
	.asciz "Interrupt level 7"
	.asciz "Trap #0"
	.asciz "Trap #1"
	.asciz "Trap #2"
	.asciz "Trap #3"
	.asciz "Trap #4"
	.asciz "Trap #5"
	.asciz "Trap #6"
	.asciz "Trap #7"
	.asciz "Trap #8"
	.asciz "Trap #9"
	.asciz "Trap #10"
	.asciz "Trap #11"
	.asciz "Trap #12"
	.asciz "Trap #13"
	.asciz "Trap #14"
	.asciz "Trap #15"
	.byte -1

tab_status:	.ascii "CVZNX   012 MS T"

tab_fslw1:	.ascii "    M LRWSSTTTTTIPSPPIPSWTRWTB S"
tab_fslw2:	.ascii "    A K  ZZTTMMMOBBTTLFPPWEETP S"
tab_fslw3:	.ascii "         1010210 EEAB    E  RE E"
