398 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
			
		
		
	
	
			398 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
| /*
 | |
|  * mvme135-asm.S -- assembler routines for the MVME stub.
 | |
|  *
 | |
|  * This code was pulled out of mvme135-stub.c by Ian Taylor so that I
 | |
|  * could handle different register and label prefixes in a sensible
 | |
|  * way.
 | |
|  */
 | |
| 
 | |
| /****************************************************************************
 | |
| 
 | |
| 		THIS SOFTWARE IS NOT COPYRIGHTED  
 | |
|    
 | |
|    HP offers the following for use in the public domain.  HP makes no
 | |
|    warranty with regard to the software or it's performance and the 
 | |
|    user accepts the software "AS IS" with all faults.
 | |
| 
 | |
|    HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
 | |
|    TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 | |
|    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 | |
| 
 | |
| ****************************************************************************/
 | |
| 
 | |
| #include "asm.h"
 | |
| 
 | |
| 	.title "mvme135-asm.S for m68k"
 | |
| 
 | |
| 	.globl SYM (registers)
 | |
| 	.globl SYM (lastFrame)
 | |
| 	.globl SYM (superStack)
 | |
| 	.globl SYM (exceptionHook)
 | |
| 	.globl SYM (_returnFromException)
 | |
| 	.globl SYM (stackPtr)
 | |
| 	.globl SYM (handle_exception)
 | |
| 	.globl SYM (exceptionSize)
 | |
| 	.globl SYM (exceptionHandler)
 | |
| 
 | |
| .text
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Create a new exception vector table and populates it. Vectors from the
 | |
|  * boot monitor are spliced in so I/O and the abort button will continue
 | |
|  * to work. We also use the monitor's generalized vector for anything the
 | |
|  * debugger doesn't want.
 | |
|  */
 | |
| 	.global	SYM (setup_vectors)
 | |
| SYM (setup_vectors):
 | |
| 	link	fp, IMM (-8)
 | |
| 	/* copy monitor vector table */
 | |
| 
 | |
| 	movecl	vbr, a0
 | |
| 	lea	SYM (vbr_table), a1
 | |
| 	movel	0x8(a0), d0		/* get generalized vector */
 | |
| 	movew	IMM (0x3fc), d1		/* load vector count */
 | |
| 
 | |
| loop:					/* fill table to gen. vector */
 | |
| 	movel	d0, (a1,d1)
 | |
| 	subqw	IMM (4), d1
 | |
| 	bne	loop
 | |
| 
 | |
| 	movel	0x10(a0), 0x10(a1) /* breakpoint */
 | |
| 	movel	0x24(a0), 0x24(a1) /* trace */
 | |
| 	movel	0xbc(a0), 0xbc(a1) /* system call */
 | |
| 
 | |
|         /* add stub vectors to table */
 | |
|         movel	SYM (_catchException), 0x8(a1)  /* vector = 2,  Access Fault */
 | |
|         movel	SYM (_catchException), 0xc(a1)  /* vector = 3,  Address Error */
 | |
|         movel   SYM (_catchException), 0x10(a1) /* vector = 4,  Illegal instruction */
 | |
|         movel   SYM (_catchException), 0x14(a1) /* vector = 5,  divide by 0 */
 | |
|         movel   SYM (_catchException), 0x18(a1) /* vector = 6,  chk, chk2 instruction */
 | |
|         movel   SYM (_catchException), 0x1c(a1) /* vector = 7,  ftrap, trap, trapv ins */
 | |
|         movel   SYM (_catchException), 0x20(a1) /* vector = 8,  priviledge violation */
 | |
|         movel   SYM (_catchException), 0x24(a1) /* vector = 9,  trace */
 | |
|         movel   SYM (_catchException), 0x28(a1) /* vector = 10, Aline opcode */
 | |
|         movel   SYM (_catchException), 0x2c(a1) /* vector = 11, fline opcode */
 | |
|         movel   SYM (_catchException), 0x30(a1) /* vector = 12, reserved */
 | |
|         movel   SYM (_catchException), 0x34(a1) /* vector = 13, coprocessor protocol violation */
 | |
|         movel   SYM (_catchException), 0x38(a1) /* vector = 14, format error */
 | |
|         movel   SYM (_catchException), 0x3c(a1) /* vector = 15, unitialized interupt */
 | |
|         
 | |
|         /* unassigned, reserved */
 | |
|         movel   SYM (_catchException), 0x40(a1) /* vector = 16 */
 | |
|         movel   SYM (_catchException), 0x44(a1) /* vector = 17 */
 | |
|         movel   SYM (_catchException), 0x48(a1) /* vector = 18 */
 | |
|         movel   SYM (_catchException), 0x4c(a1) /* vector = 19 */
 | |
|         movel   SYM (_catchException), 0x50(a1) /* vector = 20 */
 | |
|         movel   SYM (_catchException), 0x54(a1) /* vector = 21 */
 | |
|         movel   SYM (_catchException), 0x58(a1) /* vector = 22 */
 | |
|         movel   SYM (_catchException), 0x5c(a1) /* vector = 23 */
 | |
| 
 | |
|         movel   SYM (_catchException), 0x84(a1) /* vector = 33, breakpoint, trap #1 */
 | |
|         movel   SYM (_catchException), 0xa0(a1) /* vector = 40 , trap #8*/
 | |
| 
 | |
|         /* floating point traps */
 | |
|         movel   SYM (_catchException), 0xc0(a1) /* vector = 48 */
 | |
|         movel   SYM (_catchException), 0xc4(a1) /* vector = 49 */
 | |
|         movel   SYM (_catchException), 0xc8(a1) /* vector = 50 */
 | |
|         movel   SYM (_catchException), 0xcc(a1) /* vector = 51 */
 | |
|         movel   SYM (_catchException), 0xd0(a1) /* vector = 52 */
 | |
|         movel   SYM (_catchException), 0xd4(a1) /* vector = 53 */
 | |
|         movel   SYM (_catchException), 0xd8(a1) /* vector = 54 */
 | |
|         movel   SYM (_catchException), 0xdc(a1) /* vector = 55 */
 | |
|         movel   SYM (_catchException), 0xe0(a1) /* vector = 56 */
 | |
|         movel   SYM (_catchException), 0xe4(a1) /* vector = 57 */
 | |
|         movel   SYM (_catchException), 0xe8(a1) /* vector = 58 */
 | |
| 
 | |
| /***        movel   &__debug_level7, 0x7c(a1) /* level7 interupt vector */
 | |
| 
 | |
| 	movecl	a1, vbr		/* change VBR to new table */        
 | |
| 	unlk	fp
 | |
| 	rts
 | |
| /*
 | |
|  * exceptionHandler -- sets up exception vector table.
 | |
|  *		       First arg is an integer vector number
 | |
|  *		       Second arg is the function pointer for the vector
 | |
|  */
 | |
| SYM (exceptionHandler):
 | |
| #	link	a6, IMM (-8)
 | |
| #str1:	.ascii	"Exception Handler Called\n"
 | |
| #	moveal	IMM (str1), a0
 | |
| #	moveal	IMM (str1+25), a1
 | |
| #	jsr	SYM (outln)
 | |
| 
 | |
| #	unlk	a6
 | |
| 	rts
 | |
| 
 | |
| /* this never gets called */
 | |
|  	movel	fp@(8), d0		/* get vector number */
 | |
| 	movel	fp@(12), a0		/* get function address */
 | |
| 	moveal	&SYM (vbr_table), a1	/* FIXME */
 | |
| 
 | |
| 	addl	d0, d0
 | |
| 	addl	d0, d0
 | |
| 
 | |
| 	addal	d0, a1
 | |
| 	movel	a0, (a1)
 | |
| 
 | |
| 	movecl	a1, vbr
 | |
| 	unlk	a6
 | |
| 	rts
 | |
| 
 | |
| .globl SYM (return_to_super)
 | |
| SYM (return_to_super):
 | |
|         movel   SYM (registers)+60,sp /* get new stack pointer */
 | |
|         movel   SYM (lastFrame),a0    /* get last frame info  */
 | |
|         bra     return_to_any
 | |
| 
 | |
| .globl SYM (return_to_user)
 | |
| SYM (return_to_user):
 | |
|         movel   SYM (registers)+60,a0   /* get usp */
 | |
|         movel   a0,usp           /* set usp */
 | |
|         movel   SYM (superStack),sp    /* get original stack pointer */
 | |
| 
 | |
| return_to_any:
 | |
|         movel   SYM (lastFrame),a0     /* get last frame info  */
 | |
|         movel   a0@+,SYM (lastFrame)   /* link in previous frame     */
 | |
|         addql   IMM (8),a0            /* skip over pc, vector#*/              
 | |
|         movew  	a0@+,d0         /* get # of words in cpu frame */       
 | |
|         addw    d0,a0           /* point to end of data        */       
 | |
|         addw    d0,a0           /* point to end of data        */       
 | |
|         movel   a0,a1
 | |
| /* copy the stack frame */
 | |
|         subql   IMM (1),d0
 | |
| copyUserLoop:                                                               
 | |
|         movew   a1@-,sp@-                                               
 | |
|         dbf     d0,copyUserLoop                                             
 | |
| 
 | |
| #ifdef __HAVE_68881__
 | |
| 	fmoveml  SYM (registers)+168,fpcr/fpsr/fpi
 | |
| 	fmovemx  SYM (registers)+72,fp0-fp7
 | |
| 	cmpl     IMM (-1),a0@     /* skip frestore flag set ? */
 | |
| 	beq      skip_frestore
 | |
| 	frestore a0@+
 | |
| skip_frestore:
 | |
| #endif
 | |
| 
 | |
| 	moveml  SYM (registers),d0-d7/a0-a6
 | |
| 	rte  /* pop and go! */
 | |
| 
 | |
| 
 | |
| /* this function is called immediately when a level 7 interrupt occurs */
 | |
| /* if the previous interrupt level was 7 then we're already servicing  */
 | |
| /* this interrupt and an rte is in order to return to the debugger.    */
 | |
| /* For the 68000, the offset for sr is 6 due to the jsr return address */
 | |
| .text
 | |
| .globl SYM (_debug_level7)
 | |
| SYM (_debug_level7):
 | |
| 	movew   d0,sp@-
 | |
| #ifdef mc68020
 | |
| 	movew   sp@(2),d0
 | |
| #else
 | |
| 	movew   sp@(6),d0
 | |
| #endif
 | |
| 	andiw   IMM (0x700),d0
 | |
| 	cmpiw   IMM (0x700),d0
 | |
| 	beq     _already7
 | |
|         movew   sp@+,d0	
 | |
|         bra     SYM (_catchException)
 | |
| _already7:
 | |
| 	movew   sp@+,d0
 | |
| #ifndef mc68020
 | |
| 	lea     sp@(4),sp     /* pull off 68000 return address */
 | |
| #endif
 | |
| 	rte
 | |
| 
 | |
| #ifdef mc68020
 | |
| /* This function is called when a 68020 exception occurs.  It saves
 | |
|  * all the cpu and fpcp regs in the _registers array, creates a frame on a
 | |
|  * linked list of frames which has the cpu and fpcp stack frames needed
 | |
|  * to properly restore the context of these processors, and invokes
 | |
|  * an exception handler (remcom_handler).
 | |
|  *
 | |
|  * stack on entry:                       stack on exit:
 | |
|  *   N bytes of junk                     exception # MSWord
 | |
|  *   Exception Format Word               exception # MSWord
 | |
|  *   Program counter LSWord              
 | |
|  *   Program counter MSWord             
 | |
|  *   Status Register                    
 | |
|  *                                       
 | |
|  *                                       
 | |
|  */
 | |
| 
 | |
| .text
 | |
| .globl SYM (_catchException)
 | |
| SYM (_catchException):
 | |
| 
 | |
| 	oriw   IMM (0x0700),sr	/* Disable interrupts */
 | |
| 
 | |
|         moveml  d0-d7/a0-a6,SYM (registers) /* save registers        */
 | |
| 	movel	SYM (lastFrame),a0	/* last frame pointer */
 | |
| 
 | |
| #ifdef __HAVE_68881__
 | |
| 	/* do an fsave, then remember the address to begin a restore from */
 | |
| 	fsave   a0@-
 | |
| 	fmovemx fp0-fp7, SYM (registers)+72
 | |
| 	fmoveml fpcr/fpsr/fpi, SYM (registers)+168
 | |
| #endif
 | |
| 
 | |
| 	lea     SYM (registers),a5    /* get address of registers     */
 | |
|         movew   sp@,d1          /* get status register          */
 | |
|         movew   d1,a5@(66)      /* save sr		 	*/	
 | |
| 	movel   sp@(2),a4       /* save pc in a4 for later use  */
 | |
|         movel   a4,a5@(68)      /* save pc in _regisers[]      	*/
 | |
| 
 | |
| /* figure out how many bytes in the stack frame */
 | |
| 	movew   sp@(6),d0	/* get '020 exception format	*/
 | |
|         movew   d0,d2   	/* make a copy of format word   */
 | |
|         andiw   IMM (0xf000),d0 /* mask off format type         */
 | |
|         rolw    IMM (5),d0           /* rotate into the low byte *2  */
 | |
|         lea     SYM (exceptionSize),a1
 | |
|         addw    d0,a1          /* index into the table         */
 | |
| 	movew   a1@,d0         /* get number of words in frame */
 | |
|         movew   d0,d3          /* save it                      */
 | |
|         subw    d0,a0	       /* adjust save pointer          */
 | |
|         subw    d0,a0	       /* adjust save pointer(bytes)   */
 | |
| 	movel   a0,a1          /* copy save pointer            */
 | |
| 	subql   IMM (1),d0     /* predecrement loop counter    */
 | |
| 
 | |
| /* copy the frame */
 | |
| 
 | |
| saveFrameLoop:
 | |
| 	movew  	sp@+,a1@+
 | |
| 	dbf     d0,saveFrameLoop
 | |
| 
 | |
| /* now that the stack has been clenaed,
 | |
|  * save the a7 in use at time of exception
 | |
|  */
 | |
|         movel   sp,SYM (superStack)  /* save supervisor sp           */
 | |
|         andiw   IMM (0x2000),d1      /* were we in supervisor mode ? */
 | |
|         beq     userMode       
 | |
|         movel   a7,a5@(60)      /* save a7                  */
 | |
|         bra     a7saveDone
 | |
| userMode:  
 | |
| 	movel   usp,a1    	
 | |
|         movel   a1,a5@(60)     /* save user stack pointer	*/
 | |
| a7saveDone:
 | |
| 
 | |
| 
 | |
| /* save size of frame */
 | |
|         movew   d3,a0@-
 | |
| 
 | |
| /* compute exception number */
 | |
| 	andl    IMM (0xfff),d2   	/* mask off vector offset	*/
 | |
| 	lsrw    IMM (2),d2   	/* divide by 4 to get vect num	*/
 | |
|         movel   d2,a0@-       /* save it                      */
 | |
| 
 | |
| /* save pc causing exception */
 | |
|         movel   a4,a0@-
 | |
| 
 | |
| /* save old frame link and set the new value*/
 | |
| 	movel	SYM (lastFrame),a1	/* last frame pointer */
 | |
| 	movel   a1,a0@-		/* save pointer to prev frame	*/
 | |
|         movel   a0,SYM (lastFrame)
 | |
| 
 | |
|         movel   d2,sp@-		/* push exception num           */
 | |
| #ifdef TMP_HACK
 | |
| 	movel   SYM (exceptionHook),a0   /* get address of handler */
 | |
|         jbsr    a0@            /* and call it */
 | |
| #else
 | |
|         jbsr    SYM (remcomHandler)
 | |
| #endif
 | |
|         clrl    sp@             /* replace exception num parm with frame ptr */
 | |
|         jbsr    SYM (_returnFromException)    /* jbsr, but never returns */
 | |
| 
 | |
| #else /* mc68000 */
 | |
| 
 | |
| /* This function is called when an exception occurs.  It translates the
 | |
|  * return address found on the stack into an exception vector # which
 | |
|  * is then handled by either handle_exception or a system handler.
 | |
|  * _catchException provides a front end for both.  
 | |
|  *
 | |
|  * stack on entry:                       stack on exit:
 | |
|  *   Program counter MSWord              exception # MSWord 
 | |
|  *   Program counter LSWord              exception # MSWord
 | |
|  *   Status Register                     
 | |
|  *   Return Address  MSWord              
 | |
|  *   Return Address  LSWord             
 | |
|  */
 | |
| .text
 | |
| .globl SYM (_catchException)
 | |
| SYM (_catchException):
 | |
| 
 | |
| 	oriw   IMM (0x0700),sr	/* Disable interrupts */
 | |
| 
 | |
|         moveml d0-d7/a0-a6,SYM (registers)  /* save registers               */
 | |
| 	movel	SYM (lastFrame),a0	/* last frame pointer */
 | |
| 
 | |
| #ifdef __HAVE_68881__
 | |
| 	/* do an fsave, then remember the address to begin a restore from */
 | |
| 	fsave   a0@-
 | |
| 	fmovemx fp0-fp7, SYM (registers)+72
 | |
| 	fmoveml fpcr/fpsr/fpi, SYM (registers)+168
 | |
| #endif
 | |
| 
 | |
|         lea     SYM (registers),a5    /* get address of registers     */
 | |
|         movel   sp@+,d2        /* pop return address           */
 | |
| 	addl 	IMM (1530),d2  /* convert return addr to 	*/
 | |
| 	divs 	IMM (6),d2     /*  exception number		*/
 | |
| 	extl    d2   
 | |
| 
 | |
|         moveql  IMM (3),d3     /* assume a three word frame     */
 | |
| 
 | |
|         cmpiw   IMM (3),d2     /* bus error or address error ? */
 | |
|         bgt     normal         /* if >3 then normal error      */
 | |
|         movel   sp@+,a0@-      /* copy error info to frame buff*/
 | |
|         movel   sp@+,a0@-      /* these are never used         */
 | |
|         moveql  IMM (7),d3     /* this is a 7 word frame       */
 | |
|      
 | |
| normal:   
 | |
| 	movew   sp@+,d1        /* pop status register          */
 | |
|         movel   sp@+,a4        /* pop program counter          */
 | |
|         movew   d1,a5@(66)     /* save sr		 	*/	
 | |
|         movel   a4,a5@(68)     /* save pc in _regisers[]      	*/
 | |
|         movel   a4,a0@-        /* copy pc to frame buffer      */
 | |
| 	movew   d1,a0@-        /* copy sr to frame buffer      */
 | |
| 
 | |
|         movel   sp,SYM (superStack)   /* save supervisor sp          */
 | |
| 
 | |
|         andiw   IMM (0x2000),d1      /* were we in supervisor mode ? */
 | |
|         beq     userMode       
 | |
|         movel   a7,a5@(60)      /* save a7                  */
 | |
|         bra     saveDone             
 | |
| userMode:
 | |
|         movel   usp,a1    	 /* save user stack pointer 	*/
 | |
|         movel   a1,a5@(60)     /* save user stack pointer	*/
 | |
| saveDone:
 | |
| 
 | |
|         movew   d3,a0@-        /* push frame size in words     */
 | |
|         movel   d2,a0@-        /* push vector number           */
 | |
|         movel   a4,a0@-        /* push exception pc            */
 | |
| 
 | |
| /* save old frame link and set the new value */
 | |
| 	movel	SYM (lastFrame),a1	 /* last frame pointer */
 | |
| 	movel   a1,a0@-	 /* save pointer to prev frame	*/
 | |
|         movel   a0,SYM (lastFrame)
 | |
| 
 | |
|         movel   d2,sp@-	    	/* push exception num           */
 | |
| 	movel   SYM (exceptionHook),a0   /* get address of handler */
 | |
|         jbsr    a0@             /* and call it */
 | |
|         clrl    sp@             /* replace exception num parm with frame ptr */
 | |
|         jbsr     SYM (_returnFromException)   /* jbsr, but never returns */
 | |
| 
 | |
| #endif /* m68000 */
 | |
| 
 | |
| /*
 | |
|  * remcomHandler is a front end for handle_exception.  It moves the
 | |
|  * stack pointer into an area reserved for debugger use in case the
 | |
|  * breakpoint happened in supervisor mode.
 | |
|  */
 | |
| .globl SYM (remcomHandler)
 | |
| SYM (remcomHandler):
 | |
| 	addl    IMM (4),sp	/* pop off return address     */
 | |
|         movel   sp@+,d0     	/* get the exception number   */
 | |
| 	movel   SYM (stackPtr),sp	/* move to remcom stack area  */
 | |
| 	movel   d0,sp@-	 	/* push exception onto stack  */
 | |
| 	jbsr    SYM (handle_exception)	/* this never returns */
 | |
|         rts			/* return */
 |