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