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