1 /* $NetBSD: macromasm.s,v 1.23 2026/03/20 14:02:53 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 * 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 movl %sp@(FR_PC + 4),%a0 | retrieve PC 433 movw %a0@,%d0 | retrieve trap word 434 btst #11,%d0 | ToolBox trap? 435 bne Laltoolbox | branch if ToolBox 436 jbsr _C_LABEL(mrg_aline_super) | supervisor a-line trap 437 Lalrts: 438 addql #4,%sp | pop frame ptr 439 movw %sp@(FR_HW),%sr | restore status register (I hate MacOS traps) 440 movl %sp@(FR_PC),%a0 | move PC to correct location 441 movl %a0,%sp@(FR_PC+2) 442 moveml %sp@+,#0xffff | restore registers (some of which may have 443 | been magically changed) 444 addql #8,%sp | pop alignment long, make stack look like 445 | ordinary jbsr 446 tstw %d0 | Gotta do this because call might depend on it 447 rts | Go home (God, this is ugly.) 448 Laltoolbox: 449 addql #4,%sp | pop frame ptr 450 #if defined(MRG_DEBUG) 451 movml #0xC0C0,%sp@- | better save 452 pea LalP1 453 jbsr _C_LABEL(printf) 454 | printf ("Toolbox trap\n"); 455 lea %sp@(4),%sp | pop 456 movml %sp@+,#0x0303 | restore 457 #endif 458 movl %a0,%a1 | save PC 459 movw %sp@(FR_HW),%sr | restore status register 460 #if defined(MRG_DEBUG) 461 movml #0xC0C0,%sp@- | better save 462 movw %sr,%sp@- 463 clrw %sp@- | coerce to int 464 pea LalP2 465 jbsr _C_LABEL(printf) 466 | printf ("Status register 0x%x\n", sr); 467 lea %sp@(8),%sp | pop 468 movml %sp@+,#0x0303 | restore 469 #endif 470 btst #10,%d0 | auto-pop the jump address? 471 beq Lalnoauto | branch if no auto-pop 472 pea Lalautopanic | I really don't know how to handle this 473 jbsr _C_LABEL(panic) 474 Lalnoauto: 475 addl #2,%a1 | add 2 to PC 476 #if defined(MRG_DEBUG) 477 movml #0xC0C0,%sp@- | better save 478 movl %a1,%sp@- 479 pea LalP4 480 jbsr _C_LABEL(printf) 481 | printf ("return address is 0x%x\n", new pc); 482 lea %sp@(8),%sp | pop 483 movml %sp@+,#0x0303 | restore 484 #endif 485 movl %a1,%sp@(FR_PC+2) | push new return address 486 movl %d0,%d1 | just in case of panic 487 andl #0x3ff,%d0 | %d0 = trap number 488 #if defined(MRG_DEBUG) 489 movml #0xC0C0,%sp@- | better save 490 movl %d0,%sp@- 491 pea LalP5 492 jbsr _C_LABEL(printf) 493 | printf ("trap number is 0x%x\n", trapnum); 494 lea %sp@(8),%sp | pop 495 movml %sp@+,#0x0303 | restore 496 #endif 497 lsll #2,%d0 | ptr = 4 bytes 498 lea _C_LABEL(mrg_ToolBoxtraps),%a0 499 addl %d0,%a0 | get trap address 500 movl %a0@,%a0 501 bne Laltbok | branch on trap addr non-zero 502 movl %d1,%sp@+ | trap word 503 pea Laltbnotrap 504 jbsr _C_LABEL(printf) 505 pea Laltbnogo 506 jbsr _C_LABEL(panic) 507 Laltbok: 508 #if defined(MRG_DEBUG) 509 movml #0xC0C0,%sp@- | better save 510 movl %a0,%sp@- 511 pea LalP6 512 jbsr _C_LABEL(printf) 513 | printf ("trap address is 0x%x\n", trapaddr); 514 lea %sp@(8),%sp | pop 515 movml %sp@+,#0x0303 | restore 516 #endif 517 movl %a0,%sp@(FR_HW) | we will RTS to trap routine (ick) 518 moveml %sp@+,#0xffff | restore registers 519 addql #4,%sp | pop alignment long 520 rts | go for it 521 522 Lalautopanic: 523 .asciz "mrg: A-line ToolBox trap wanted auto-pop; I don't know how" 524 Laltbnotrap: 525 .asciz "mrg: Don't know how to handle this trap: 0x%x\n" 526 Laltbnogo: 527 .asciz "mrg: can't go on" 528 LalP1: 529 .asciz "mrg: TB!" 530 LalP2: 531 .asciz " sr 0x%x" 532 LalP4: 533 .asciz " ret 0x%x" 534 LalP5: 535 .asciz " #%d" 536 LalP6: 537 .asciz " addr 0x%x\n" 538 .even 539 540 541 .data 542 543 GLOBAL(traceloopstart) 544 .space 20 * 4 | save last 20 program counters on trace trap 545 GLOBAL(traceloopend) 546 GLOBAL(traceloopptr) 547 .long _C_LABEL(traceloopstart) 548 549 .text 550 ENTRY_NOPROFILE(mrg_tracetrap) 551 movl %d0,%sp@- | save %d0 552 movl %a0,%sp@- | save %a0 553 movl %sp@(0x10),%d0 | address of instruction 554 |%sp@ old %a0 555 |%sp@(4) old %d0 556 |%sp@(8) old %sr 557 |%sp@(10) old %PC 558 |%sp@(14) exception vector 559 |%sp@(16) address of instruction 560 #if defined(MRG_FOLLOW) 561 movml #0xc0c0,%sp@- 562 movl %d0,%sp@- 563 pea Ltraceprint 564 jbsr _C_LABEL(printf) | printf("PC is %x\n", pc); 565 addql #8,%sp 566 movml %sp@+,#0x0303 567 tstl %d0 568 #endif 569 beq LPCiszero | if PC goes to zero, freak! 570 movl _C_LABEL(traceloopptr),%a0 | ptr = traceloopptr; 571 movl %d0,%a0@+ | *ptr++ = PC; 572 cmpl #_C_LABEL(traceloopend),%a0 | if(ptr == traceloopend) 573 bne Lnotpast | { 574 movl #_C_LABEL(traceloopstart),%a0 | ptr = traceloopstart; 575 Lnotpast: | } 576 movl %a0,_C_LABEL(traceloopptr) | traceloopptr = ptr; 577 movl %sp@+,%a0 | restore %a0 578 movl %sp@+,%d0 | restore %d0 579 rte | everything cool, return. 580 LPCiszero: 581 movl %sp@+,%a0 | restore %a0 582 movl %sp@+,%d0 | restore %d0 583 movml #0xc0c0,%sp@- 584 pea LtracePCzero 585 jbsr _C_LABEL(panic) | panic("PC is zero!", pc); 586 addql #4,%sp 587 movml %sp@+,#0x0303 588 589 Ltraceprint: 590 .asciz "tracing, pc at 0x%08x\n" 591 LtracePCzero: 592 .asciz "PC went to zero!\n" 593 .even 594