Date: Mon, 6 Mar 1995 15:36:53 -0800 (PST) From: Chris Larson Subject: RegisterSafeFat.cpt.hqx : Code resource Rez template Attached is the Rez source for a template, similar to the 'sdes' template, which allows the construction of safe, fat code resoruces with register-based calling conventions. Moderators: This probably belongs in dev/src. Feel free to include this on any CD you see fit. --Chris Chris Larson -- Amateur Macintosh Geek, CoBase Research Assistant Internet: larson@kingston.cs.ucla.edu | Insert Disclaimer Here #include "MixedMode.r" /**************** RegisterSafeFat.r -- Chris Larson, 1995 Use this template to create a safe, fat resource. This template differs from that in MidexMode.r in that it allows the construction of resources containing code with register-based calling conventions. All registers are preserved but condition codes are not, so if your resource¹s entry point depends upon the condition codes, this template will not work. First, the address of _Unimplemented is retrieved. Then, the size of the toolbox trap table is determined according to the method in Inside Macintosh: Operating System Utilities, page 8-22 (Trap Manager chapter). If a small trap table is in use (pretty much meaning a Plus or SE with System 6), a 680x0 with no Mixed Mode Manager is assumed. If a large trap table exists, we check to see if _MixedModeMagic is implemented. If so, the routine descriptor is copied to the head of the resource. Otherwise, a branch instruction is installed at the top of the resource which points to the 680x0 code. Then, if _HWPriv is implemented, the instruction cache is flushed. The initial register contents are restored, and we branch (by means of RTS) to the top of the resource which now contains the routine descriptor or the branch instruction. This template has been tested on the following systems: (1) Power Macintosh 7100/80, System 7.5 (2) PowerBook 160, System 7.1 (with System Update 3.0) (3) Macintosh Plus, System 6.0.8 Use it in the same manner as you use the 'sdes' template (except, of course, this template is called 'Rdes' for Register sdes). ****************/ /* Safe Fat Resource Allowing Register-Based Calling Conventions */ type 'Rdes' { Top: hex string = $"48E7 E0C0" // Start: MOVEM.L D0-D2/A0/A1,-(A7) ; Save work registers. $"303C A89F" // MOVE.W #$A89F,D0 ; Move _Unimplemented trap word to D0. $"A746" // _GetToolBoxTrapAddress ; Get _Unimplemented¹s address. $"2F08" // MOVE.L A0,-(A7) ; Push the address onto the stack. $"303C A86E" // MOVE.W #$A86E,D0 ; Move _InitGraf trap word into D0. $"A746" // _GetToolBoxTrapAddress ; Get _InitGraf¹s address. $"2F08" // MOVE.L A0,-(A7) ; Push _InitGraf¹s address. $"303C AA6E" // MOVE.W #$AA6E,D0 ; Move the test trap word into D0. $"A746" // _GetToolBoxTrapAddress ; Get the test trap¹s address. $"B1DF" // CMPA.L (A7)+,A0 ; Is it the same as _InitGraf (and pop _InitGraf)? $"670A" // BEQ.S NoMixedMode ; Yup, small trap tables: assume 680x0, no Mixed Mode. $"303C AAFE" // MOVE.W #$AAFE,D0 ; Move _MixedModeMagic trap word into D0. $"A746" // _GetToolBoxTrapAddress ; Get _MixedModeMagic¹s address. $"B1D7" // CMPA.L (A7),A0 ; Is _MixedModeMagic implemented? $"6616" // BNE.S HasMixedMode ; Yup, install the routine descriptor. $"41FA FFD6" // NoMixedMode: LEA Start,A0 ; Get the address of Start into A0. $"30FC 6000" // MOVE.W #$6000,(A0)+ ; Install the bra.w opcode. $"43FA 0034" // LEA TheRD,A1 ; Load routine descriptor address into A1. $"2029 0014" // MOVE.L $0014(A1),D0 ; Move the displacement to 680x0 code (from Start) to D0. $"5540" // SUBQ.W #$2,D0 ; Correct displacement for length of bra.w opcode. $"3080" // MOVE.W D0,(A0) ; Install branch displacement. $"6010" // BRA.S Done ; We¹re outa here. $"43FA FFC0" // HasMixedMode: LEA Start,A1 ; Load Start address into A1. $"41FA 0022" // LEA TheRD,A0 ; Load routine descriptor address into A0. $"203C 0000 0034" // MOVE.L #$34,D0 ; Size of routine descriptor to D0. $"A22E" // _BlockMoveData ; Install routine descriptor (don¹t flush cache yet). $"303C A198" // Done: MOVE.W #$A198,D0 ; Move _HWPriv trap word into D0. $"A346" // _GetOSTrapAddress ; Get _HWPriv¹s address. $"B1DF" // CMPA.L (A7)+,A0 ; Is _HWPriv implemented (and pop _Unimplemented)? $"6704" // BEQ.S NoCache ; Nope, skip the cache flush. $"7001 A198" // _FlushInstructionCache ; Flush I-Cache so our modifications work. $"4CDF 0307" // NoCache: MOVEM.L (A7)+,D0-D2/A0/A1 ; Restore the work registers. $"487A FF9E" // PEA Start ; Push the address to jump to (so we can RTS to it). $"4E75"; // RTS ; Jump to Start (now containing RD or bra.w). // TheRD: /* Routine Descriptor */ GoMixedModeTrapType = _MixedModeMagic; VersionType = kRoutineDescriptorVersion; fill bit [7]; SelectorsAreIndexableType = FALSE; Reserved1Type; Reserved2Type; SelectorInfoType = 0; RoutineCountType = 1; /* Routine Record For 680x0 Code */ ProcInfoType; Reserved3Type; ISAType = kM68kISA; fill bit [11]; RoutineIsDispatchedDefaultType = FALSE; DontPassSelectorType = FALSE; UseNativeISAType = TRUE; FragmentNeedsPreparingType = FALSE; ProcDescriptorIsRelativeType = TRUE; ProcDescriptorType = ( Start680x0 - Top ) / 8; Reserved4Type; SelectorType = 0; /* Routine Record For PPC Code */ ProcInfoType; Reserved3Type; ISAType = kPowerPCISA; fill bit [11]; RoutineIsDispatchedDefaultType = FALSE; DontPassSelectorType = FALSE; UseNativeISAType = TRUE; FragmentNeedsPreparingType = TRUE; ProcDescriptorIsRelativeType = TRUE; ProcDescriptorType = ( StartPPC - Top ) / 8; Reserved4Type; SelectorType = 0; Align LONG; Start680x0: hex string; // The 680x0 code starts here Align LONG; StartPPC: hex string; // The PEF container starts here };