Home | History | Annotate | Line # | Download | only in mac68k
      1 /*	$NetBSD: macromasm.s,v 1.22 2009/11/01 01:51:35 snj Exp $	*/
      2 
      3 /*-
      4  * Copyright (C) 1994	Bradley A. Grantham
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 /*
     29  * Mac ROM Glue assembly
     30  */
     31 
     32 
     33 #include "opt_adb.h"
     34 #include "assym.h"
     35 #include <machine/asm.h>
     36 #include <machine/trap.h>
     37 
     38 
     39 	/* Define this symbol as global with (v) value */
     40 #define loglob(g, v)	\
     41 	.global _C_LABEL(g) ;\
     42 	.set	_C_LABEL(g), v
     43 
     44 	/* Return from a pascal function; pop (pbytes) number of bytes */
     45 	/*  passed as parameters.  Should have picked up "pascal" extension */
     46 	/*  to GCC... */
     47 #ifdef __STDC__
     48 #define	IMMEDIATE	#
     49 #define pascalret(pbytes)	\
     50 	movl	%sp@+,%a1		/* get PC (I hate Pascal) */ ; \
     51 	addl	IMMEDIATE pbytes,%sp	/* pop params (I hate Pascal) */ ; \
     52 	jra	%a1@			/* return (I hate Pascal) */
     53 #else
     54 #define pascalret(pbytes)	\
     55 	movl	%sp@+,%a1		/* get PC (I hate Pascal) */ ; \
     56 	addl	#pbytes,%sp		/* pop params (I hate Pascal) */ ; \
     57 	jra	%a1@			/* return (I hate Pascal) */
     58 #endif
     59 
     60 
     61 /*
     62  * MacOS low-memory global variables.
     63  */
     64 	loglob(ADBBase, 0xcf8)		/* ptr to ADB driver variables */
     65 	loglob(ADBYMM, 0xd18)		/* Yet more memory used by ADB/PM */
     66 	loglob(ADBDelay, 0xcea) 	/* 8s of dbras per ADB delay */
     67 	loglob(ROMBase, 0x2ae)		/* ptr to ROM Base */
     68 	loglob(Lvl1DT, 0x192)		/* VIA 1 interrupt table */
     69 	loglob(Lvl2DT, 0x1b2)		/* VIA 2 interrupt table? */
     70 	loglob(JADBProc, 0x6b8) 	/* ADBReinit pre/post-processing */
     71 	loglob(jADBOp, 0x5f0)		/* pointer to ADBOp */
     72 	loglob(DeviceList, 0x8a8)	/* ptr to first device entry */
     73 	loglob(KbdLast, 0x218)		/* ptr to first device entry */
     74 	loglob(KbdType, 0x21E)		/* ptr to first device entry */
     75 	loglob(JKybdTask, 0x21A)	/* keyboard task jump ptr? */
     76 	loglob(Lo3Bytes, 0x31a) 	/* contains 0x00ffffff */
     77 	loglob(MinusOne, 0xa06) 	/* contains 0xffffffff */
     78 	loglob(MMU32Bit, 0xcb2) 	/* MMU mode (uh-oh) 1 = 32 bit? */
     79 	loglob(CPUFlag, 0x12f)		/* CPU type */
     80 	loglob(MacJmp, 0x120)		/* ?? */
     81 	loglob(Scratch8, 0x9fa) 	/* 8-byte scratch area */
     82 	loglob(Scratch20, 0x1e4)	/* 20-byte scratch area */
     83 	loglob(Ticks, 0x16a)		/* ticks since system startup */
     84 	loglob(Time, 0x20c)		/* Sec since midnight, 1-1-1904 */
     85 	loglob(TimeDBRA, 0xd00) 	/* dbra's per millisecond (short) */
     86 	loglob(ToolScratch, 0x9ce)	/* another 8-byte scratch area */
     87 	loglob(VIA, 0x1d4)		/* VIA1 base address */
     88 	loglob(mrg_VIA2, 0xcec) 	/* VIA2 base address */
     89 	loglob(SCCRd, 0x1d8)		/* SCC read base address */
     90 	loglob(FinderName, 0x2e0)	/* Name of finder */
     91 	loglob(jSwapMMU, 0xdbc) 	/* ptr to MMU swap routine */
     92 	loglob(ADBState, 0xde0) 	/* ptr to ADB state information? */
     93 	loglob(jUnimplTrap, 0x61c)	/* ptr to UnimplTrap routine */
     94 	loglob(jEgret, 0x648)		/* ptr to Egret trap routine */
     95 	loglob(HwCfgFlags, 0xb22)	/* 2 bytes, h/w config flags */
     96 	loglob(HwCfgFlags2, 0xdd0)	/* 4 bytes, more h/w config flags */
     97 	loglob(HwCfgFlags3, 0xdd4)	/* 4 bytes, more h/w config flags */
     98 	loglob(ADBReInit_JTBL, 0xdd8)	/* 4 bytes, pointer to patch table */
     99 	loglob(jClkNoMem, 0x54c)	/* Pointer to ClkNoMem function */
    100 	loglob(PramTransfer, 0x1e4)	/* Transfer buffer used with PRam */
    101 	loglob(SysParam, 0x1f8) 	/* Place where PRam data gets stored */
    102 	loglob(ExpandMem, 0x2b6)	/* pointer to Expanded Memory used by */
    103 					/*   newer ADB routines */
    104 	loglob(VBLQueue, 0x160)		/* Vertical blanking Queue, unused ? */
    105 	loglob(VBLQueue_head, 0x162)	/* Vertical blanking Queue, head */
    106 	loglob(VBLQueue_tail, 0x166)	/* Vertical blanking Queue, tail */
    107 	loglob(jDTInstall, 0xd9c)	/* Deferred task mgr trap handler */
    108 
    109 	loglob(InitEgretJTVec, 0x2010)	/* pointer to a jump table for */
    110 					/* InitEgret on AV machines */
    111 
    112 #if 0
    113 	/* I wish I knew what these things were */
    114 	loglob(MMUFlags, 0xcb0)
    115 	loglob(MMUFluff, 0xcb3)
    116 	loglob(MMUTbl, 0xcb4)
    117 	loglob(MMUTblSize, 0xcb8)
    118 	loglob(MMUType, 0xcb1)
    119 #endif
    120 
    121 	.text
    122 	.even
    123 	.global _C_LABEL(panic)
    124 	.global _C_LABEL(printf)
    125 
    126 #ifdef MRG_ADB
    127 /*
    128  * These functions are defined in adb_direct.c if we are not using
    129  * the MRG method of accessing the ADB/PRAM/RTC.
    130  */
    131 /*
    132  * Most of the following glue just takes C function calls, converts
    133  * the parameters to the MacOS Trap parameters, and then tries to
    134  * return the result correctly.  About the only thing our C functions
    135  * and MacOS' traps have in common is returning numerical results in
    136  * %d0.
    137  *
    138  * If some code actually pulls down the a-trap line, we jump right
    139  * to the ROMs; none of this is called.
    140  */
    141 
    142 /* Initialize Utils, mainly XPRam */
    143 	/*
    144 	 * void
    145 	 */
    146 ENTRY(InitUtil)
    147 	.word 0xa03f
    148 	rts
    149 
    150 
    151 /* Initialize the ADB ------------------------------------------------------*/
    152 	/*
    153 	 * void
    154 	 */
    155 ENTRY(ADBReInit)
    156 	.word	0xa07b
    157 	rts
    158 
    159 
    160 /* Set the ADB device info for a device; routine handler and so on ---------*/
    161 	/*
    162 	 * %sp@(4)	ADBSetInfoBlock *info
    163 	 * %sp@(8)	int		adbAddr
    164 	 */
    165 ENTRY(SetADBInfo)
    166 	movl	%sp@(4),%a0
    167 	movl	%sp@(8),%d0
    168 	.word	0xa07a
    169 	rts
    170 
    171 
    172 /* Find the number of ADB devices in the device table ----------------------*/
    173 	/*
    174 	 * void
    175 	 */
    176 ENTRY(CountADBs)
    177 	.word 0xa077
    178 	rts
    179 
    180 
    181 /* Get ADB entry from index in table ---------------------------------------*/
    182 	/*
    183 	 * sp@(4)	ADBDataBlock	*info
    184 	 * sp@(8)	u_short 	devTableIndex
    185 	 */
    186 ENTRY(GetIndADB)
    187 	movl	%sp@(4),%a0
    188 	movl	%sp@(8),%d0
    189 	.word 0xa078
    190 	rts
    191 
    192 
    193 /* Get ADB device information ----------------------------------------------*/
    194 	/*
    195 	 * sp@(4)	ADBSetInfoBlock *info
    196 	 * sp@(8)	int		adbAddr
    197 	 */
    198 ENTRY(GetADBInfo)
    199 	movl	%sp@(4),%a0
    200 	movl	%sp@(8),%d0
    201 	.word 0xa079
    202 	rts
    203 
    204 
    205 /* Perform an ADB transaction ----------------------------------------------*/
    206 	/*
    207 	 * sp@(4)	Ptr	buffer
    208 	 * sp@(8)	Ptr	compRout
    209 	 * sp@(12)	Ptr	data
    210 	 * sp@(16)	short	commandNum
    211 	 */
    212 ENTRY(ADBOp)
    213 	lea	%sp@(4),%a0
    214 	movl	%sp@(16),%d0
    215 	.word 0xa07c
    216 	rts
    217 #endif /* MRG_ADB */
    218 
    219 
    220 #if 0
    221 /* My Own Trap (for testing.  returns 50.) ---------------------------------*/
    222 	.global _MyOwnTrap
    223 _MyOwnTrap:
    224 	.word	0xa000
    225 	rts
    226 
    227 
    228 /* Known RTS (for testing) -------------------------------------------------*/
    229 	.global _KnownRTS
    230 _KnownRTS:
    231 	.word	0xa001
    232 	rts
    233 #endif
    234 
    235 
    236 /* Allocate memory ---------------------------------------------------------*/
    237 ENTRY(NewPtr)
    238 	/*
    239 	 * int size
    240 	 */
    241 	movl	%sp@(4),%d0
    242 	.word	0xa71e		/* clear and sys */
    243 	rts
    244 
    245 
    246 /* Free memory -------------------------------------------------------------*/
    247 ENTRY(DisposPtr)
    248 	/*
    249 	 * Ptr ptr
    250 	 */
    251 	movl	%sp@(4),%a0
    252 	.word	0xa01f
    253 	rts
    254 
    255 
    256 /* Get size of allocated memory --------------------------------------------*/
    257 ENTRY(GetPtrSize)
    258 	/*
    259 	 * Ptr ptr
    260 	 */
    261 	movl	%sp@(4),%a0
    262 	.word	0xa021
    263 	rts
    264 
    265 
    266 /* Extend allocated memory -------------------------------------------------*/
    267 ENTRY(SetPtrSize)
    268 	/*
    269 	 * Ptr ptr
    270 	 * int bytesdiff
    271 	 */
    272 	movl	%sp@(4),%a0
    273 	movl	%sp@(8),%d0
    274 	.word	0xa020
    275 	rts
    276 
    277 
    278 /* Resource manager */
    279 	.data
    280 GLOBAL(mrg_ResErr)
    281 	.word	0
    282 
    283 	.text
    284 /* Return the current Resource Manager Error -------------------------------*/
    285 ENTRY(ResError)
    286 	/*
    287 	 * void
    288 	 */
    289 	movl	%d2,%sp@-		| Toolbox trap may alter %d0-%d2,%a0,%a1
    290 					| but C caller would save %d1,%a0,%a1
    291 	clrw	%sp@-			| space for return arg (ugh)
    292 	.word	0xa9af			| ResError
    293 	movw	%sp@+,%d0
    294 	movl	%sp@+,%d2		| restore %d2
    295 	rts
    296 
    297 ENTRY(mrg_ResError)
    298 	/*
    299 	 * %sp@(4)	:short
    300 	 */
    301 #if defined(MRG_SHOWTRAPS)
    302 		movml	#0xc0c0,%sp@-
    303 		pea	LRE_enter
    304 		jbsr	_C_LABEL(printf)
    305 		addql	#4,%sp
    306 		movml	%sp@+,#0x0303
    307 #endif
    308 	movw	_C_LABEL(mrg_ResErr),%sp@(4)
    309 	| movw	%d0,%sp@(4)
    310 	pascalret(0)
    311 
    312 LRE_enter:
    313 	.asciz	"mrg: ResError()\n"
    314 	.even
    315 
    316 /* Find a resource in open resource files ----------------------------------*/
    317 ENTRY(GetResource)
    318 	/*
    319 	 * sp@(4)	u_int theType
    320 	 * sp@(8)	short theID
    321 	 */
    322 	movl	%sp@(8),%a1
    323 	movl	%sp@(4),%a0
    324 	movl	%d2,%sp@-		| Toolbox trap may alter %d0-%d2,%a0,%a1
    325 					| but C caller would save %d1,%a0,%a1
    326 	clrl	%sp@-			| space for :Handle
    327 	movl	%a0,%sp@-
    328 	movw	%a1,%sp@-		| pascal parameters upside down
    329 	.word	0xa9a0			| GetResource
    330 	movl	%sp@+,%d0		| return Handle
    331 	movl	%sp@+,%d2		| restore registers
    332 	rts
    333 
    334 ENTRY(mrg_GetResource)
    335 	/*
    336 	 * sp@(10)	:Handle
    337 	 * sp@(6)	u_int	theType
    338 	 * sp@(4)	short	theID
    339 	 */
    340 	/* For now, we return NIL, because, well, we have no resources. */
    341 #if defined(MRG_SHOWTRAPS)
    342 		movml	#0xc0c0,%sp@-
    343 		movw	%sp@(20),%d0
    344 		movl	%sp@(22),%d1
    345 		movl	%d0,%sp@-
    346 		movl	%d1,%sp@-
    347 		pea	LGR_enter
    348 		jbsr	_C_LABEL(printf)
    349 		addl	#12,%sp
    350 		movml	%sp@+,#0x0303
    351 #endif
    352 	clrl	%d0			| okay to change %d0 ?
    353 	movl	%d0,%sp@(10)		| return value is NIL
    354 	movl	#-192,%d0		| resNotFound; that's pretty accurate.
    355 	movw	%d0,_C_LABEL(mrg_ResErr)| set current ResMan error
    356 	pascalret(6)			| I hate Pascal.
    357 
    358 
    359 
    360 ENTRY(mrg_CountResources)
    361 /* Original from WRU: 960120
    362  * sp@(4)	u_int32_t  rsrc_type
    363  * sp@(8)	u_int16_t  nr_of_rsrcs
    364  */
    365 	movl 	%sp@(4),%d0
    366   	movl	%d0,%sp@-
    367 	jbsr	_C_LABEL(Count_Resources)
    368 	addl	#4,%sp			| pop C params
    369 	movw	%d0,%sp@(8)		| store result
    370 	pascalret(4)
    371 
    372 ENTRY(mrg_GetIndResource)
    373 /* Original from WRU: 960120
    374  * sp@(4)	u_int16_t  rsrc_index
    375  * sp@(6)	u_int32_t  rsrc_type
    376  * sp@(10)	void *  *rsrc_handle
    377  */
    378 	movl	%sp@(6),%a0
    379 	clrl	%d0
    380 	movw	%sp@(4),%d0
    381   	movl	%d0,%sp@-
    382 	movl	%a0,%sp@-
    383 	jbsr	_C_LABEL(Get_Ind_Resource)
    384 	addl	#8,%sp		| pop C params
    385 	movl	%d0,%sp@(10)	| store result
    386 	pascalret(6)
    387 
    388 /*
    389  * I'd like to take a moment here to talk about the calling convention
    390  * for ToolBox routines.  Inside Mac "Operating System Utilities,"
    391  * page 8-16, "About the Trap Manager," states that ToolBox routines
    392  * may alter %D0-%D2 and %A0-%A1.  However, a crucial bit of code in
    393  * ADBReInit on the Mac II, 0x40807834, does not save its own %D1 or %A1
    394  * before calling GetResource.	Therefore, it is imperative that our
    395  * MacBSD ToolBox trap handler save at least %D1, %D2, %A0, and %A1.  I
    396  * believe that the system uses %D0 in most places to hold the function's
    397  * return value, as in "movl	%sp@+,%d0", and so I don't think it's
    398  * that necessary to save %d0 unless we find a specific case of ugliness.
    399  *
    400  * It surprises me during every moment that I deal with the Macintosh
    401  * architecture how wonderful and ugly it really is.  I continue to find
    402  * pieces of beautiful, elegant code, reduced to crap by another following
    403  * piece of code which uses global offsets, doesn't save registers, and
    404  * makes assumptions.  If only it was consistent, Mac ROMs would be a
    405  * true example to programmers everywhere.  As it stands, it is an example
    406  * of a different kind. 	-Brad Grantham, September 5th, 1994
    407  */
    408 
    409 LGR_enter:
    410 	.asciz	"GetResource('0x%x', %d)\n"
    411 	.even
    412 
    413 
    414 /*
    415  * 1010 line emulator; A-line trap
    416  * (we fake MacOS traps from here)
    417  */
    418 	.global _C_LABEL(mrg_aline_super)
    419 	.global _C_LABEL(mrg_ToolBoxtraps)
    420 ENTRY_NOPROFILE(alinetrap)
    421 	clrl	%sp@-		| pad %SR to longword (I still don't know
    422 				| why we do this.)
    423 	moveml	#0xffff,%sp@-	| save registers
    424 	movl	%sp,%sp@-	| save pointer to frame
    425 	movw	%sp@(FR_HW + 4),%d0	| retrieve status register
    426 	andw	#PSL_S,%d0	| supervisor state?
    427 	bne	Lalnosup	| branch if supervisor
    428 	addql	#4,%sp		| pop frame ptr
    429 	movql	#T_ILLINST,%d0	| user-mode fault
    430 	jra	_ASM_LABEL(fault)
    431 Lalnosup:
    432 #define FR_PC (FR_HW+2)
    433 	movl	%sp@(FR_PC + 4),%a0	| retrieve PC
    434 	movw	%a0@,%d0 	| retrieve trap word
    435 	btst	#11,%d0 	| ToolBox trap?
    436 	bne	Laltoolbox	| branch if ToolBox
    437 	jbsr	_C_LABEL(mrg_aline_super) | supervisor a-line trap
    438 Lalrts:
    439 	addql	#4,%sp		| pop frame ptr
    440 	movw	%sp@(FR_HW),%sr	| restore status register (I hate MacOS traps)
    441 	movl	%sp@(FR_PC),%a0	| move PC to correct location
    442 	movl	%a0,%sp@(FR_PC+2)
    443 	moveml	%sp@+,#0xffff	| restore registers (some of which may have
    444 				| been magically changed)
    445 	addql	#8,%sp		| pop alignment long, make stack look like
    446 				| ordinary jbsr
    447 	tstw	%d0		| Gotta do this because call might depend on it
    448 	rts			| Go home (God, this is ugly.)
    449 Laltoolbox:
    450 	addql	#4,%sp		| pop frame ptr
    451 #if defined(MRG_DEBUG)
    452 		movml	#0xC0C0,%sp@-	| better save
    453 		pea	LalP1
    454 		jbsr	_C_LABEL(printf)
    455 			| printf ("Toolbox trap\n");
    456 		lea	%sp@(4),%sp	| pop
    457 		movml	%sp@+,#0x0303	| restore
    458 #endif
    459 	movl	%a0,%a1		| save PC
    460 	movw	%sp@(FR_HW),%sr	| restore status register
    461 #if defined(MRG_DEBUG)
    462 		movml	#0xC0C0,%sp@-	| better save
    463 		movw	%sr,%sp@-
    464 		clrw	%sp@-		| coerce to int
    465 		pea	LalP2
    466 		jbsr	_C_LABEL(printf)
    467 			| printf ("Status register 0x%x\n", sr);
    468 		lea	%sp@(8),%sp	| pop
    469 		movml	%sp@+,#0x0303	| restore
    470 #endif
    471 	btst	#10,%d0 	| auto-pop the jump address?
    472 	beq	Lalnoauto	| branch if no auto-pop
    473 	pea	Lalautopanic	| I really don't know how to handle this
    474 	jbsr	_C_LABEL(panic)
    475 Lalnoauto:
    476 	addl	#2,%a1		| add 2 to PC
    477 #if defined(MRG_DEBUG)
    478 		movml	#0xC0C0,%sp@-	| better save
    479 		movl	%a1,%sp@-
    480 		pea	LalP4
    481 		jbsr	_C_LABEL(printf)
    482 			| printf ("return address is 0x%x\n", new pc);
    483 		lea	%sp@(8),%sp	| pop
    484 		movml	%sp@+,#0x0303	| restore
    485 #endif
    486 	movl	%a1,%sp@(FR_PC+2)	| push new return address
    487 	movl	%d0,%d1		| just in case of panic
    488 	andl	#0x3ff,%d0	| %d0 = trap number
    489 #if defined(MRG_DEBUG)
    490 		movml	#0xC0C0,%sp@-	| better save
    491 		movl	%d0,%sp@-
    492 		pea	LalP5
    493 		jbsr	_C_LABEL(printf)
    494 			| printf ("trap number is 0x%x\n", trapnum);
    495 		lea	%sp@(8),%sp	| pop
    496 		movml	%sp@+,#0x0303	| restore
    497 #endif
    498 	lsll	#2,%d0		| ptr = 4 bytes
    499 	lea	_C_LABEL(mrg_ToolBoxtraps),%a0
    500 	addl	%d0,%a0		| get trap address
    501 	movl	%a0@,%a0
    502 	bne	Laltbok 	| branch on trap addr non-zero
    503 	movl	%d1,%sp@+	| trap word
    504 	pea	Laltbnotrap
    505 	jbsr	_C_LABEL(printf)
    506 	pea	Laltbnogo
    507 	jbsr	_C_LABEL(panic)
    508 Laltbok:
    509 #if defined(MRG_DEBUG)
    510 		movml	#0xC0C0,%sp@-	| better save
    511 		movl	%a0,%sp@-
    512 		pea	LalP6
    513 		jbsr	_C_LABEL(printf)
    514 			| printf ("trap address is 0x%x\n", trapaddr);
    515 		lea	%sp@(8),%sp	| pop
    516 		movml	%sp@+,#0x0303	| restore
    517 #endif
    518 	movl	%a0,%sp@(FR_HW)	| we will RTS to trap routine (ick)
    519 	moveml	%sp@+,#0xffff	| restore registers
    520 	addql	#4,%sp		| pop alignment long
    521 	rts			| go for it
    522 
    523 Lalautopanic:
    524 	.asciz	"mrg: A-line ToolBox trap wanted auto-pop; I don't know how"
    525 Laltbnotrap:
    526 	.asciz	"mrg: Don't know how to handle this trap: 0x%x\n"
    527 Laltbnogo:
    528 	.asciz	"mrg: can't go on"
    529 LalP1:
    530 	.asciz	"mrg: TB!"
    531 LalP2:
    532 	.asciz	" sr 0x%x"
    533 LalP4:
    534 	.asciz	" ret 0x%x"
    535 LalP5:
    536 	.asciz	" #%d"
    537 LalP6:
    538 	.asciz	" addr 0x%x\n"
    539 	.even
    540 
    541 
    542 	.data
    543 
    544 GLOBAL(traceloopstart)
    545 	.space	20 * 4		| save last 20 program counters on trace trap
    546 GLOBAL(traceloopend)
    547 GLOBAL(traceloopptr)
    548 	.long	_C_LABEL(traceloopstart)
    549 
    550 	.text
    551 ENTRY_NOPROFILE(mrg_tracetrap)
    552 	movl	%d0,%sp@-		| save %d0
    553 	movl	%a0,%sp@-		| save %a0
    554 	movl	%sp@(0x10),%d0		| address of instruction
    555 		|%sp@	 old %a0
    556 		|%sp@(4) old %d0
    557 		|%sp@(8) old %sr
    558 		|%sp@(10) old %PC
    559 		|%sp@(14) exception vector
    560 		|%sp@(16) address of instruction
    561 #if defined(MRG_FOLLOW)
    562 		movml	#0xc0c0,%sp@-
    563 		movl	%d0,%sp@-
    564 		pea	Ltraceprint
    565 		jbsr	_C_LABEL(printf) | printf("PC is %x\n", pc);
    566 		addql	#8,%sp
    567 		movml	%sp@+,#0x0303
    568 		tstl	%d0
    569 #endif
    570 	beq	LPCiszero		| if PC goes to zero, freak!
    571 	movl	_C_LABEL(traceloopptr),%a0	| ptr = traceloopptr;
    572 	movl	%d0,%a0@+		| *ptr++ = PC;
    573 	cmpl	#_C_LABEL(traceloopend),%a0	| if(ptr == traceloopend)
    574 	bne	Lnotpast		|  {
    575 	movl	#_C_LABEL(traceloopstart),%a0	|   ptr = traceloopstart;
    576 Lnotpast:				|  }
    577 	movl	%a0,_C_LABEL(traceloopptr)	| traceloopptr = ptr;
    578 	movl	%sp@+,%a0		| restore %a0
    579 	movl	%sp@+,%d0		| restore %d0
    580 	rte				| everything cool, return.
    581 LPCiszero:
    582 	movl	%sp@+,%a0		| restore %a0
    583 	movl	%sp@+,%d0		| restore %d0
    584 	movml	#0xc0c0,%sp@-
    585 	pea	LtracePCzero
    586 	jbsr	_C_LABEL(panic)		| panic("PC is zero!", pc);
    587 	addql	#4,%sp
    588 	movml	%sp@+,#0x0303
    589 
    590 Ltraceprint:
    591 	.asciz	"tracing, pc at 0x%08x\n"
    592 LtracePCzero:
    593 	.asciz	"PC went to zero!\n"
    594 	.even
    595