📄 mcfv4e_lo.s
字号:
/*
* File: mcfv4e_lo.s
* Purpose: Lowest level routines for all CF V4e
*
* Notes: Has support for FPU registers
*
*/
/*
* 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
#define __SP_INIT ___SP_INIT
#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_cacr
.global _mcf5xxx_wr_cacr
.global mcf5xxx_wr_asid
.global _mcf5xxx_wr_asid
.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_mmubar
.global _mcf5xxx_wr_mmubar
.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_pc
.global _mcf5xxx_wr_pc
.global mcf5xxx_wr_rombar0
.global _mcf5xxx_wr_rombar0
.global mcf5xxx_wr_rombar1
.global _mcf5xxx_wr_rombar1
.global mcf5xxx_wr_rambar0
.global _mcf5xxx_wr_rambar0
.global mcf5xxx_wr_rambar1
.global _mcf5xxx_wr_rambar1
.global mcf5xxx_wr_mpcr
.global _mcf5xxx_wr_mpcr
.global mcf5xxx_wr_secmbar
.global _mcf5xxx_wr_secmbar
.global mcf5xxx_wr_mbar
.global _mcf5xxx_wr_mbar
/*
* The following define the registers that are
* maintained by the debugger.
*/
#define r_d0 0
#define r_d1 4
#define r_d2 8
#define r_d3 12
#define r_d4 16
#define r_d5 20
#define r_d6 24
#define r_d7 28
#define r_a0 32
#define r_a1 36
#define r_a2 40
#define r_a3 44
#define r_a4 48
#define r_a5 52
#define r_a6 56
#define r_a7 60
#define r_fp0 64
#define r_fp1 72
#define r_fp2 80
#define r_fp3 88
#define r_fp4 96
#define r_fp5 104
#define r_fp6 112
#define r_fp7 120
#define r_fpcr 128
#define r_fpsr 132
#define r_fpiar 136
#define r_pc 140
#define r_sr 144
#define 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:
/* 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 */
/* Restore user SP */
move.l a6,sp
/* Restore user floating point registers */
fmovem r_fp0(a0),fp0-fp7 /* 0xF228D0FF0040 */
fmove.l r_fpcr(a0),FPCR /* 0xF22890000080 */
fmove.l r_fpsr(a0),FPSR /* 0xF22888000084 */
fmove.l r_fpiar(a0),FPIAR /* 0xF22884000088 */
/* Restore user data and address registers */
movem.l (a0),d0-d7/a0-a6
/* 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) */
/* Save off floating point registers */
fmovem fp0-fp7,r_fp0(a0) /* 0xF228F0FF0040 */
fmove.l FPCR,r_fpcr(a0) /* 0xF228B0000080 */
fmove.l FPSR,r_fpsr(a0) /* 0xF228A8000084 */
fmove.l FPIAR,r_fpiar(a0) /* 0xF228A4000088 */
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_sr:
_mcf5xxx_wr_sr:
move.l 4(SP),D0
move.w D0,SR
rts
mcf5xxx_wr_cacr:
_mcf5xxx_wr_cacr:
move.l 4(SP),D0
.long 0x4e7b0002 /* movec d0,cacr */
nop
rts
mcf5xxx_wr_asid:
_mcf5xxx_wr_asid:
move.l 4(SP),D0
.long 0x4e7b0003 /* movec d0,asid */
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_mmubar:
_mcf5xxx_wr_mmubar:
move.l 4(SP),D0
.long 0x4e7b0008 /* movec d0,MBAR */
nop
rts
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_pc:
_mcf5xxx_wr_pc:
move.l 4(SP),D0
.long 0x4e7b080F /* movec d0,PC */
nop
rts
mcf5xxx_wr_rombar0:
_mcf5xxx_wr_rombar0:
move.l 4(SP),D0
.long 0x4e7b0C00 /* movec d0,ROMBAR0 */
nop
rts
mcf5xxx_wr_rombar1:
_mcf5xxx_wr_rombar1:
move.l 4(SP),D0
.long 0x4e7b0C01 /* movec d0,ROMBAR1 */
nop
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_mpcr:
_mcf5xxx_wr_mpcr:
move.l 4(SP),D0
.long 0x4e7b0C0C /* movec d0,MPCR */
nop
rts
mcf5xxx_wr_secmbar:
_mcf5xxx_wr_secmbar:
move.l 4(SP),D0
.long 0x4e7b0C0E /* movec d0,MBAR1 */
nop
rts
mcf5xxx_wr_mbar:
_mcf5xxx_wr_mbar:
move.l 4(SP),D0
.long 0x4e7b0C0F /* movec d0,MBAR0 */
nop
rts
/********************************************************************/
.end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -