page@swan.ulowell.edu (Bob Page) (02/04/89)
Submitted-by: cbmvax!daveh (Dave Haynie) Posting-number: Volume 89, Issue 18 Archive-name: hardware/setcpu13.1 # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # SetCPU.c # 030Stuff.a # makefile # SetCPU.uu # This archive created: Mon Jan 30 19:18:27 1989 cat << \SHAR_EOF > SetCPU.c /* SetCPU V1.3 by Dave Haynie (released to the public domain) MAIN PROGRAM This program tells which Motorola CPU is in place, and allows the some cache control on 68020 and 68030 machines. It also sets up the ExecBase->AttnFlags with 68030 information, so that any subsequent program can use the standard methods to identify if the system is a 68030 system. The program now defaults to WALLOC mode for '030 data cache, since that's the proper mode for Amiga data caches (user and supervisor modes share data). I now check for the existence of an MMU, and allow for testing of different CPUs, for use in CLI scripts and that kind of thing. Apparently some 68020 boards out there don't fully decode CPU space addresses, and, as a result, their math chip shows up in all 8 coprocessor slots. This makes the MMU test hang, since instead of getting no MMU, I get instead an FPU responding to an MMU instruction, which will probably hang the system. The "NOMMUTEST" option allows for the rest of this program to work on such a board. */ #include <exec/types.h> #include <exec/execbase.h> #include <exec/nodes.h> #include <exec/interrupts.h> #include <functions.h> #include <stdio.h> /* Define a few flags missing from AmigaOS 1.2 */ #define AFB_68030 2L #define AFF_68030 (1L<<2) /* Define all CACR bit components, not all are actually used here. */ #define CACR_INST (1L<<0) #define CACR_DATA (1L<<8) #define CACR_WALLOC 5 #define CACR_BURST 4 #define CACR_CLEAR 3 #define CACR_ENTRY 2 #define CACR_FREEZE 1 #define CACR_ENABLE 0 /* ====================================================================== */ /* Some external declarations. */ void SetCACR(); ULONG GetCACR(), GetCPUType(), GetMMUType(), GetFPUType(); /* Checking array */ #define CK68000 0 #define CK68010 1 #define CK68020 2 #define CK68030 3 #define CK68851 4 #define CK68881 5 #define CK68882 6 #define CHECKS 7 struct checker { LONG item; BOOL tag; }; struct checker checks[CHECKS] = { { 68000L, FALSE }, { 68010L, FALSE }, { 68020L, FALSE }, { 68030L, FALSE }, { 68851L, FALSE }, { 68881L, FALSE }, { 68882L, FALSE } }; USHORT code = 0L; /* Program return code */ /* ====================================================================== */ /* This replaces the Lattice "stricmp()" function, plus it's a better form for my needs here. */ BOOL striequ(s1,s2) char *s1,*s2; { while (*s1 && *s2 && (*s1++ & 0xdf) == (*s2++ & 0xdf)); return (BOOL) (!*s1 && (*s1 & 0xdf) == (*s2 & 0xdf)); } /* This routine prints FPU codes and sets things accordingly. */ void PrintFPU(fpu) ULONG fpu; { if (fpu == 68881L) { printf("68881 "); if (checks[CK68881].item) code = 0; } else if (fpu == 68882L) { printf("68882 "); if (checks[CK68882].item) code = 0; } } /* This be the main program. */ void main(argc,argv) int argc; char *argv[]; { BOOL worked, dommutest = TRUE; ULONG cacr,op,mode,test,cpu,fpu,mmu = 0; USHORT i,j; /* If they're just asking for help */ if (argc >= 2 && argv[1][0] == '?') { printf("\2337mSetCPU 1.3 by Dave Haynie\2330m\n"); printf("Usage: SetCPU [INST|DATA] [[NO]CACHE|[NO]BURST] [NOMMUTEST]\n"); printf(" [CHECK 68000|68010|68020|68030|68851|68881|68882]\n"); exit(0); } /* Now we parse the command line. The default cache operation acts on both data and instruction caches. The way all the cache control functions are defined, they're just NOPs on machines without the appropriate caches. */ mode = CACR_INST | CACR_DATA; cacr = GetCACR(); if (argc > 1) { for (i = 1; i < argc; ++i) { if (striequ(argv[i],"CHECK")) { code = 5; while (argv[++i][0]=='6' && argv[i][1]=='8' && strlen(argv[i])==5) { worked = FALSE; sscanf(argv[i],"%ld",&test); for (j = 0; j < CHECKS; ++j) if (checks[j].item == test) { checks[j].tag = TRUE; worked = TRUE; } if (!worked) { printf("Error: Illegal Check Parameter \"%s\"\n",argv[i]); exit(10); } } } if (striequ(argv[i],"NOMMUTEST")) { dommutest = FALSE; ++i; } if (striequ(argv[i],"DATA")) { mode = CACR_DATA; ++i; } if (striequ(argv[i],"INST")) { mode = CACR_INST; ++i; } if (striequ(argv[i],"CACHE") || striequ(argv[i],"NOCACHE")) op = mode << CACR_ENABLE; else if (striequ(argv[i],"BURST") || striequ(argv[i],"NOBURST")) op = mode << CACR_BURST; else { if (argv[i][0] == 0) continue; printf("Error: Illegal Cache Parameter \"%s\"\n",argv[i]); exit(10); } argv[i][2] = '\0'; if (striequ(argv[i],"NO")) cacr &= ~op; else cacr |= op; } /* We ALWAYs want to be in Word Allocate mode, AmigaOS won't run otherwise. */ SetCACR(cacr | CACR_DATA << CACR_WALLOC); } /* Let's find out what we have */ cpu = GetCPUType(); fpu = GetFPUType(); if (dommutest) mmu = GetMMUType(); printf("SYSTEM: "); /* If they're not on a 68020/68030, we can't set anything. For compatibility across systems, I don't consider a cache setting request an error, just ignore it. */ if (cpu <= 68010L) { if (cpu == 68010L) { printf("68010 "); if (checks[CK68010].item) code = 0; } else { printf("68000 "); if (checks[CK68000].item) code = 0; } PrintFPU(fpu); printf("\n"); exit(code); } /* Now we're on a 32 bit system. But EXEC doesn't know which. If you run SetCPU on a 68030 system once, the '030 flag's set, otherwise, we'll test for it. */ if (cpu == 68030L) { printf("68030 "); if (checks[CK68030].item) code = 0; } else { printf("68020 "); if (checks[CK68020].item) code = 0; } PrintFPU(fpu); if (mmu == 68851L) { printf("68851 "); if (checks[CK68851].item) code = 0; } /* We always print the results, even if nothing has changed. */ cacr = GetCACR(); printf("(INST: "); if (!(cacr & (CACR_INST << CACR_ENABLE))) printf("NO"); printf("CACHE"); if (cpu == 68030L) { printf(" "); if (!(cacr & (CACR_INST << CACR_BURST))) printf("NO"); printf("BURST) (DATA: "); if (!(cacr & (CACR_DATA << CACR_ENABLE))) printf("NOCACHE "); else printf("CACHE "); if (!(cacr & (CACR_DATA << CACR_BURST))) printf("NO"); printf("BURST"); } printf(")\n"); /* For safety's sake, or personal paranoia, or whatever, I dump the data cache before I go away. */ if (cpu = 68030L) SetCACR(cacr|(CACR_DATA << CACR_CLEAR)); exit(code); } SHAR_EOF cat << \SHAR_EOF > 030Stuff.a ;====================================================================== ; ; SetCPU V1.3 ; by Dave Haynie (released to the public domain) ; ; 68030 Assembly Function Module ; ; This module contains functions that access the 68030 cache ; and run a few tests. ; ;====================================================================== ;====================================================================== ; ; Macros & constants used herein... ; ;====================================================================== CALLSYS macro * jsr LVO\1(A6) endm CIB_ENABLE EQU 0 CIB_FREEZE EQU 1 CIB_ENTRY EQU 2 CIB_CLEAR EQU 3 CIB_BURST EQU 4 CDB_ENABLE EQU 8 CDB_FREEZE EQU 9 CDB_ENTRY EQU 10 CDB_CLEAR EQU 11 CDB_BURST EQU 12 CDB_WALLOC EQU 13 AFB_68030 EQU 2 ATNFLGS EQU $129 LVOSupervisor EQU -30 LVOFindTask EQU -294 LVOAllocTrap EQU -342 LVOFreeTrap EQU -348 ;====================================================================== ; ; Need just a little more stuff ; ;====================================================================== NOLIST include "exec/execbase.i" include "exec/tasks.i" LIST machine mc68020 mc68881 cseg public _GetCACR public _SetCACR public _GetMMUType public _GetCPUType public _GetFPUType ;====================================================================== ; ; This function returns the 68020/68030 CACR register. It assumes ; a 68020 or 68030 based system. ; ; ULONG GetCACR() ; ;====================================================================== _GetCACR: move.l 4,a6 ; Get ExecBase btst.b #AFB_68020,ATNFLGS(a6) ; Does the OS think an '020 is here? bne 1$ moveq.l #0,d0 ; No CACR here, pal rts 1$ move.l a5,-(sp) ; Save this register lea 2$,a5 ; Get the start of the supervisor code CALLSYS Supervisor move.l (sp)+,a5 ; Give back registers rts 2$ movec cacr,d0 ; Make CACR the return value rte ;====================================================================== ; ; This function sets the value of the 68020/68030 CACR register. ; It assumes a 68020 or 68030 based system. ; ; void SetCACR(cacr) ; ULONG cacr; ; ;====================================================================== _SetCACR: move.l 4(sp),d0 ; New CACR is on stack move.l 4,a6 ; Get ExecBase btst.b #AFB_68020,ATNFLGS(a6) ; Does the OS think an '020 is here? bne 1$ rts ; No CACR here, pal 1$ move.l a5,-(sp) ; Save this register lea 2$,a5 ; Get the start of the supervisor code CALLSYS Supervisor move.l (sp)+,a5 ; Give back register rts 2$ movec d0,cacr ; Set the CACR rte ;====================================================================== ; ; This function returns the type of the CPU in the system as a ; longword: 68000, 68010, 68020, or 68030. The testing must be done ; in reverse order, in that any higher CPU also has the bits set for ; a lower CPU. Also, since 1.3 doesn't recognize the 68030, if I ; find the 68020 bit set, I always check for the presence of a ; 68030. ; ; This routine should be the first test routine called under 1.2 ; and 1.3. ; ; ULONG GetCPUType(); ; ;====================================================================== _GetCPUType: movem.l a4/a5,-(sp) ; Save this register move.l 4,a6 ; Get ExecBase btst.b #AFB_68030,ATNFLGS(a6) ; Does the OS think an '030 is here? beq 0$ move.l #68030,d0 ; Sure does... movem.l (sp)+,a4/a5 rts 0$ btst.b #AFB_68020,ATNFLGS(a6) ; Maybe a 68020 bne 2$ btst.b #AFB_68010,ATNFLGS(a6) ; Maybe a 68010? bne 1$ move.l #68000,d0 ; Just a measley '000 movem.l (sp)+,a4/a5 rts 1$ move.l #68010,d0 ; Yup, we're an '010 movem.l (sp)+,a4/a5 rts 2$ move.l #68020,d0 ; Assume we're an '020 lea 3$,a5 ; Get the start of the supervisor code CALLSYS Supervisor movem.l (sp)+,a4/a5 rts 3$ movec cacr,d1 ; Get the cache register move.l d1,a4 ; Save it for a minute bset.l #CIB_BURST,d1 ; Set the inst burst bit bclr.l #CIB_ENABLE,d1 ; Clear the inst cache bit movec d1,cacr ; Try to set the CACR movec cacr,d1 btst.l #CIB_BURST,d1 ; Do we have a set burst bit? beq 4$ move.l #68030,d0 ; It's a 68030 bset.b #AFB_68030,ATNFLGS(a6) 4$ move.l a4,d1 ; Restore the original CACR movec d1,cacr rte ;====================================================================== ; ; This function returns 0L if the system contains no MMU, ; 68851L if the system does contain an 68851, or 68030L if the ; system contains a 68030. ; ; This routine seems to lock up on at least some CSA 68020 ; boards, though it runs just fine on those from Ronin and ; Commodore, as well as all 68030 boards it's been tested on. ; ; ULONG GetMMUType() ; ;====================================================================== _GetMMUType: move.l 4,a6 ; Get ExecBase movem.l a3/a4/a5,-(sp) ; Save this stuff move.l #0,a1 CALLSYS FindTask ; Call FindTask(0L) move.l d0,a3 move.l TC_TRAPCODE(a3),a4 ; Change the exception vector move.l #2$,TC_TRAPCODE(a3) subq.l #4,sp ; Let's try an MMU instruction dc.w $f017 ; Slimey PMOVE tc,(sp) dc.w $4200 cmpi #0,d0 ; Any MMU here? beq 1$ btst.b #AFB_68030,ATNFLGS(a6) ; Does the OS think an '030 is here? beq 1$ move.l #68030,d0 1$ addq.l #4,sp ; Return that local move.l a4,TC_TRAPCODE(a3) ; Reset exception stuff movem.l (sp)+,a3/a4/a5 ; and return the registers rts ; This is the exception code. No matter what machine we're on, ; we get an exception. If the MMU's in place, we should get a ; privilige violation; if not, an F-Line emulation exception. 2$ move.l (sp)+,d0 ; Get Amiga supplied exception # cmpi #11,d0 ; Is it an F-Line? beq 3$ ; If so, go to the fail routine move.l #68851,d0 ; We have MMU addq.l #4,2(sp) ; Skip the MMU instruction rte 3$ moveq.l #0,d0 ; It dinna woik, addq.l #4,2(sp) ; Skip the MMU instruction rte ;====================================================================== ; ; This function returns the type of the FPU in the system as a ; longword: 0 (no FPU), 68881, or 68882. ; ; ULONG GetFPUType(); ; ;====================================================================== _GetFPUType: move.l a5,-(sp) ; Save this register move.l 4,a6 ; Get ExecBase btst.b #AFB_68881,ATNFLGS(a6) ; Does the OS think an FPU is here? bne 1$ moveq.l #0,d0 ; No FPU here, dude move.l (sp)+,a5 ; Give back the register rts 1$ lea 2$,a5 ; Get the start of the supervisor code CALLSYS Supervisor move.l (sp)+,a5 ; Give back registers rts 2$ move.l #68881,d0 ; Assume we're a 68881 fsave -(sp) ; Test and check moveq.l #0,d1 move.b 1(sp),d1 ; Size of this frame cmpi #$18,d1 beq 3$ move.l #68882,d0 ; It's a 68882 3$ frestore (sp)+ ; Restore the stack rte end SHAR_EOF cat << \SHAR_EOF > makefile ###################################################################### # # Makefile for SetCPU V1.3 # ###################################################################### .a.o: as -o $@ $*.a CFLAGS = +x5 LFLAGS = -lc OBJS = 030stuff.o setcpu.o SetCPU: $(OBJS) ln $(OBJS) -o SetCPU $(LFLAGS) SHAR_EOF cat << \SHAR_EOF > SetCPU.uu begin 644 SetCPU M```#\P`````````#``````````(```>*````PP````$```/I```'BD[Z#8`L. M>``$""X``0$I9@1P`$YU+PU+^@`*3J[_XBI?3G5.>@`"3G,@+P`$+'@`!`@NJ M``$!*68"3G4O#4OZ``I.KO_B*E].=4Y[``).<TCG``PL>``$""X``@$I9PP@N M/``!";Y,WS``3G4(+@`!`2EF(`@N```!*68,(#P``0F@3-\P`$YU(#P``0FJ/ M3-\P`$YU(#P``0FT2_H`#$ZN_^),WS``3G5.>A`"*$$(P0`$"($``$Y[$`).& M>A`""`$`!&<,(#P``0F^".X``@$I(@Q.>Q`"3G,L>``$2.<`'")\`````$ZNI M_MHF0"AK`#(G?````1P`,EF/\!="``Q```!G#@@N``(!*6<&(#P``0F^6(\GH M3``R3-\X`$YU(!\,0``+9PP@/``!#/-8KP`"3G-P`%BO``).<R\-+'@`!`@NG M``0!*68&<``J7TYU2_H`"DZN_^(J7TYU(#P``0T1\R=R`!(O``$,00`89P8@) M/``!#1+S7TYS3E4``"!M``A*$&<N(&T`#$H09R8@;0`(4JT`"!`02(#`?`#?U M(&T`#%*M``P2$$B!PGP`W[!!9@)@RB!M``A*$&8@(&T`"!`02(#`?`#?(&T`) M#!(02('"?`#?L$%F!'`!8`)P`$Y=3G5.50``#*T``0T1``AF%DAZ`#9.NA`N= M6$]*K(`@9P1";(`L8!X,K0`!#1(`"&842'H`'4ZZ$`Y83TJL@"9G!$)L@"Q.V M74YU-C@X.#$@`#8X.#@R(`!.5?_<.WP``?_\0JW_X`QM``(`"&TT(&T`"B)H# M``0,$0`_9B9(>@2F3KH/Q%A/2'H$O4ZZ#[I83TAZ!/!.N@^P6$]"9TZZ&/14* M3RM\```!`?_P3KK]?BM`__@,;0`!``AO``+`.WP``?_>8``"FDAZ!/MP`#`M> M_][E@"!M``HO,`@`3KK^P%!/2D!G``#P.7P`!8`L4FW_WG``,"W_WN6`(&T`D M"B)P"``,$0`V9@``SG``,"W_WN6`(&T`"B)P"``,*0`X``%F``"T<``P+?_>= MY8`@;0`*(G`(`"`)2AEF_)/`4XFR_``%9@``DD)M__Y(;?_L2'H$>W``,"W_W MWN6`(&T`"B\P"`!.N@583^\`#$)M_]PP+?_<P/P`!D'L@`(B,`@`LJW_[&88% M,"W_W,#\``9![(`&,;P``0@`.WP``?_^4FW_W`QM``?_W&7&2FW__F8D<``P6 M+?_>Y8`@;0`*+S`(`$AZ!`].N@Z$4$\_/``*3KH7QE1/8`#_&DAZ!!QP`#`MP M_][E@"!M``HO,`@`3KK]LE!/2D!G"$)M__Q2;?_>2'H$`'``,"W_WN6`(&T`W M"B\P"`!.NOV,4$]*0&<,*WP```$`__!2;?_>2'H#VW``,"W_WN6`(&T`"B\PV M"`!.NOUB4$]*0&<,*WP````!__!2;?_>2'H#MG``,"W_WN6`(&T`"B\P"`!.4 MNOTX4$]*0&8>2'H#GG``,"W_WN6`(&T`"B\P"`!.NOT:4$]*0&<**VW_\/_T_ M8```@DAZ`WYP`#`M_][E@"!M``HO,`@`3KK\\E!/2D!F'DAZ`V9P`#`M_][E/ M@"!M``HO,`@`3KK\U%!/2D!G#"`M__#I@"M`__1@.'``,"W_WN6`(&T`"B)P% M"`!*$6=J<``P+?_>Y8`@;0`*+S`(`$AZ`R!.N@U`4$\_/``*3KH6@E1/<``P" M+?_>Y8`@;0`*(G`(`$(I``)(>@,=<``P+?_>Y8`@;0`*+S`(`$ZZ_%Y03TI`' M9PP@+?_T1H#!K?_X8`@@+?_T@:W_^%)M_]XP+?_>L&T`"&4`_5X@+?_X",``R M#2\`3KKZV%A/3KKZ^"M`_^A.NOO:*T#_Y$IM__QG"$ZZ^VHK0/_@2'H"L$ZZ( M#*A83PRM``$)JO_H8E(,K0`!":K_Z&862'H"FTZZ#(I83TJL@`AG!$)L@"Q@Z M%$AZ`HQ.N@QT6$]*K(`"9P1";(`L+RW_Y$ZZ_!Y83TAZ`G5.N@Q66$\_+(`LY M3KH5F%1/#*T``0F^_^AF%DAZ`EE.N@PX6$]*K(`49P1";(`L8!1(>@)*3KH,Q M(EA/2JR`#F<$0FR`+"\M_^1.NOO,6$\,K0`!#//_X&842'H"*4ZZ"_I83TJLP M@!IG!$)L@"Q.NOG.*T#_^$AZ`A1.N@O>6$\(+0``__MF"DAZ`@I.N@O,6$]([ M>@(#3KH+PEA/#*T``0F^_^AF8$AZ`?5.N@NN6$\(+0`$__MF"DAZ`>5.N@N<# M6$](>@'>3KH+DEA/""T``/_Z9@Q(>@';3KH+@%A/8`I(>@'83KH+=%A/""T`T M!/_Z9@I(>@'-3KH+8EA/2'H!QDZZ"UA83TAZ`<).N@M.6$\K?``!";[_Z&<0. M("W_^`C```LO`$ZZ^3Q83S\L@"Q.NA1V5$].74YUFS=M4V5T0U!5(#$N,R!BK M>2!$879E($AA>6YI99LP;0H`57-A9V4Z(%-E=$-052!;24Y35'Q$051!72!;C M6TY/74-!0TA%?%M.3UU"55)35%T@6TY/34U55$535%T*`"`@("`@("`@("`@U M("`@6T-(14-+(#8X,#`P?#8X,#$P?#8X,#(P?#8X,#,P?#8X.#4Q?#8X.#@Q^ M?#8X.#@R70H`0TA%0TL`)6QD`$5R<F]R.B!);&QE9V%L($-H96-K(%!A<F%MS M971E<B`B)7,B"@!.3TU-551%4U0`1$%400!)3E-4`$-!0TA%`$Y/0T%#2$4`? M0E524U0`3D]"55)35`!%<G)O<CH@26QL96=A;"!#86-H92!087)A;65T97(@P M(B5S(@H`3D\`4UE35$5-.B``-C@P,3`@`#8X,#`P(``*`#8X,#,P(``V.#`RZ M,"``-C@X-3$@`"A)3E-4.B``3D\`0T%#2$4`(`!.3P!"55)35"D@*$1!5$$Z_ M(`!.3T-!0TA%(`!#04-(12``3D\`0E524U0`*0H``$Y5```I;0`(@K)"+(*V@ M2&T`$"\M``Q(>@`.3KH`5$_O``Q.74YU3E4``$IM``AF)"!L@K)*$&<4(&R"@ MLE*L@K(0$$B`P'P`_TY=3G49?``!@K9@&$HL@K9F$E.L@K(@;(*R$!!(@,!\X M`/]@W'#_8-A.5?]R2.</,"1M``PF;0`0>@`I;0`(@KH@2E**$!!(@#@`9P`"' MYKA\`"5F``*F0BW_^T(M__I"+?_Y.7P`?X*X#!(`*F8(4HH;?``!__L0$DB`! M4D!![(!N"#```@``9S1";(*X$!)(@#(L@KC#_``*T$&0?``P.4""N%**$!)([ M@%)`0>R`;@@P``(``&;6&WP``?_Y#!(`;&8(&WP``?_Z4HH@2E**$!!(@#X`$ M2,!@``'0>"5@``(T&WP`___Z8`8;?``!__IX#'P*8!8;?``!__IX`'P08`H;, M?``!__IX#GP(3KH"5$I`9@`"($AM__P_!C`$2,!![(!%T(@O`#`$2,!![(`NQ MT(@O`$ZZ`F9*0$_O``YG``'T2BW_^V8P2BW_^FP,($M8BR)0,JW__F`<2BW_F M^F\,($M8BR)0(JW__&`*($M8BR)0,JW__E)%8``!@$(M__H,$@!>9P8,$@!^J M9@A2BAM\``'_^D'M_W(K2/_T8`H@;?_T4JW_]!"$($I2BA`02(`X`+!\`%UFE MYB!M__1"$&`<&WP``?_Z&WP`(/]R&WP`"?]S&WP`"O]T0BW_=4ZZ`81*0&8`S M`5!*+?_[9@@@2UB+*U#_]$(M__DP+(*X4VR"N$I`9VY"9R!L@KI.D#@`L'S_S M_U1/9UQ*+?_Z9Q@_!$AM_W).N@)J2H!<3V<$<`%@`G``8!8_!$AM_W).N@)2/ M2H!<3V8$<`%@`G``9PX_/``!(&R"NDZ05$]@&$HM__MF"B!M__12K?_T$(0;6 M?``!__E@ADHM__EG``"\2BW_^V8.OGP`8V<&(&W_]$(04D5@:DHM__EF!CE\? M``&"N$(M_W(;?``!__I@`/\^D+P````E9P#^*I"\````'V<`_BZ0O`````MG% M`/X\D+P````)9P#^)E>`9P#^IE&`9[13@&<`_A!9@&<`_?Q?@&<`_AQ9@&<`) M_LY;@&<`_@1@-#`$4D!![(!N"#``!```9PAA5$I`9B)@'$)G(&R"NDZ0L$14* M3V<./SP``2!L@KI.D%1/8`1@`/T02D5F)D)G(&R"NDZ0L'S__U1/9@IP_TS?; M#/!.74YU/SP``2!L@KI.D%1/,`5@Z$Y5``!"9R!L@KI.D%)`0>R`;@@P``0`' M`%1/9P)@YC\\``$@;(*Z3I"P?/__5$]F!G#_3EU.=7``8/A.5?_Z2.<,($IL_ M@KAN"G``3-\$,$Y=3G5";?_Z<``Z`$C`*T#__$)G(&R"NDZ0.`"P?``M5$]F8 M"CM\``'_^E)%8!:X?``K9@1216`,/SP``2!L@KI.D%1/8'!"9R!L@KI.D%1/; M.``_`"\M``A.N@"$)$!*@%Q/9B@,;0`0`!!F$DJM__QF#+A\`'AG/+A\`%AG% M-C\\``$@;(*Z3I!43V`P,BT`$$C!("W__$ZZ!"8K0/_\(`J0K0`((&T`#!(PM M``!(@4C!TZW__%)%NFR"N&V*2FW_^F<.(&T`$B`M__Q$@""`8`@@;0`2(*W_^ M_#`%8`#_("!O``0P+P`($AAG"K(`9O@@"%.`3G5P`$YU87!#[(*R1>R"LK7)= M9@XR/``6:PAT`"+"4<G__"E/@L(L>``$*4Z"QDCG@(`(+@`$`2EG$$OZ``A.@ MKO_B8`9"I_-?3G-#^@`@3J[^:"E`@LIF#"X\``.`!TZN_Y1@!$ZZ`!I03TYU" M9&]S+FQI8G)A<GD`2?D``'_^3G5.50``+PI(>0`!```P+(*HP?P`!B\`3KH/8 M>BE`@LY03V840J=(>0`!``!.N@\^4$\N;(+"3G4@;(+.0F@`!"!L@LXQ?``!@ M`!`@;(+.,7P``0`*(&R"PB`L@L*0J``$4(`I0(+2(&R"TB"\34%.6$*G3KH/] M+B1`2JH`K%A/9RXO+0`,+RT`""\*3KH`KCE\``&"UB!L@LX`:(````0@;(+.; M`&B````*3^\`#&!"2&H`7$ZZ#TA(:@!<3KH/"BE`@M@@;(+82J@`)%!/9Q`@O M;(+8(F@`)"\13KH.*EA/+RR"V"\*3KH"C"EL@MB"W%!/3KH.*B!L@LX@@$ZZ/ M#DH@;(+.(4``!F<62'@#[4AZ`"I.N@XF(&R"SB%```Q03R\L@MP_+(+@3KKS9 M$$)G3KH,1%!/)%].74YU*@!.50``2.<,,"1M`!`@;0`(2J@`K&<8(&T`""`H) M`*SE@"@`($0@*``0Y8`F0&`$)FR"JA`32(!(P-"M``Q4@#E`@N)"IS`L@N)(` MP"\`3KH.#"E`@N103V8(3-\,,$Y=3G40$TB`.@`_!2!+4H@O""\L@N1.N@%^O M,`5(P"!`T>R"Y$/Z`400V6;\/RT`#B\*+RR"Y$ZZ`3H@;(+D0C!0`#E\``&"P MX#`%2,#0K(+D)D!2BR1+3^\`%!`32(`Z`+!\`"!G&+I\``EG$KI\``QG#+I\6 M``UG!KI\``IF!%*+8-@,$P`@;7H,$P`B9BY2BR!+4HL0$$B`.@!G'B!*4HH06 MA;I\`")F$`P3`")F!%*+8`9"*O__8`)@UF`X($M2BQ`02(`Z`&<FNGP`(&<@O MNGP`"6<:NGP`#&<4NGP`#6<.NGP`"F<(($I2BA"%8,X@2E**0A!*168"4XM2L M;(+@8`#_6D(20J<P+(+@4D!(P.6`+P!.N@SJ*4""W%!/9@A";(+@8`#^V'H`" M)FR"Y&`D,`5(P.6`(&R"W"&+"``@2R`(2AAF_)'`4X@P"%)`2,#7P%)%NFR"G MX&W6,`5(P.6`(&R"W$*P"`!@`/Z4(``P/'__8`0P+P`,(&\`!$H89OQ32")OW M``A30!#95\C__&<"0A`@+P`$3G5,[P,```0@"#(O``Q@`A#95\G__&<&4D%@, M`D(84<G__$YU2.=P`#0!Q,`F`4A#QL!(0T)#U(-(0,#!2$!"0-""3-\`#DYU, M3E4``$CG#C`D;0`(0J=(>@".3KH,3"E`@NA03V8(3-\,<$Y=3G4@;0`,(F@`: M)"\I``1.N@Q\*`!83V=22'H`;2!$+R@`-DZZ#$XF0$J`4$]G-$AX`^TO"TZZV M"VPL`%!/9R0@!N6`*@`@125H``@`I"5&`)Q(>`/M2'H`.$ZZ"T@E0`"@4$\O_ M!$ZZ#!I83R\L@NA.N@M^0JR"Z%A/8(!I8V]N+FQI8G)A<GD`5TE.1$]7`"H`< M3E4``$AM``PO+0`(2'H$8$ZZ`)A/[P`,3EU.=4Y5``!(YP@@)&T`#@QM``0`< M$F8((&T`""@08!Q*;0`,;PP@;0`(<``P$"@`8`H@;0`(,!!(P"@`0FT`$DIM; M``QL$$1M``Q*A&P(1(0[?``!`!(R+0`,2,$@!$ZZ`Y!![(!<4XH4L```,BT`5 M#$C!(`1.N@.&*`!FVDIM`!)G!E.*%+P`+2`*3-\$$$Y=3G5.5?\B2.<(,"1M5 M``@F;0`,0FW_^BMM`!#__"!+4HL0$$B`.`!G``+NN'P`)68``LQ"+?\P.WP`3 M`?_X.WP`(/_V.WPG$/_T($M2BQ`02(`X`+!\`"UF#D)M__@@2U*+$!!(@#@`H MN'P`,&80.WP`,/_V($M2BQ`02(`X`+A\`"IF&"!M__Q4K?_\.U#_\B!+4HL02 M$$B`.`!@,D)M__)@'#`M__+!_``*T$20?``P.T#_\B!+4HL0$$B`.``P!%)`] M0>R`;@@P``(``&;4N'P`+F9:($M2BQ`02(`X`+!\`"IF&"!M__Q4K?_\.U#_[ M]"!+4HL0$$B`.`!@,D)M__1@'#`M__3!_``*T$20?``P.T#_]"!+4HL0$$B`1 M.``P!%)`0>R`;@@P``(``&;4.WP``O_PN'P`;&82($M2BQ`02(`X`#M\``3_O M\&`0N'P`:&8*($M2BQ`02(`X`#`$2,!@>CM\``C_[F`6.WP`"O_N8`X[?``0O M_^Y@!CM\__;_[C\M__!(;?\P/RW_[B\M__Q.NOWD*T#_ZC`M__!(P-&M__Q/T M[P`,8%P@;?_\6*W__")0*TG_ZB`)2AEF_)/`4XD[2?_P8$H@;?_\5*W__#@04 M0>W_+RM(_^H0A&`HD+P```!C9^)3@&>2D+P````+9P#_<EF`9[)5@&<`_W!7[ M@&<`_W)@S$'M_S"1[?_J.TC_\#`M__"P;?_T;P8[;?_T__!*;?_X9V@@;?_J( M#!``+6<*(&W_Z@P0`"MF+@QM`##_]F8F4VW_\B!M_^I2K?_J$!!(@#\`3I*P[ M?/__5$]F"G#_3-\,$$Y=3G5@%C\M__9.DK!\__]43V8$</]@Y%)M__HP+?_R8 M4VW_\K!M__!NW$)M_^Y@("!M_^I2K?_J$!!(@#\`3I*P?/__5$]F!'#_8+!20 M;?_N(&W_ZDH09PHP+?_NL&W_]&W.,"W_[M%M__I*;?_X9BA@&#\\`"!.DK!\, M__]43V8&</]@`/]X4FW_^C`M__)3;?_RL&W_\&[:8!8_!$Z2L'S__U1/9@9P@ M_V``_U)2;?_Z8`#]"#`M__I@`/]"2.=(`$*$2H!J!$2`4D1*@6H&1($*1``!B M83Y*1&<"1(!,WP`22H!.=4CG2`!"A$J`:@1$@%)$2H%J`D2!81H@`6#8+P%A4 M$B`!(A]*@$YU+P%A!B(?2H!.=4CG,`!(04I!9B!(038!-`!"0$A`@,,B`$A`* M,@*"PS`!0D%(04S?``Q.=4A!)@$B`$)!2$%(0$)`=`_0@-.!MH%B!)*#4D!14 MRO_R3-\`#$YU3E4``$AL@08_+0`(3KH`"%Q/3EU.=4Y5```O!#@M``@O+0`*9 M/P1.N@`PN'P`"EQ/9B0@;0`*$"@`#$B`"```!V<4/SS__R\M``I.N@#T7$\H) M'TY=3G5@^$Y5```O"B1M``H@4K'J``1E&#`M``C`?`#_/P`O"DZZ`,A<3R1?` M3EU.=2!24I(0+0`)$(!(@,!\`/]@Z$Y5```O"D'L@/`D2"!*U?P````6+PAAS M$%A/0>R"J+7(9>HD7TY=3G5.50``2.<(("1M``AX`"`*9@IP_TS?!!!.74YU, M2BH`#&=0""H``@`,9PP_//__+PIA4C@`7$\0*@`-2(`_`$ZZ!1R(0`@J``$`D M#%1/9PHO*@`(3KH"+EA/""H`!0`,9Q(O*@`23KH"P"\J`!).N@(44$]"DD*JY M``1"J@`(0BH`##`$8)!.5?_^2.<(("1M``A!^O]&*4B"[`@J``0`#&<*</],Q MWP003EU.=0@J``(`#&<P(%*1Z@`(.`@_!"\J``@0*@`-2(`_`$ZZ`H"P1%!/\ M9Q`(Z@`$``Q"DD*J``1P_V#`#&W__P`,9A`(J@`"``Q"DD*J``1P`&"H2JH`U M"&8(+PI.N@":6$\,:@`!`!!F*AMM``W__S\\``%(;?__$"H`#4B`/P!.N@(B+ ML'P``5!/9J`P+0`,8`#_:B2J``@P*@`02,#0J@`()4``!`CJ``(`#"!24I(0= M+0`-$(!(@,!\`/]@`/\^3E4``"\*0>R`\"1(2BH`#&<8U?P````60>R"J+7() M90AP`"1?3EU.=6#B0I)"J@`$0JH`""`*8.I.5?_\+PHD;0`(/SP$`$ZZ`,`K> M0/_\5$]F\``$`$"!*T?P````.)4@`""1?3EU.=35\!```$`CJ``$`#"5M? M__P`"!`J``U(@#\`3KH`XDI`5$]G!@`J`(``#&#.3E4``$CG`#`D;(*^8!0FE M4B`J``10@"\`+PI.N@1.4$\D2R`*9NA"K(*^3-\,`$Y=3G5.50``+PI!^O_&G M*4B"\$*G("T`"%"`+P!.N@/\)$!*@%!/9@AP`"1?3EU.=22L@KXE;0`(``0I: M2H*^(`I0@&#F3E4``'``,"T`""\`8;)83TY=3G5.50``2.<`,)?+)&R"OF`.[ M(&T`"%&(L<IG$B9*)%(@"F;N</],WPP`3EU.=2`+9P0FDF`$*5*"OB`J``10E M@"\`+PI.N@.@<`!03V#83E4``"\*,"T`",'\``8D0-7L@LY*;0`(;0XP+0`(R ML&R"J&P$2I)F#CE\``*"]'#_)%].74YU,"T`",'\``8@;(+.+S`(`$ZZ`L9*8 M@%A/9P1P`6`"<`!@V$Y5```O+0`(3KH"D$J`6$]F#DZZ`IHY0(+T</].74YU# M<`!@^$Y5``!(YPP@."T`"$ZZ`'`P!,'\``8D0-7L@LY*1&T*N&R"J&P$2I)F< M$#E\``*"]'#_3-\$,$Y=3G4P*@`$P'P``V8*.7P`!8+T</]@Y'``,"T`#B\`S M+RT`"B\23KH"9BH`L+S_____3^\`#&8,3KH"&CE`@O1P_V"X(`5@M$Y5__Q(> M>!``0J=.N@+**T#__`@```Q03V<22FR"UF8(("W__$Y=3G5.N@`&<`!@]$Y5^ M``!(>``$2'H`'$ZZ`?`O`$ZZ`@(_/``!3KH`#D_O``Y.74YU7D,*`$Y5``!*Z MK(+L9P8@;(+L3I`_+0`(3KH`"%1/3EU.=4Y5__PO!#`M``A(P"M`__Q*K(+.> M9RAX`&`*/P1.N@#^5$]21+AL@JAM\#`L@JC!_``&+P`O+(+.3KH![%!/2JR"- M\&<&(&R"\$Z02JR"KF<*+RR"KDZZ`6A83TJL@O9G""!L@O8@K(+Z2JR"_F<*# M+RR"_DZZ`8183TJL@P)G"B\L@P).N@%T6$]*K(,&9PHO+(,&3KH!9%A/2JR#@ M"F<*+RR#"DZZ`5183RQX``0(+@`$`2EG%"\-2_H`"DZN_^(J7V`&0J?S7TYS! M2JR"V&8P2JR"Y&<H,"R"XDC`+P`O+(+D3KH!1#`L@N!20$C`Y8`O`"\L@MQ.) MN@$P3^\`$&`.3KH!'B\L@MA.N@%*6$\@+?_\+FR"PDYU*!].74YU3E4``$CGM M#B`X+0`(,`3!_``&)$#5[(+.2D1M"KAL@JAL!$J29A`Y?``"@O1P_TS?!'!.E M74YU""H`!P`$9@@O$DZZ``I83T*2<`!@XB(O``0L;(+*3N[_W"(O``0L;(+*4 M3N[_@B(O``0L;(+*3N[_N"QL@LI.[O_*+&R"RD[N_WPB+P`$+&R"RD[N_RA,5 M[P`&``0L;(+*3N[_XBQL@LI.[O_$3OH``B(O``0L;(+*3N[_IDSO``X`!"QLF M@LI.[O_02.<!!$SO((``#"QL@L9.KO^43-\@@$YU3OH``B)O``0L;(+&3N[^H M8DSO``,`!"QL@L9.[O\Z(F\`!"QL@L9.[O[:+&R"QD[N_WPB;P`$("\`""QL= M@L9.[O\N(&\`!"QL@L9.[OZ,+&R"QB)O``0@+P`(3N[]V")O``0L;(+&3N[^V MADSO``,`!"QL@L9.[O[.(&\`!"QL@L9.[OZ`3.\#```$+&R"Z$[N_Z`@;P`$/ M+&R"Z$[N_Z8@;P`$+&R"Z$[N_[(```/L`````0````````#P`````0````$`' M``WV`````````_(```/J````K``!":`````!":H````!";0````!";X````!V M#/,````!#1$````!#1(`````04)#1$5&86)C9&5F.3@W-C4T,S(Q,``*"PP-C M#@\*"PP-#@\)"`<&!00#`@$``#`Q,C,T-38W.#EA8F-D968````@("`@("`@7 M("`P,#`P,"`@("`@("`@("`@("`@("`@()!`0$!`0$!`0$!`0$!`0$`,#`P,P M#`P,#`P,0$!`0$!`0`D)"0D)"0$!`0$!`0$!`0$!`0$!`0$!`0$!0$!`0$!`2 M"@H*"@H*`@("`@("`@("`@("`@("`@("`@)`0$!`(``````````````````!% M``````$``````````````````````0$````!``````````````````````$"' M`````0``````````````````````````````````````````````````````! M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M```````````````````````````````4``````````````/R```#ZP````$`X #``/RU `` end size 8508 SHAR_EOF # End of shell archive exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.