1/*
2 * mvme135-asm.S -- assembler routines for the MVME stub.
3 *
4 * This code was pulled out of mvme135-stub.c by Ian Taylor so that I
5 * could handle different register and label prefixes in a sensible
6 * way.
7 */
8
9/****************************************************************************
10
11		THIS SOFTWARE IS NOT COPYRIGHTED
12
13   HP offers the following for use in the public domain.  HP makes no
14   warranty with regard to the software or it's performance and the
15   user accepts the software "AS IS" with all faults.
16
17   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
18   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20
21****************************************************************************/
22
23#include "asm.h"
24
25	.title "mvme135-asm.S for m68k"
26
27	.globl SYM (registers)
28	.globl SYM (lastFrame)
29	.globl SYM (superStack)
30	.globl SYM (exceptionHook)
31	.globl SYM (_returnFromException)
32	.globl SYM (stackPtr)
33	.globl SYM (handle_exception)
34	.globl SYM (exceptionSize)
35	.globl SYM (exceptionHandler)
36
37.text
38
39
40/*
41 * Create a new exception vector table and populates it. Vectors from the
42 * boot monitor are spliced in so I/O and the abort button will continue
43 * to work. We also use the monitor's generalized vector for anything the
44 * debugger doesn't want.
45 */
46	.global	SYM (setup_vectors)
47SYM (setup_vectors):
48	link	fp, IMM (-8)
49	/* copy monitor vector table */
50
51	movecl	vbr, a0
52	lea	SYM (vbr_table), a1
53	movel	0x8(a0), d0		/* get generalized vector */
54	movew	IMM (0x3fc), d1		/* load vector count */
55
56loop:					/* fill table to gen. vector */
57	movel	d0, (a1,d1)
58	subqw	IMM (4), d1
59	bne	loop
60
61	movel	0x10(a0), 0x10(a1) /* breakpoint */
62	movel	0x24(a0), 0x24(a1) /* trace */
63	movel	0xbc(a0), 0xbc(a1) /* system call */
64
65        /* add stub vectors to table */
66        movel	SYM (_catchException), 0x8(a1)  /* vector = 2,  Access Fault */
67        movel	SYM (_catchException), 0xc(a1)  /* vector = 3,  Address Error */
68        movel   SYM (_catchException), 0x10(a1) /* vector = 4,  Illegal instruction */
69        movel   SYM (_catchException), 0x14(a1) /* vector = 5,  divide by 0 */
70        movel   SYM (_catchException), 0x18(a1) /* vector = 6,  chk, chk2 instruction */
71        movel   SYM (_catchException), 0x1c(a1) /* vector = 7,  ftrap, trap, trapv ins */
72        movel   SYM (_catchException), 0x20(a1) /* vector = 8,  priviledge violation */
73        movel   SYM (_catchException), 0x24(a1) /* vector = 9,  trace */
74        movel   SYM (_catchException), 0x28(a1) /* vector = 10, Aline opcode */
75        movel   SYM (_catchException), 0x2c(a1) /* vector = 11, fline opcode */
76        movel   SYM (_catchException), 0x30(a1) /* vector = 12, reserved */
77        movel   SYM (_catchException), 0x34(a1) /* vector = 13, coprocessor protocol violation */
78        movel   SYM (_catchException), 0x38(a1) /* vector = 14, format error */
79        movel   SYM (_catchException), 0x3c(a1) /* vector = 15, unitialized interupt */
80
81        /* unassigned, reserved */
82        movel   SYM (_catchException), 0x40(a1) /* vector = 16 */
83        movel   SYM (_catchException), 0x44(a1) /* vector = 17 */
84        movel   SYM (_catchException), 0x48(a1) /* vector = 18 */
85        movel   SYM (_catchException), 0x4c(a1) /* vector = 19 */
86        movel   SYM (_catchException), 0x50(a1) /* vector = 20 */
87        movel   SYM (_catchException), 0x54(a1) /* vector = 21 */
88        movel   SYM (_catchException), 0x58(a1) /* vector = 22 */
89        movel   SYM (_catchException), 0x5c(a1) /* vector = 23 */
90
91        movel   SYM (_catchException), 0x84(a1) /* vector = 33, breakpoint, trap #1 */
92        movel   SYM (_catchException), 0xa0(a1) /* vector = 40 , trap #8*/
93
94        /* floating point traps */
95        movel   SYM (_catchException), 0xc0(a1) /* vector = 48 */
96        movel   SYM (_catchException), 0xc4(a1) /* vector = 49 */
97        movel   SYM (_catchException), 0xc8(a1) /* vector = 50 */
98        movel   SYM (_catchException), 0xcc(a1) /* vector = 51 */
99        movel   SYM (_catchException), 0xd0(a1) /* vector = 52 */
100        movel   SYM (_catchException), 0xd4(a1) /* vector = 53 */
101        movel   SYM (_catchException), 0xd8(a1) /* vector = 54 */
102        movel   SYM (_catchException), 0xdc(a1) /* vector = 55 */
103        movel   SYM (_catchException), 0xe0(a1) /* vector = 56 */
104        movel   SYM (_catchException), 0xe4(a1) /* vector = 57 */
105        movel   SYM (_catchException), 0xe8(a1) /* vector = 58 */
106
107/***        movel   &__debug_level7, 0x7c(a1) /* level7 interupt vector */
108
109	movecl	a1, vbr		/* change VBR to new table */
110	unlk	fp
111	rts
112/*
113 * exceptionHandler -- sets up exception vector table.
114 *		       First arg is an integer vector number
115 *		       Second arg is the function pointer for the vector
116 */
117SYM (exceptionHandler):
118#	link	a6, IMM (-8)
119#str1:	.ascii	"Exception Handler Called\n"
120#	moveal	IMM (str1), a0
121#	moveal	IMM (str1+25), a1
122#	jsr	SYM (outln)
123
124#	unlk	a6
125	rts
126
127/* this never gets called */
128 	movel	fp@(8), d0		/* get vector number */
129	movel	fp@(12), a0		/* get function address */
130	moveal	&SYM (vbr_table), a1	/* FIXME */
131
132	addl	d0, d0
133	addl	d0, d0
134
135	addal	d0, a1
136	movel	a0, (a1)
137
138	movecl	a1, vbr
139	unlk	a6
140	rts
141
142.globl SYM (return_to_super)
143SYM (return_to_super):
144        movel   SYM (registers)+60,sp /* get new stack pointer */
145        movel   SYM (lastFrame),a0    /* get last frame info  */
146        bra     return_to_any
147
148.globl SYM (return_to_user)
149SYM (return_to_user):
150        movel   SYM (registers)+60,a0   /* get usp */
151        movel   a0,usp           /* set usp */
152        movel   SYM (superStack),sp    /* get original stack pointer */
153
154return_to_any:
155        movel   SYM (lastFrame),a0     /* get last frame info  */
156        movel   a0@+,SYM (lastFrame)   /* link in previous frame     */
157        addql   IMM (8),a0            /* skip over pc, vector#*/
158        movew  	a0@+,d0         /* get # of words in cpu frame */
159        addw    d0,a0           /* point to end of data        */
160        addw    d0,a0           /* point to end of data        */
161        movel   a0,a1
162/* copy the stack frame */
163        subql   IMM (1),d0
164copyUserLoop:
165        movew   a1@-,sp@-
166        dbf     d0,copyUserLoop
167
168#ifdef __HAVE_68881__
169	fmoveml  SYM (registers)+168,fpcr/fpsr/fpi
170	fmovemx  SYM (registers)+72,fp0-fp7
171	cmpl     IMM (-1),a0@     /* skip frestore flag set ? */
172	beq      skip_frestore
173	frestore a0@+
174skip_frestore:
175#endif
176
177	moveml  SYM (registers),d0-d7/a0-a6
178	rte  /* pop and go! */
179
180
181/* this function is called immediately when a level 7 interrupt occurs */
182/* if the previous interrupt level was 7 then we're already servicing  */
183/* this interrupt and an rte is in order to return to the debugger.    */
184/* For the 68000, the offset for sr is 6 due to the jsr return address */
185.text
186.globl SYM (_debug_level7)
187SYM (_debug_level7):
188	movew   d0,sp@-
189#ifdef mc68020
190	movew   sp@(2),d0
191#else
192	movew   sp@(6),d0
193#endif
194	andiw   IMM (0x700),d0
195	cmpiw   IMM (0x700),d0
196	beq     _already7
197        movew   sp@+,d0
198        bra     SYM (_catchException)
199_already7:
200	movew   sp@+,d0
201#ifndef mc68020
202	lea     sp@(4),sp     /* pull off 68000 return address */
203#endif
204	rte
205
206#ifdef mc68020
207/* This function is called when a 68020 exception occurs.  It saves
208 * all the cpu and fpcp regs in the _registers array, creates a frame on a
209 * linked list of frames which has the cpu and fpcp stack frames needed
210 * to properly restore the context of these processors, and invokes
211 * an exception handler (remcom_handler).
212 *
213 * stack on entry:                       stack on exit:
214 *   N bytes of junk                     exception # MSWord
215 *   Exception Format Word               exception # MSWord
216 *   Program counter LSWord
217 *   Program counter MSWord
218 *   Status Register
219 *
220 *
221 */
222
223.text
224.globl SYM (_catchException)
225SYM (_catchException):
226
227	oriw   IMM (0x0700),sr	/* Disable interrupts */
228
229        moveml  d0-d7/a0-a6,SYM (registers) /* save registers        */
230	movel	SYM (lastFrame),a0	/* last frame pointer */
231
232#ifdef __HAVE_68881__
233	/* do an fsave, then remember the address to begin a restore from */
234	fsave   a0@-
235	fmovemx fp0-fp7, SYM (registers)+72
236	fmoveml fpcr/fpsr/fpi, SYM (registers)+168
237#endif
238
239	lea     SYM (registers),a5    /* get address of registers     */
240        movew   sp@,d1          /* get status register          */
241        movew   d1,a5@(66)      /* save sr		 	*/
242	movel   sp@(2),a4       /* save pc in a4 for later use  */
243        movel   a4,a5@(68)      /* save pc in _regisers[]      	*/
244
245/* figure out how many bytes in the stack frame */
246	movew   sp@(6),d0	/* get '020 exception format	*/
247        movew   d0,d2   	/* make a copy of format word   */
248        andiw   IMM (0xf000),d0 /* mask off format type         */
249        rolw    IMM (5),d0           /* rotate into the low byte *2  */
250        lea     SYM (exceptionSize),a1
251        addw    d0,a1          /* index into the table         */
252	movew   a1@,d0         /* get number of words in frame */
253        movew   d0,d3          /* save it                      */
254        subw    d0,a0	       /* adjust save pointer          */
255        subw    d0,a0	       /* adjust save pointer(bytes)   */
256	movel   a0,a1          /* copy save pointer            */
257	subql   IMM (1),d0     /* predecrement loop counter    */
258
259/* copy the frame */
260
261saveFrameLoop:
262	movew  	sp@+,a1@+
263	dbf     d0,saveFrameLoop
264
265/* now that the stack has been clenaed,
266 * save the a7 in use at time of exception
267 */
268        movel   sp,SYM (superStack)  /* save supervisor sp           */
269        andiw   IMM (0x2000),d1      /* were we in supervisor mode ? */
270        beq     userMode
271        movel   a7,a5@(60)      /* save a7                  */
272        bra     a7saveDone
273userMode:
274	movel   usp,a1
275        movel   a1,a5@(60)     /* save user stack pointer	*/
276a7saveDone:
277
278
279/* save size of frame */
280        movew   d3,a0@-
281
282/* compute exception number */
283	andl    IMM (0xfff),d2   	/* mask off vector offset	*/
284	lsrw    IMM (2),d2   	/* divide by 4 to get vect num	*/
285        movel   d2,a0@-       /* save it                      */
286
287/* save pc causing exception */
288        movel   a4,a0@-
289
290/* save old frame link and set the new value*/
291	movel	SYM (lastFrame),a1	/* last frame pointer */
292	movel   a1,a0@-		/* save pointer to prev frame	*/
293        movel   a0,SYM (lastFrame)
294
295        movel   d2,sp@-		/* push exception num           */
296#ifdef TMP_HACK
297	movel   SYM (exceptionHook),a0   /* get address of handler */
298        jbsr    a0@            /* and call it */
299#else
300        jbsr    SYM (remcomHandler)
301#endif
302        clrl    sp@             /* replace exception num parm with frame ptr */
303        jbsr    SYM (_returnFromException)    /* jbsr, but never returns */
304
305#else /* mc68000 */
306
307/* This function is called when an exception occurs.  It translates the
308 * return address found on the stack into an exception vector # which
309 * is then handled by either handle_exception or a system handler.
310 * _catchException provides a front end for both.
311 *
312 * stack on entry:                       stack on exit:
313 *   Program counter MSWord              exception # MSWord
314 *   Program counter LSWord              exception # MSWord
315 *   Status Register
316 *   Return Address  MSWord
317 *   Return Address  LSWord
318 */
319.text
320.globl SYM (_catchException)
321SYM (_catchException):
322
323	oriw   IMM (0x0700),sr	/* Disable interrupts */
324
325        moveml d0-d7/a0-a6,SYM (registers)  /* save registers               */
326	movel	SYM (lastFrame),a0	/* last frame pointer */
327
328#ifdef __HAVE_68881__
329	/* do an fsave, then remember the address to begin a restore from */
330	fsave   a0@-
331	fmovemx fp0-fp7, SYM (registers)+72
332	fmoveml fpcr/fpsr/fpi, SYM (registers)+168
333#endif
334
335        lea     SYM (registers),a5    /* get address of registers     */
336        movel   sp@+,d2        /* pop return address           */
337	addl 	IMM (1530),d2  /* convert return addr to 	*/
338	divs 	IMM (6),d2     /*  exception number		*/
339	extl    d2
340
341        moveql  IMM (3),d3     /* assume a three word frame     */
342
343        cmpiw   IMM (3),d2     /* bus error or address error ? */
344        bgt     normal         /* if >3 then normal error      */
345        movel   sp@+,a0@-      /* copy error info to frame buff*/
346        movel   sp@+,a0@-      /* these are never used         */
347        moveql  IMM (7),d3     /* this is a 7 word frame       */
348
349normal:
350	movew   sp@+,d1        /* pop status register          */
351        movel   sp@+,a4        /* pop program counter          */
352        movew   d1,a5@(66)     /* save sr		 	*/
353        movel   a4,a5@(68)     /* save pc in _regisers[]      	*/
354        movel   a4,a0@-        /* copy pc to frame buffer      */
355	movew   d1,a0@-        /* copy sr to frame buffer      */
356
357        movel   sp,SYM (superStack)   /* save supervisor sp          */
358
359        andiw   IMM (0x2000),d1      /* were we in supervisor mode ? */
360        beq     userMode
361        movel   a7,a5@(60)      /* save a7                  */
362        bra     saveDone
363userMode:
364        movel   usp,a1    	 /* save user stack pointer 	*/
365        movel   a1,a5@(60)     /* save user stack pointer	*/
366saveDone:
367
368        movew   d3,a0@-        /* push frame size in words     */
369        movel   d2,a0@-        /* push vector number           */
370        movel   a4,a0@-        /* push exception pc            */
371
372/* save old frame link and set the new value */
373	movel	SYM (lastFrame),a1	 /* last frame pointer */
374	movel   a1,a0@-	 /* save pointer to prev frame	*/
375        movel   a0,SYM (lastFrame)
376
377        movel   d2,sp@-	    	/* push exception num           */
378	movel   SYM (exceptionHook),a0   /* get address of handler */
379        jbsr    a0@             /* and call it */
380        clrl    sp@             /* replace exception num parm with frame ptr */
381        jbsr     SYM (_returnFromException)   /* jbsr, but never returns */
382
383#endif /* m68000 */
384
385/*
386 * remcomHandler is a front end for handle_exception.  It moves the
387 * stack pointer into an area reserved for debugger use in case the
388 * breakpoint happened in supervisor mode.
389 */
390.globl SYM (remcomHandler)
391SYM (remcomHandler):
392	addl    IMM (4),sp	/* pop off return address     */
393        movel   sp@+,d0     	/* get the exception number   */
394	movel   SYM (stackPtr),sp	/* move to remcom stack area  */
395	movel   d0,sp@-	 	/* push exception onto stack  */
396	jbsr    SYM (handle_exception)	/* this never returns */
397        rts			/* return */
398