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 */ 146ENTRY(InitUtil) 147 .word 0xa03f 148 rts 149 150 151/* Initialize the ADB ------------------------------------------------------*/ 152 /* 153 * void 154 */ 155ENTRY(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 */ 165ENTRY(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 */ 176ENTRY(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 */ 186ENTRY(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 */ 198ENTRY(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 */ 212ENTRY(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 ---------------------------------------------------------*/ 237ENTRY(NewPtr) 238 /* 239 * int size 240 */ 241 movl %sp@(4),%d0 242 .word 0xa71e /* clear and sys */ 243 rts 244 245 246/* Free memory -------------------------------------------------------------*/ 247ENTRY(DisposPtr) 248 /* 249 * Ptr ptr 250 */ 251 movl %sp@(4),%a0 252 .word 0xa01f 253 rts 254 255 256/* Get size of allocated memory --------------------------------------------*/ 257ENTRY(GetPtrSize) 258 /* 259 * Ptr ptr 260 */ 261 movl %sp@(4),%a0 262 .word 0xa021 263 rts 264 265 266/* Extend allocated memory -------------------------------------------------*/ 267ENTRY(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 280GLOBAL(mrg_ResErr) 281 .word 0 282 283 .text 284/* Return the current Resource Manager Error -------------------------------*/ 285ENTRY(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 297ENTRY(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 312LRE_enter: 313 .asciz "mrg: ResError()\n" 314 .even 315 316/* Find a resource in open resource files ----------------------------------*/ 317ENTRY(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 334ENTRY(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 360ENTRY(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 372ENTRY(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 409LGR_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) 420ENTRY_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) 431Lalnosup: 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 438Lalrts: 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.) 449Laltoolbox: 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) 475Lalnoauto: 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) 508Laltbok: 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 523Lalautopanic: 524 .asciz "mrg: A-line ToolBox trap wanted auto-pop; I don't know how" 525Laltbnotrap: 526 .asciz "mrg: Don't know how to handle this trap: 0x%x\n" 527Laltbnogo: 528 .asciz "mrg: can't go on" 529LalP1: 530 .asciz "mrg: TB!" 531LalP2: 532 .asciz " sr 0x%x" 533LalP4: 534 .asciz " ret 0x%x" 535LalP5: 536 .asciz " #%d" 537LalP6: 538 .asciz " addr 0x%x\n" 539 .even 540 541 542 .data 543 544GLOBAL(traceloopstart) 545 .space 20 * 4 | save last 20 program counters on trace trap 546GLOBAL(traceloopend) 547GLOBAL(traceloopptr) 548 .long _C_LABEL(traceloopstart) 549 550 .text 551ENTRY_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; 576Lnotpast: | } 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. 581LPCiszero: 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 590Ltraceprint: 591 .asciz "tracing, pc at 0x%08x\n" 592LtracePCzero: 593 .asciz "PC went to zero!\n" 594 .even 595