⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mcf5xxx_lo.s

📁 motorola自己开发的针对coldfire 5272的Dbug bootloader程序
💻 S
字号:
/*
 * File:	mcf5xxx_lo.s
 * Purpose:	Lowest level routines for all MCF5xxx
 *
 * Notes:	This file assembles with both Diab and GNU tools
 *
 */

/*
 * Only need underscore for C functions. The assembly functions will
 * provide both style names.
 */
#ifdef _UNDERSCORE_
#define context					_context
#define cpu_handler				_cpu_handler
#define isr_execute_handler		_isr_execute_handler
#define mainloop				_mainloop
#endif

	.extern ___SP_INIT
	.extern	context
	.extern mainloop
	.extern	cpu_handler
	.extern	isr_execute_handler

	.extern	cpu_cache_flush
	.extern	_cpu_cache_flush
	
	.extern	VECTOR_TABLE
	.extern	_VECTOR_TABLE

	.global	asm_exception_handler
	.global	_asm_exception_handler
	.global	asm_switch_context
	.global	_asm_switch_context
	.global	asm_set_ipl
	.global	_asm_set_ipl
	.global	asm_sc_exit_to_dbug
	.global	_asm_sc_exit_to_dbug
	.global	asm_isr_handler
	.global	_asm_isr_handler
	.global	mcf5xxx_wr_vbr
	.global	_mcf5xxx_wr_vbr
	.global	mcf5xxx_wr_cacr
	.global	_mcf5xxx_wr_cacr
	.global	mcf5xxx_wr_acr0
	.global	_mcf5xxx_wr_acr0
	.global	mcf5xxx_wr_acr1
	.global	_mcf5xxx_wr_acr1
	.global	mcf5xxx_wr_acr2
	.global	_mcf5xxx_wr_acr2
	.global	mcf5xxx_wr_acr3
	.global	_mcf5xxx_wr_acr3
	.global	mcf5xxx_wr_other_sp
	.global	_mcf5xxx_wr_other_sp
	.global	mcf5xxx_wr_other_a7
	.global	_mcf5xxx_wr_other_a7
	.global	mcf5xxx_wr_vbr
	.global	_mcf5xxx_wr_vbr
	.global	mcf5xxx_wr_macsr
	.global	_mcf5xxx_wr_macsr
	.global	mcf5xxx_wr_mask
	.global	_mcf5xxx_wr_mask
	.global	mcf5xxx_wr_acc0
	.global	_mcf5xxx_wr_acc0
	.global	mcf5xxx_wr_accext01
	.global	_mcf5xxx_wr_accext01
	.global	mcf5xxx_wr_accext23
	.global	_mcf5xxx_wr_accext23
	.global	mcf5xxx_wr_acc1
	.global	_mcf5xxx_wr_acc1
	.global	mcf5xxx_wr_acc2
	.global	_mcf5xxx_wr_acc2
	.global	mcf5xxx_wr_acc3
	.global	_mcf5xxx_wr_acc3
	.global	mcf5xxx_wr_sr
	.global _mcf5xxx_wr_sr
	.global	mcf5xxx_wr_rambar0
	.global	_mcf5xxx_wr_rambar0
	.global	mcf5xxx_wr_rambar1
	.global	_mcf5xxx_wr_rambar1
	.global	mcf5xxx_wr_mbar
	.global	_mcf5xxx_wr_mbar
	.global	mcf5xxx_wr_mbar0
	.global	_mcf5xxx_wr_mbar0
	.global	mcf5xxx_wr_mbar1
	.global	_mcf5xxx_wr_mbar1
	.global	mcf5xxx_wr_mpcr
	.global	_mcf5xxx_wr_mpcr


/*
 * The following defines the registers that are
 * maintained by the debugger.  
 */

	.equ	r_d0,0
	.equ	r_d1,4
	.equ	r_d2,8
	.equ	r_d3,12
	.equ	r_d4,16
	.equ	r_d5,20
	.equ	r_d6,24
	.equ	r_d7,28
	.equ	r_a0,32
	.equ	r_a1,36
	.equ	r_a2,40
	.equ	r_a3,44
	.equ	r_a4,48
	.equ	r_a5,52
	.equ	r_a6,56
	.equ	r_a7,60
	.equ	r_pc,64
	.equ	r_sr,68
		
	.equ	r_sp,r_a7

	.text

/*
 * This routine is responsible for restoring a user
 * register set and executing it.
 * Since all registers about to be restored, use any
 * register.
 *
 * call from C:  asm_switch_context(REGISTERS *context);
 */
asm_switch_context:
_asm_switch_context:

	move.l		4(sp),a0		/* point to cpu data structure */

	/* ColdFire 5xxx requires stack frames be 0 modula 4 */

	/* calculate format field encoding */
	move.l	r_sp(a0),d6			/* sp for stack adjustment	*/
	move.l	d6,d7				/* sp for comparisons	*/
	andi.l	#0x00000003,d7		/* last two bits of a7	*/
	beq.s	ff0100				/* format field 0100	*/
	cmpi.l	#1,d7
	beq.s	ff0101				/* format field 0101	*/
	cmpi.l	#2,d7
	beq.s	ff0110				/* format field 0110	*/
	/* must be format field 0111 */

ff0111:
	subq.l	#3,d6			/* adjust sp 3 bytes to align	*/
	move.l	#0x70000000,d7	/* encode format 0111	*/
	bra.s	write_frame
ff0110:
	subq.l	#2,d6			/* adjust sp 2 bytes to align	*/
	move.l	#0x60000000,d7	/* encode format 0110	*/
	bra.s	write_frame
ff0101:
	subq.l	#1,d6			/* adjust sp 1 bytes to align	*/
	move.l	#0x50000000,d7	/* encode format 0101	*/
	bra.s	write_frame
ff0100:
	/* no stack adjustment necessary */
	move.l	#0x40000000,d7	/* encode format 0100	*/
		

write_frame:
/*
	move.l	d6,sp			; sp (change sp to user stack)
	move.l	r_pc(a0),-(sp)	; pc
	move.w	r_sr(a0),d7		; sr (format already in d7)
	move.l	d7,-(sp)
*/

	/* Build stack frame before switching stacks */
    move.l  d6,a6
    move.l  r_pc(a0),-(a6)  /* sp							*/
    move.w  r_sr(a0),d7     /* sr (format already in d7)	*/
    move.l  d7,-(a6)
    nop                     /* force pending writes			*/
    move.l  a6,sp

	/* the PC and SR are in the stack frame */
	movem.l	(a0),d0-d7/a0-a6	/* remaining registers */
/*
 or could use ...
   move.l  r_d7(a0),d7
   move.l  r_d6(a0),d6
   move.l  r_d5(a0),d5
   move.l  r_d4(a0),d4
   move.l  r_d3(a0),d3
   move.l  r_d2(a0),d2
   move.l  r_d1(a0),d1
   move.l  r_d0(a0),d0
   move.l  r_a6(a0),a6
   move.l  r_a5(a0),a5
   move.l  r_a4(a0),a4
   move.l  r_a3(a0),a3
   move.l  r_a2(a0),a2
   move.l  r_a1(a0),a1
   move.l  r_a0(a0),a0
*/

	/* here we go! */
	nop
	rte


/*
 * This routine is the lowest-level exception handler for ColdFire.
 * This routine switches SP to a known-good RAM location, and then
 * saves the registers.  This routine should work even if the user
 * code has a bad stack pointer.
 */
asm_exception_handler:
_asm_exception_handler:

	move.w	#0x2700,sr	/* if doing interrupt i/o, then comment out */

	/* Change to dBUG stack space */
	move.l	sp,___SP_INIT
	move.l	#___SP_INIT,sp

	move.l	a0,-(sp)
	lea		context,a0

	movem.l	d0-d7/a0-a7,(a0)	/* d0-d7/a0-a7 (a0/a7 are bad)	 */
	move.l	(sp)+,r_a0(a0)		/* a0	 */
	move.l	(sp),a1
	move.l	a1,r_sp(a0)			/* sp/a7 at end of stack frame	 */
	move.l	4(a1),r_pc(a0)		/* pc	 */
	move.w	2(a1),r_sr(a0)		/* sr	 */

	/* Flush caches and disable them. */
	jsr		cpu_cache_flush

/*
 * all regs are saved and correct except SP, but SP taken care of
 * in cpu_handler():  int cpu_handler (STACK_FRAME *framep);
 */
	move.l	a1,-(sp)
	jsr		cpu_handler
	lea		4(sp),sp
	tst.l	d0
	bne.s	backtomonitor

/*
 * restore registers modified:  a0,d0,a1,d1,sp
 * sr in stack frame
 */
	lea		context,a0

/*
 * sp must have been adjusted properly for RTE
 * since cpu_handler() initially knocks off the
 * frame from the user stack. (see ispdelta)
 */
	move.l	r_sp(a0),sp

	move.l	r_d1(a0),d1
	move.l	r_a1(a0),a1
	move.l	r_d0(a0),d0
	move.l	r_a0(a0),a0	/* This one must be done LAST!!! */

	rte

backtomonitor:
	move.w	#0x2700,sr
	jmp	mainloop




/*
 * This routine is called from within/by a user system call to save the
 * context and return to dBUG cleanly.  This routine expects a pointer
 * to the exception stack frame.  This pointer provides three pieces of
 * information.  1) The SP (which points to end of exception stack frame),
 * 2) the PC, and 3) the SR.  All other regs are preserved from their
 * values entering this routine.  This routine must be called via a JSR
 * or BSR instruction.
 *
 * So, stack coming into this routine looks like:
 *
 *                  |       ...        |
 *                  |    Return PC     |
 *                  | Format/Vector/SR | <-- SP after exception
 *                  |       ...        |
 *                  |  Stack Frame Ptr | (The SP after exception)
 *                  |   JSR Return PC  | (not used)
 *                  |                  |
 */
asm_sc_exit_to_dbug:
_asm_sc_exit_to_dbug:
	/* Save off general purpose registers */

		move.w		#0x2700,sr

		move.l		a0,-(sp)
		lea			context,a0
		move.l		d0,r_d0(a0)
		move.l		d1,r_d1(a0)
		move.l		d2,r_d2(a0)
		move.l		d3,r_d3(a0)
		move.l		d4,r_d4(a0)
		move.l		d5,r_d5(a0)
		move.l		d6,r_d6(a0)
		move.l		d7,r_d7(a0)
		move.l		a1,r_a1(a0)
		move.l		a2,r_a2(a0)
		move.l		a3,r_a3(a0)
		move.l		a4,r_a4(a0)
		move.l		a5,r_a5(a0)
		move.l		a6,r_a6(a0)
		move.l		(sp)+,a1
		move.l		a1,r_a0(a0)

	/* Now get info from stack frame pointer */

		move.l		4(sp),a1		/* Stack frame pointer argument	 */
		move.l		a1,r_a7(a0) 	/* SP at end of exception	 */
		move.l		4(a1),r_pc(a0)	/* pc	 */
		move.w		2(a1),r_sr(a0)	/* sr	 */

/*
 * Now that context has been stored off, change to dBUG stack
 * and prepare to enter the debugger again.
 */
		move.l		#___SP_INIT,sp

	/* Flush caches and disable them */
		jsr			cpu_cache_flush
		jmp			mainloop




/*
 * This routines changes the IPL to the value passed into the routine.
 * It also returns the old IPL value back.
 * Calling convention from C:
 *   old_ipl = asm_set_ipl(new_ipl);
 * For the Diab Data C compiler, it passes return value thru D0.
 * Note that only the least significant three bits of the passed
 * value are used.
 */

	.text
asm_set_ipl:
_asm_set_ipl:
	link	a6,#-8
	movem.l	d6-d7,(sp)

		move.w	sr,d7		/* current sr	 */

		move.l	d7,d0		/* prepare return value	 */
		andi.l	#0x0700,d0	/* mask out IPL	 */
		lsr.l	#8,d0		/* IPL	 */

		move.l	8(a6),d6	/* get argument	 */
		andi.l	#0x07,d6		/* least significant three bits	 */
		lsl.l	#8,d6		/* move over to make mask	 */

		andi.l	#0x0000F8FF,d7	/* zero out current IPL	 */
		or.l	d6,d7			/* place new IPL in sr	 */
		move.w	d7,sr

	movem.l	(sp),d6-d7
	lea		8(sp),sp
	unlk	a6
	rts

/*
 * This is the low-level Interrupt Service Routine code for ISRs
 * that are registered within the dBUG monitor.
 */

asm_isr_handler:
_asm_isr_handler:
	link		a6,#-16
	movem.l		d0-d1/a0-a1,(sp)

	move.w		4(a6),d0
	lsr.l		#2,d0
	andi.l		#0x0000FF,d0
	move.l		d0,-(sp)
	jsr			isr_execute_handler
	lea			4(sp),sp
	cmpi.l		#1,d0
	beq			handled

nothandled:
	movem.l		(sp),d0-d1/a0-a1
	unlk		a6
	jmp			asm_exception_handler

handled:
	movem.l		(sp),d0-d1/a0-a1
	unlk		a6
	rte

/*
 * These routines write to the special purpose registers in the ColdFire
 * core.  Since these registers are write-only in the supervisor model,
 * no corresponding read routines exist.
 */
 
mcf5xxx_wr_cacr:
_mcf5xxx_wr_cacr:
    move.l  4(sp),d0
    .long   0x4e7b0002      /* movec d0,cacr	 */
    nop
    rts

mcf5xxx_wr_acr0:
_mcf5xxx_wr_acr0:
    move.l  4(sp),d0
    .long   0x4e7b0004      /* movec d0,ACR0	*/
    nop
    rts

mcf5xxx_wr_acr1:
_mcf5xxx_wr_acr1:
    move.l	4(sp),d0
    .long   0x4e7b0005      /* movec d0,ACR1	*/
    nop
    rts

mcf5xxx_wr_acr2:
_mcf5xxx_wr_acr2:
    move.l  4(sp),d0
    .long   0x4e7b0006      /* movec d0,ACR2	*/
    nop
    rts

mcf5xxx_wr_acr3:
_mcf5xxx_wr_acr3:
    move.l  4(sp),d0
    .long   0x4e7b0007      /* movec d0,ACR3	*/
    nop
    rts

mcf5xxx_wr_other_sp:
_mcf5xxx_wr_other_sp:
mcf5xxx_wr_other_a7:
_mcf5xxx_wr_other_a7:
	move.l	4(sp),d0
	.long	0x4e7b0800		/* movec d0,OTHER_A7 */
	nop
	rts
	
mcf5xxx_wr_vbr:
_mcf5xxx_wr_vbr:
	move.l	4(sp),d0
	.long	0x4e7b0801		/* movec d0,VBR	*/
	nop
	rts

mcf5xxx_wr_macsr:
_mcf5xxx_wr_macsr:
    move.l  4(sp),d0
    .long   0x4e7b0804      /* movec d0,MACSR	*/
    nop
    rts

mcf5xxx_wr_mask:
_mcf5xxx_wr_mask:
    move.l  4(sp),d0
    .long   0x4e7b0805      /* movec d0,MASK	*/
    nop
    rts

mcf5xxx_wr_acc0:
_mcf5xxx_wr_acc0:
    move.l  4(sp),d0
    .long   0x4e7b0806      /* movec d0,ACC0	*/
    nop
    rts

mcf5xxx_wr_accext01:
_mcf5xxx_wr_accext01:
    move.l  4(sp),d0
    .long   0x4e7b0807      /* movec d0,ACCEXT01	*/
    nop
    rts

mcf5xxx_wr_accext23:
_mcf5xxx_wr_accext23:
    move.l  4(sp),d0
    .long   0x4e7b0808      /* movec d0,ACCEXT23	*/
    nop
    rts

mcf5xxx_wr_acc1:
_mcf5xxx_wr_acc1:
    move.l  4(sp),d0
    .long   0x4e7b0809      /* movec d0,ACC1	*/
    nop
    rts

mcf5xxx_wr_acc2:
_mcf5xxx_wr_acc2:
    move.l  4(sp),d0
    .long   0x4e7b080A      /* movec d0,ACC2	*/
    nop
    rts

mcf5xxx_wr_acc3:
_mcf5xxx_wr_acc3:
    move.l  4(sp),d0
    .long   0x4e7b080B      /* movec d0,ACC3	*/
    nop
    rts

mcf5xxx_wr_sr:
_mcf5xxx_wr_sr:
	move.l	4(sp),d0
	move.w	d0,SR
	rts
	
mcf5xxx_wr_rambar0:
_mcf5xxx_wr_rambar0:
    move.l  4(sp),d0
    .long   0x4e7b0C04      /* movec d0,RAMBAR0	*/
    nop
    rts

mcf5xxx_wr_rambar1:
_mcf5xxx_wr_rambar1:
    move.l  4(sp),d0
    .long   0x4e7b0C05      /* movec d0,RAMBAR1	*/
    nop
    rts

mcf5xxx_wr_mbar:
_mcf5xxx_wr_mbar:
mcf5xxx_wr_mbar0:
_mcf5xxx_wr_mbar0:
    move.l  4(sp),d0
    .long   0x4e7b0C0F      /* movec d0,MBAR0	*/
    nop
    rts

mcf5xxx_wr_mbar1:
_mcf5xxx_wr_mbar1:
    move.l  4(sp),d0
    .long   0x4e7b0C0E      /* movec d0,MBAR1	*/
    nop
    rts

mcf5xxx_wr_mpcr:
_mcf5xxx_wr_mpcr:
	move.l	4(sp),d0
    .long	0x4e7b0C0C      /* movec d0,MPCR	*/
    nop
    rts

done:
	rts

	.end

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -