[comp.sources.amiga] v89i057: setcpu - show/set cpu attributes v1.4

page@swan.ulowell.edu (Bob Page) (03/16/89)

Submitted-by: cbmvax!daveh (Dave Haynie)
Posting-number: Volume 89, Issue 57
Archive-name: kernel/setcpu14.1

As well as fixing and extending the CHECK code, SetCPU V1.4 also has
some simple "FASTROM" code to allow 32 bit systems with MMUs to copy
ROM into RAM and then relocate this RAM as ROM, thus greatly enhancing
the speed of ROM based operations.

[uuencoded executables included.  ..Bob]

#	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.txt
#	ROMBash.c
#	SetCPU.c
#	030Stuff.a
#	makefile
#	RomBash.uu
#	SetCPU.uu
# This archive created: Wed Mar 15 13:44:12 1989
cat << \SHAR_EOF > SetCPU.txt

			SetCPU V1.4
		       by Dave Haynie 
		(released to the public domain)


	This program is designed to allow the user to detect and modify
various parameters related to 32 bit CPUs in Amiga computers.  This program
began life as "WhatCPU", which did little more than read the proper place
in ExecBase and report what kind of CPU/FPU was in the system.  The first
version of SetCPU added the capability to identify a 68030 and to change the 
cache parameters of the 68020 and 68030 systems.  The recently released SetCPU
V1.3 also did tests for 68882 vs. 68881, and for the presence of an MMU.  It
was supposed to allow for checking of a particular thing in a startup 
sequence, but unfortunately the CHECK code in V1.3 was broken.

	That brings us up to V1.4.  As well as fixing and extending the CHECK
code, SetCPU V1.4 also has some simple MMU code to allow 32 bit systems with
MMUs to copy ROM into RAM and then relocate this RAM as ROM, thus greatly
enhancing the speed of ROM based operations.  This "FASTROM" code isn't
extremely sophisticated, and could possibly run into trouble on other 32 bit
systems, but it has been tested on the A2620.  It will certainly have to be 
rethought to work properly with memory outside of the 68000 compatible 24 bit
address space.

	In any case, the syntax of the program is given as follows:

		SetCPU [INST|DATA] [[NO]CACHE|[NO]BURST]
		       [[NO]FASTROM [TRAP]] [NOMMUTEST]
		       [CHECK 680x0|68851|6888x|MMU|FPU]

where "[]" indicates an optional parameter, "|" indicates a choice of
parameters.  Typing "SetCPU ?" will retrieve this same syntax diagram.
Typing SetCPU alone will result in the SYSTEM configuration being 
send to the console, my current system returns this:

	SYSTEM: 68020 68881 68851 FASTROM (INST: CACHE)

This indicates I have a 68020/68881/68851 system (eg, standard A2620), I've
previously installed the FASTROM translation, and my instruction cache is
turned on (done by AmigaOS V1.2 or V1.3).  Note that any parameters that
don't make sense to the real system configuration, such as asking to modify
the data cache on a 68020 system or install the FASTROM translation on a
68000 system are just ignored.

	The individual commands are given below in detail:


[NO]CACHE
	This command will switch on or off 68020 and 68030 caches.  If
	not qualified, it'll act on both instruction and data caches of
	the 68030.

[NO]BURST
	This command will switch on or off the burst cache line fill 
	request of the 68030.  If not qualified, it'll act on both 
	instruction and data caches.

INST
	This preceeds a CACHE or BURST operation to restrict it's application
	to the instruction cache only.

DATA
	This preceeds a CACHE or BURST operation to restrict it's application
	to the data cache only.

[NO]FASTROM [TRAP]
	This activates the FASTROM translation on or off an MMU equipped 
	system.  When switching on, it first allocates 256K of memory for
	the ROM image, then currenly 512 bytes of memory for the MMU table.
	It copies the ROM into the image area, then applies the translation
	by pointing the MMU at the table and activating it.  The TRAP option
	causes the MMU to look at all 32 bits of address; access to any 
	memory outside of the 24 bit space will result in an exception, which
	if unhandled, results in a GURU 2.  When TRAP is not specified, the 
	MMU is only looking at 24 bits of address space.  This is the mode 
	you'd normally run in.  Under V1.3 and earlier releases, a DOS bug 
	can cause invalid accesses, which cause the exception, when running 
	the EndCLI or NewCLI/NewShell programs; running untrapped will avoid 
	gurus with these commands.  It's still possible to run into an 
	exception when running without the TRAP option.  One easy way is 
	writing to the ROM image, which is write protected by the MMU.  The 
	NOFASTROM option will switch off the MMU and reclaim the memory used
	for the ROM image and MMU table.  Note that this is achieved by 
	locating these items via the appropriate MMU registers.  If any other
	program set up the MMU for something, this could be a very bad thing
	to do.  In general, until there's some level of OS support for the 
	MMU in Amiga systems, you're really safe using only one MMU tool at 
	a time.

NOMMUTEST
	This option won't normally be necessary.  However, some 68020 boards
	out there apparently have hardware bugs of some sort that make
	testing for the MMU impossible, at least as near as I can tell.  If
	your 68020 board freezes, or crashes with some kind of coprocessor 
	protocol violation GURU (probably numbers $0D or $0E), you have a
	problem with your 68020 board.  The most common bug is the 68020
	board hardware failing to fully decode CPU space, such that the FPU
	in the system also responds to the MMU's address space.

CHECK 
	This option lets you check for the existence of a particular
	CPU system component in a script.  It works like this:

		SetCPU CHECK 68020
		If WARN
			echo "No 68020 here!"
		Else
			echo "Sho nuff got a 68020 here!"
		Endif

	The arguments to CHECK can be any of:

		68000	Matches the obvious
		68010	"
		68020	"
		68030	"
		68851	"
		68881	"
		68882	"
		FPU	Matches 68881 or 68882
		MMU	Matches 68851 or 68030

That's about it.  As mentioned, this code is public domain, and you're
free to do anything with it you like.  Even make it better!  For any real
MMU programming, I'd recommend both "MC68030 Enhanced 32-Bit Microprocessor
User's Manual" and "MC68881 Paged Memory Management Unit User's Manual",
both from Motorola.  There are some differences between the two, please make 
sure, if you're writing any MMU code, that you either write code that works
on both, or you specifically check for each MMU and act accordingly.

Also note that much of what SetCPU does may be wrong in a future release of
the OS, so it's a very bad idea to put any of this stuff in a commercial
program.  Things like identifying the MMU, CPU, or FPU that aren't fully
done in 1.3 may still work in a future OS release, but if that OS is
correctly identifying the MMU, CPU (eg, 68020 vs. 68030), or FPU (eg,
68881 vs. 68882), SetCPU should be using the OS's opinion of these items,
not testing itself.  On a more drastic note, if an OS ever starts using
the MMU, the FASTROM code will certainly break.  It's the job of the OS to
arbitrate the MMU, and if the OS is doing that, no legal program would be
able to come along and muck with the MMU registers without reeking havoc
on the operating system.

One final note, if you have a 68020 board that locks up without the
NOMMUTEST option, you'd be wise to express your concerns to the vendor
of that board.  There's an awful good chance that if, in the future, 
Amiga releases an operating system that knows about the MMU, it'll test
for it in some way, probably similar to what I do here.  If your board
locks up on MMU operations, you may not be able to run this future OS
on your 68020 board.  Maybe the vendors can fix these now, instead of
later when you really need this fixed.

			-Dave Haynie
			 PLINK:		D-Dave H
			 bix:		hazy
			 usenet:	{uunet,rutgers}!cbmvax!daveh
SHAR_EOF
cat << \SHAR_EOF > ROMBash.c
/* This program bashes on the ROM; basically, just copying the ROM around
   several times. */

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/ports.h>
#include <exec/tasks.h>
#include <exec/devices.h>
#include <exec/io.h>
#include <devices/timer.h>
#include <libraries/dos.h>

struct Task *FindTask();
void SubTime(), *AllocMem();
struct Device *TimerBase;

/* This routine wastes time, based on ROM access. */

#define	ROMBASE		0x00FC0000L
#define ROMSIZE		0x00030000L

void ROMBash() {
   short ctr;
   ULONG *mem;

   mem = AllocMem(ROMSIZE,0L);
   for (ctr = 0; ctr < 100; ++ctr) {
      CopyMemQuick(ROMBASE,mem,ROMSIZE);
   }
   FreeMem(mem,ROMSIZE);
}

/* This is the main program. */

void main()
{
   struct MsgPort port;
   struct timerequest treq;
   long pass;
   struct timeval origtime, finaltime;

  /* Initialize the timer stuff */
   port.mp_Node.ln_Name = "ROMBash";
   port.mp_Flags = PA_SIGNAL;
   port.mp_SigTask = FindTask(0L);
   port.mp_SigBit = AllocSignal(-1L);
   AddPort(&port);
   treq.tr_node.io_Message.mn_ReplyPort = &port;

   if (OpenDevice(TIMERNAME,0L,&treq,0L) != 0) {
      printf("Error: Can't get \"%s\"\n",TIMERNAME);
      exit(20);
   }
   TimerBase = treq.tr_node.io_Device;
   treq.tr_node.io_Command = TR_GETSYSTIME;

  /* Find the starting time */
   DoIO(&treq);
   origtime = treq.tr_time;

   ROMBash();

  /* Find the ending time */
   DoIO(&treq);
   finaltime = treq.tr_time;   

   SubTime(&finaltime,&origtime);
   
   printf("DONE: Elapsed time = %ld.%6ld seconds\n",
          finaltime.tv_secs,finaltime.tv_micro);

   CloseDevice(&treq);
   RemPort(&port);
   FreeSignal((ULONG)port.mp_SigBit);
}
SHAR_EOF
cat << \SHAR_EOF > SetCPU.c
/*
	SetCPU V1.4
	by Dave Haynie (released to the public domain)

	MAIN PROGRAM

    V1.4
	I now add several commands in the assembly stub for manipulating
	a few of the MMU registers.  SetCPU now uses this to permit a
	simple relocation of the ROM Kernel into 32 bit memory, which is
	then translated back to the normal $00FC0000 base of the ROM
	Kernel.  This will increase system performance noticably.

    V1.3
	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.
	
    V1.2
	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).
	
    V1.1
	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.
	
*/

#define PROGRAM_VERSION	"V1.4"

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/nodes.h>
#include <exec/interrupts.h>
#include <functions.h>
#include <stdio.h>

/* ====================================================================== */

/* Define all bit components used for manipulation of the Cache Control
   Register. */

#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

/* ====================================================================== */

/* Define important bits used in various MMU registers. */

/* Here are the CRP definitions.  The CRP register is 64 bits long, but
   only the first 32 bits are control bits, the next 32 bits provide the
   base address of the table. */

#define	CRP_UPPER	(1L<<31)		/* Upper/lower limit mode */
#define CRP_LIMIT(x)	((ULONG)((x)&0x7fff)<<16)/* Upper/lower limit value */
#define CRP_SG		(1L<<9)			/* Indicates shared space */
#define CRP_DT_INVALID	0x00			/* Invalid root descriptor */
#define	CRP_DT_PAGE	0x01			/* Fixed offset, auto-genned */
#define CRP_DT_V4BYTE	0x02			/* Short root descriptor */
#define	CRP_DT_V8BYTE	0x03			/* Long root descriptor */

/* Here are the TC definitions.  The TC register is 32 bits long. */

#define	TC_ENB		(1L<<31)		/* Enable the MMU */
#define	TC_SRE		(1L<<25)		/* For separate Supervisor */
#define	TC_FCL		(1L<<24)		/* Use function codes? */
#define	TC_PS(x)	((ULONG)((x)&0x0f)<<20)	/* Page size */
#define TC_IS(x)	((ULONG)((x)&0x0f)<<16)	/* Logical shift */
#define	TC_TIA(x)	((ULONG)((x)&0x0f)<<12)	/* Table indices */
#define	TC_TIB(x)	((ULONG)((x)&0x0f)<<8)
#define TC_TIC(x)	((ULONG)((x)&0x0f)<<4)
#define	TC_TID(x)	((ULONG)((x)&0x0f)<<0)

/* Here are the page descriptor definitions, for short desctriptors only,
   since that's all I'm using at this point. */
   
#define	PD_ADDR(x)	((ULONG)(x)&~0x0f)	/* Translated Address */
#define	PD_WP		(1L<<2)			/* Write protect it! */
#define PD_DT_INVALID	0x00			/* Invalid root descriptor */
#define	PD_DT_PAGE	0x01			/* Fixed offset, auto-genned */
#define PD_DT_V4BYTE	0x02			/* Short root descriptor */
#define	PD_DT_V8BYTE	0x03			/* Long root descriptor */

/* ====================================================================== */

/* Some external declarations. */

void SetCACR(), GetCRP(), SetCRP(), SetTC();
ULONG GetCACR(), GetTC(), GetCPUType(), GetMMUType(), GetFPUType();

/* Checking logic */

#define	CK68000	0
#define CK68010	1
#define CK68020	2
#define CK68030	3
#define CK68851	4
#define CK68881	5
#define CK68882	6
#define CKFPU	7
#define CKMMU	8
#define CHECKS	9

#define	WARNING	5

struct checker { char *item; BOOL tag; };

struct checker checks[CHECKS] = {
   { "68000", FALSE },
   { "68010", FALSE },
   { "68020", FALSE },
   { "68030", FALSE },
   { "68851", FALSE },
   { "68881", FALSE },
   { "68882", FALSE },
   { "FPU",   FALSE },
   { "MMU",   FALSE }
};

USHORT code = 0L;	/* Program return code */

/* ====================================================================== */

/* This replaces the Lattice "stricmp()" function, plus it's a better form
   for my needs here. */
   
static BOOL striequ(s1,s2)
char *s1,*s2;
{
   BOOL aok;
   
   while (*s1 && *s2 && (aok = (*s1++ & 0xdf) == (*s2++ & 0xdf)));
   return (BOOL) (!*s1 && aok);
}

/* This routine prints FPU codes and sets things accordingly. */

static void PrintFPU(fpu)
ULONG fpu;
{
   if (fpu == 68881L) {
      printf("68881 ");
      if (checks[CK68881].tag) code = 0;
   } else if (fpu == 68882L) {
      printf("68882 ");
      if (checks[CK68882].tag) code = 0;
   }
   if (fpu && checks[CKFPU].tag) code = 0;
}

/* ====================================================================== */

/* Here's the MMU support stuff. */

#define ROUND		0x00001000L
#define ROMBASE		0x00FC0000L
#define ROMSIZE		0x00040000L
#define TABSIZE		(128L * sizeof(ULONG))

/* Page tables and other MMU stuff must be on a page sized boundary, and
   that boundary must be a power of two.  This routine allocates such an
   aligned block of memory. */

static void *AllocAligned(size,bound)
ULONG size;
ULONG bound;
{
   void *mem, *aligned;
   
   if (!(mem = AllocMem(size+bound,0L))) return NULL;   
   Forbid();
   aligned = (void *)(((ULONG)mem + bound - 1) & ~(bound - 1));
   FreeMem(mem,size+bound);
   mem = AllocAbs(size,aligned);
   Permit();
   return mem;
}

/* This routine creates the Fast ROM.  If the memory can't be allocated,
   it returns FALSE, otherwise, TRUE.  The "wrapbits" argument probably
   won't work for every case.  There's some magic here which I seem to
   have working, but don't understand completely.  Basically, the TC
   register must be correct, or you'll get a configuration exception,
   otherwise know as GURU #38.  The big constraint is that sum of the
   TIx fields from A to the first zero field, plus PS and IS, must be
   equal to 32. */

static BOOL CreateFastROM(wrapbits)
short wrapbits;
{
   ULONG i, myCRP[2], myTC, *ROM32 = NULL, *MMUTable = NULL;

  /* First off, get the memory for the 32 bit ROM and the MMU table. */

   ROM32 = AllocAligned(ROMSIZE,ROUND);
   MMUTable = AllocAligned(TABSIZE,ROUND);
   if (!ROM32 || !MMUTable) {
      if (MMUTable) FreeMem(MMUTable,TABSIZE);
      if (ROM32)    FreeMem(ROM32,ROMSIZE);
      return FALSE;
   }

  /* Here I set up the ROM, as quickly as possible! */

   CopyMemQuick(ROMBASE,ROM32,ROMSIZE);

  /* Now I initialize the MMU table.  This translation is really very
     basic.  I set up one table level and use direct page translation
     on a grain of 128K per entry.  Everything's directly mapped except
     for the last two entries, which is for the $FC0000-$FFFFFF area.
     This I translate to my fastram ROM, and write protect it too. */

   for (i = 0; i < 126; i++) MMUTable[i] = PD_ADDR(i<<17)|PD_DT_PAGE;
   MMUTable[126] = PD_ADDR(ROM32)|PD_WP|PD_DT_PAGE;
   MMUTable[127] = PD_ADDR(((ULONG)ROM32)+0x20000L)|PD_WP|PD_DT_PAGE;

  /* Now I have to set up the MMU.  The CPU Root Pointer tells the MMU about 
     the table I've set up, and the Translation Control register will turn 
     the thing on.  Note that the first half of the CRP is control data, the
     second the address of my table. */

   myCRP[0] = CRP_LIMIT(0x007f)|CRP_SG|CRP_DT_V4BYTE;
   myCRP[1] = (ULONG)MMUTable;
   SetCRP(myCRP);

   myTC = TC_ENB|TC_PS(0x0c)|TC_IS(wrapbits)|
          TC_TIA(0x0f-wrapbits)|TC_TIB(0x05)|TC_TIC(0)|TC_TID(0);
   SetTC(myTC);
   return TRUE;
}

/* This routine remover the Fast ROM, and re-claims the memory previously
   allocated.  We've already checked to make sure that the MMU was 
   switched on. */

static void DeleteFastROM() {
   ULONG myCRP[2], *ROM32 = NULL, *MMUTable = NULL;

  /* First off, turn of the MMU.  This lets us muck with the table and
     reclaim memory without any trouble. */

   SetTC(0L);

  /* Now get the root pointer, which will tell where the memory has been
     allocated. */

   GetCRP(myCRP);
   MMUTable = (ULONG *)myCRP[1];
   ROM32 = (ULONG *)PD_ADDR(MMUTable[126]);

  /* Now I just free up the memory, and I'm done! */
  
   FreeMem(MMUTable,TABSIZE);
   FreeMem(ROM32,ROMSIZE);
}

/* ====================================================================== */

/* Codes for the FASTROM action. */

#define	FR_NO_ACTION	0
#define	FR_CREATE	1
#define	FR_DELETE	2

/* This be the main program. */

int main(argc,argv)
int argc;
char *argv[];
{
   BOOL worked, dommutest = TRUE, fastrom = FR_NO_ACTION;
   ULONG cacr,op,mode,test,cpu,fpu,mmu = 0;
   USHORT i,j;
   short wrapbits = 8;

   /* If they're just asking for help */

   if (argc >= 2 && argv[1][0] == '?') {
      printf("\2337mSetCPU %s by Dave Haynie\2330m\n",PROGRAM_VERSION);
      printf("Usage: SetCPU [INST|DATA] [[NO]CACHE|[NO]BURST]\n");
      printf("              [[NO]FASTROM [TRAP]] [NOMMUTEST]\n");
      printf("              [CHECK 680x0|68851|6888x|MMU|FPU]\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 (code == WARNING) for (j = 0; j < CHECKS; ++j)
            if (striequ(checks[j].item,argv[i])) {
               checks[j].tag = TRUE;
               break;
            }
         if (striequ(argv[i],"CHECK"))		code = WARNING;
         else if (striequ(argv[i],"FASTROM"))	fastrom = FR_CREATE;
         else if (striequ(argv[i],"NOFASTROM"))	fastrom = FR_DELETE;
         else if (striequ(argv[i],"TRAP"))	wrapbits = 0;
         else if (striequ(argv[i],"NOMMUTEST"))	dommutest = FALSE;
         else if (striequ(argv[i],"DATA"))	mode = CACR_DATA;
         else if (striequ(argv[i],"INST"))	mode = CACR_INST;
         else if (striequ(argv[i],"CACHE"))	cacr |=   mode << CACR_ENABLE;
         else if (striequ(argv[i],"NOCACHE"))	cacr &= ~(mode << CACR_ENABLE);
         else if (striequ(argv[i],"BURST"))	cacr |=   mode << CACR_BURST;
         else if (striequ(argv[i],"NOBURST"))	cacr &= ~(mode << CACR_BURST);
      }

     /* 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, and perform the ROM translation, if it's
     requested and hasn't been done already. */

   cpu = GetCPUType();
   fpu = GetFPUType();
   if (dommutest && (mmu = GetMMUType())) {
      if (!(GetTC() & TC_ENB)) {
         if (fastrom == FR_CREATE && !CreateFastROM(wrapbits)) {
            printf("Error: Can't get memory for FASTROM translation\n");
            exit(10);
         }
      } else if (fastrom == FR_DELETE)
         DeleteFastROM();
   }

   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].tag) code = 0;
      } else {
         printf("68000 ");
         if (checks[CK68000].tag) 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].tag) code = 0;
   } else {
      printf("68020 ");
      if (checks[CK68020].tag) code = 0;
   }

   PrintFPU(fpu);

   if (mmu == 68851L) {
      printf("68851 ");
      if (checks[CK68851].tag) code = 0;
   }
   if (mmu && checks[CKMMU].tag) code = 0;
   if (mmu && (GetTC() & TC_ENB)) printf("FASTROM ");

   /* 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.4
;	by Dave Haynie (released to the public domain)
;
;	68030 Assembly Function Module
;
;	This module contains functions that access functions in the 68020,
;	68030, and 68851 chips, and ID all of these, plus the 68881/68882
;	FPU chips.
;
;======================================================================

;======================================================================
;
;	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

;**********************************************************************
;
;	This section contains functions that identify and operate on CPU 
;	things.
;
;**********************************************************************

	public	_GetCPUType	; ID the CPU
	public	_GetCACR	; Get 020/030 CACR register
	public	_SetCACR	; Set 020/030 CACR register

;======================================================================
;
;	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 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 section contains functions that identify and operate on
;	MMU things.  Unfortunately, there aren't any MMU op-codes in
;	the Manx assembler yet, so I have to fudge them here.
;
;**********************************************************************

	public	_GetMMUType	; Returns the type of MMU
	public	_GetCRP		; Gets MMU CRP register
	public	_SetCRP		; Sets MMU CRP register
	public	_GetTC		; Gets MMU TC register
	public	_SetTC		; Gets MMU TC register

;======================================================================
;
;	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 MMU CRP register.  It assumes a 68020 
;	system with MMU, or a 68030 based system (eg, test for MMU before
;	you call this, or you wind up in The Guru Zone).  Note that the
;	CRP register is two longwords long.
;
;	void GetCRP(ULONG *)
;
;======================================================================

_GetCRP:
	move.l	4(sp),a0		; Pointer to the CRP storage area
	move.l	4,a6			; Get ExecBase
	move.l	a5,-(sp)
	lea	2$,a5			; Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5
	rts
2$
	dc.w	$f010			; PMOVE CRP,(a0)
	dc.w	$4e00
	rte

;======================================================================
;
;	This function sets the MMU CRP register.  It assumes a 68020 
;	system with MMU, or a 68030 based system (eg, test for MMU before
;	you call this, or you wind up in The Guru Zone).  Note that the
;	CRP register is two longwords long.
;
;	void SetCRP(ULONG *)
;
;======================================================================

_SetCRP:
	move.l	4(sp),a0		; Pointer to the CRP storage area
	move.l	4,a6			; Get ExecBase
	move.l	a5,-(sp)
	lea	2$,a5			; Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp)+,a5		; Give back registers
	rts
2$
	dc.w	$f010			; PMOVE (a0),CRP
	dc.w	$4c00
	rte

;======================================================================
;
;	This function returns the MMU TC register.  It assumes a 68020 
;	system with MMU, or a 68030 based system (eg, test for MMU before
;	you call this, or you wind up in The Guru Zone).  
;
;	ULONG GetTC()
;
;======================================================================

_GetTC:
	move.l	4,a6			; Get ExecBase
	move.l	a5,-(sp)
	subq.l	#4,sp			; Make a place to dump TC
	move.l	sp,a0
	lea	2$,a5			; Get the start of the supervisor code
	CALLSYS	Supervisor
	move.l	(sp),d0			; Here's the result
	addq.l	#4,sp
	move.l	(sp)+,a5
	rts
2$
	dc.w	$f010			; PMOVE TC,(a0)
	dc.w	$4200
	rte

;======================================================================
;
;	This function sets the MMU TC register.  It assumes a 68020 
;	system with MMU, or a 68030 based system (eg, test for MMU before
;	you call this, or you wind up in The Guru Zone).  
;
;	void SetTC(ULONG)
;
;======================================================================

_SetTC:
	lea	4(sp),a0		; Get address of our new TC value
	move.l	4,a6			; Get ExecBase
	move.l	a5,-(sp)
	lea	2$,a5			; Get the start of the supervisor code
 	CALLSYS	Supervisor
	move.l	(sp)+,a5
	rts
2$
	dc.w	$f010			; PMOVE (a0),TC
	dc.w	$4000
	rte


;**********************************************************************
;
;	This section contains functions that identify and operate on
;	FPU things.  
;
;**********************************************************************

	public	_GetFPUType	; Gets the FPU type

;======================================================================
;
;	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)

ROMBash:	ROMBash.o
		ln $*.o -o ROMBash $(LFLAGS)
SHAR_EOF
cat << \SHAR_EOF > RomBash.uu

begin 644 ROMBash
M```#\P`````````#``````````(```2O````JP````$```/I```$KT[Z`:1.T
M5?_Z0J=(>0`#``!.NA&R4$\K0/_Z0FW__DAY``,``"\M__I(>0#\``!.NA%J.
M3^\`#%)M__X,;0!D__YMW$AY``,``"\M__I.NA&V4$].74YU3E7_HD'Z`.HKR
M2/_H0BW_[$*G3KH1@EA/*T#_[DAX__].NA%`6$\;0/_M2&W_WDZZ$2983T'MW
M_]XK2/_$0J=(;?^V0J=(>@"R3KH1D$_O`!!*0&<82'H`QDAZ`*M.N@5L4$\_/
M/``43KH.KE1/*6W_RH)>.WP`"O_22&W_MDZZ$0)83T'M_ZI#[?_6(-D@V4ZZ*
M_QY(;?^V3KH0Z%A/0>W_HD/M_]8@V2#92&W_JDAM_Z).NA&F4$\O+?^F+RW_B
MHDAZ`&E.N@4&3^\`#$AM_[9.NA!86$](;?_>3KH1)EA/<``0+?_M+P!.NA#:=
M6$].74YU4D]-0F%S:`!T:6UE<BYD979I8V4`17)R;W(Z($-A;B=T(&=E="`BS
M)7,B"@!T:6UE<BYD979I8V4`1$].13H@16QA<'-E9"!T:6UE(#T@)6QD+B4V+
M;&0@<V5C;VYD<PH`87!#[():1>R"6K7)9@XR/``4:PAT`"+"4<G__"E/@F(LN
M>``$*4Z"9DCG@(`(+@`$`2EG$$OZ``A.KO_B8`9"I_-?3G-#^@`@3J[^:"E`9
M@FIF#"X\``.`!TZN_Y1@!$ZZ`!I03TYU9&]S+FQI8G)A<GD`2?D``'_^3G5."
M50``+PI(>0`!```P+().P?P`!B\`3KH/D"E`@FY03V840J=(>0`!``!.N@\:C
M4$\N;()B3G4@;()N0F@`!"!L@FXQ?``!`!`@;()N,7P``0`*(&R"8B`L@F*0H
MJ``$4(`I0()R(&R"<B"\34%.6$*G3KH/7B1`2JH`K%A/9RXO+0`,+RT`""\*,
M3KH`KCE\``&"=B!L@FX`:(````0@;()N`&B````*3^\`#&!"2&H`7$ZZ#ZI(]
M:@!<3KH/2BE`@G@@;()X2J@`)%!/9Q`@;()X(F@`)"\13KH.!EA/+RR">"\*!
M3KH":"EL@GB"?%!/3KH.!B!L@FX@@$ZZ#B8@;()N(4``!F<62'@#[4AZ`"I.<
MN@X"(&R";B%```Q03R\L@GP_+(*`3KK]$$)G3KH,(%!/)%].74YU*@!.50``G
M2.<,,"1M`!`@;0`(2J@`K&<8(&T`""`H`*SE@"@`($0@*``0Y8`F0&`$)FR"3
M4!`32(!(P-"M``Q4@#E`@H)"IS`L@H)(P"\`3KH.(BE`@H103V8(3-\,,$Y=C
M3G40$TB`.@`_!2!+4H@O""\L@H1.N@%^,`5(P"!`T>R"A$/Z`400V6;\/RT`I
M#B\*+RR"A$ZZ`3H@;(*$0C!0`#E\``&"@#`%2,#0K(*$)D!2BR1+3^\`%!`3=
M2(`Z`+!\`"!G&+I\``EG$KI\``QG#+I\``UG!KI\``IF!%*+8-@,$P`@;7H,;
M$P`B9BY2BR!+4HL0$$B`.@!G'B!*4HH0A;I\`")F$`P3`")F!%*+8`9"*O__6
M8`)@UF`X($M2BQ`02(`Z`&<FNGP`(&<@NGP`"6<:NGP`#&<4NGP`#6<.NGP`O
M"F<(($I2BA"%8,X@2E**0A!*168"4XM2;(*`8`#_6D(20J<P+(*`4D!(P.6`"
M+P!.N@T`*4""?%!/9@A";(*`8`#^V'H`)FR"A&`D,`5(P.6`(&R"?"&+"``@T
M2R`(2AAF_)'`4X@P"%)`2,#7P%)%NFR"@&W6,`5(P.6`(&R"?$*P"`!@`/Z4F
M(``P/'__8`0P+P`,(&\`!$H89OQ32")O``A30!#95\C__&<"0A`@+P`$3G5,7
M[P,```0@"#(O``Q@`A#95\G__&<&4D%@`D(84<G__$YU3E4``$CG#C`D;0`(N
M0J=(>@".3KH,QBE`@HA03V8(3-\,<$Y=3G4@;0`,(F@`)"\I``1.N@T"*`!8B
M3V=22'H`;2!$+R@`-DZZ#-0F0$J`4$]G-$AX`^TO"TZZ"VPL`%!/9R0@!N6`$
M*@`@125H``@`I"5&`)Q(>`/M2'H`.$ZZ"T@E0`"@4$\O!$ZZ#*!83R\L@HA.Y
MN@N*0JR"B%A/8(!I8V]N+FQI8G)A<GD`5TE.1$]7`"H`3E4``$AM``PO+0`(D
M2'H$8$ZZ`)A/[P`,3EU.=4Y5``!(YP@@)&T`#@QM``0`$F8((&T`""@08!Q*G
M;0`,;PP@;0`(<``P$"@`8`H@;0`(,!!(P"@`0FT`$DIM``QL$$1M``Q*A&P(/
M1(0[?``!`!(R+0`,2,$@!$ZZ`Y!![(`"4XH4L```,BT`#$C!(`1.N@.&*`!F,
MVDIM`!)G!E.*%+P`+2`*3-\$$$Y=3G5.5?\B2.<(,"1M``@F;0`,0FW_^BMMD
M`!#__"!+4HL0$$B`.`!G``+NN'P`)68``LQ"+?\P.WP``?_X.WP`(/_V.WPG.
M$/_T($M2BQ`02(`X`+!\`"UF#D)M__@@2U*+$!!(@#@`N'P`,&80.WP`,/_V\
M($M2BQ`02(`X`+A\`"IF&"!M__Q4K?_\.U#_\B!+4HL0$$B`.`!@,D)M__)@^
M'#`M__+!_``*T$20?``P.T#_\B!+4HL0$$B`.``P!%)`0>R`%`@P``(``&;40
MN'P`+F9:($M2BQ`02(`X`+!\`"IF&"!M__Q4K?_\.U#_]"!+4HL0$$B`.`!@H
M,D)M__1@'#`M__3!_``*T$20?``P.T#_]"!+4HL0$$B`.``P!%)`0>R`%`@P,
M``(``&;4.WP``O_PN'P`;&82($M2BQ`02(`X`#M\``3_\&`0N'P`:&8*($M2'
MBQ`02(`X`#`$2,!@>CM\``C_[F`6.WP`"O_N8`X[?``0_^Y@!CM\__;_[C\M>
M__!(;?\P/RW_[B\M__Q.NOWD*T#_ZC`M__!(P-&M__Q/[P`,8%P@;?_\6*W_?
M_")0*TG_ZB`)2AEF_)/`4XD[2?_P8$H@;?_\5*W__#@00>W_+RM(_^H0A&`HE
MD+P```!C9^)3@&>2D+P````+9P#_<EF`9[)5@&<`_W!7@&<`_W)@S$'M_S"19
M[?_J.TC_\#`M__"P;?_T;P8[;?_T__!*;?_X9V@@;?_J#!``+6<*(&W_Z@P0B
M`"MF+@QM`##_]F8F4VW_\B!M_^I2K?_J$!!(@#\`3I*P?/__5$]F"G#_3-\,B
M$$Y=3G5@%C\M__9.DK!\__]43V8$</]@Y%)M__HP+?_R4VW_\K!M__!NW$)M;
M_^Y@("!M_^I2K?_J$!!(@#\`3I*P?/__5$]F!'#_8+!2;?_N(&W_ZDH09PHPE
M+?_NL&W_]&W.,"W_[M%M__I*;?_X9BA@&#\\`"!.DK!\__]43V8&</]@`/]X4
M4FW_^C`M__)3;?_RL&W_\&[:8!8_!$Z2L'S__U1/9@9P_V``_U)2;?_Z8`#]2
M"#`M__I@`/]"2.=(`$*$2H!J!$2`4D1*@6H&1($*1``!83Y*1&<"1(!,WP`2T
M2H!.=4CG2`!"A$J`:@1$@%)$2H%J`D2!81H@`6#8+P%A$B`!(A]*@$YU+P%A/
M!B(?2H!.=4CG,`!(04I!9B!(038!-`!"0$A`@,,B`$A`,@*"PS`!0D%(04S?9
M``Q.=4A!)@$B`$)!2$%(0$)`=`_0@-.!MH%B!)*#4D!1RO_R3-\`#$YU3E4`+
M`$AL@*P_+0`(3KH`"%Q/3EU.=4Y5```O!#@M``@O+0`*/P1.N@`PN'P`"EQ/*
M9B0@;0`*$"@`#$B`"```!V<4/SS__R\M``I.N@#T7$\H'TY=3G5@^$Y5```O<
M"B1M``H@4K'J``1E&#`M``C`?`#_/P`O"DZZ`,A<3R1?3EU.=2!24I(0+0`)3
M$(!(@,!\`/]@Z$Y5```O"D'L@)8D2"!*U?P````6+PAA$%A/0>R"3K7(9>HDS
M7TY=3G5.50``2.<(("1M``AX`"`*9@IP_TS?!!!.74YU2BH`#&=0""H``@`,%
M9PP_//__+PIA4C@`7$\0*@`-2(`_`$ZZ!1R(0`@J``$`#%1/9PHO*@`(3KH"X
M+EA/""H`!0`,9Q(O*@`23KH"P"\J`!).N@(44$]"DD*J``1"J@`(0BH`##`$2
M8)!.5?_^2.<(("1M``A!^O]&*4B"C`@J``0`#&<*</],WP003EU.=0@J``(`"
M#&<P(%*1Z@`(.`@_!"\J``@0*@`-2(`_`$ZZ`H"P1%!/9Q`(Z@`$``Q"DD*J@
M``1P_V#`#&W__P`,9A`(J@`"``Q"DD*J``1P`&"H2JH`"&8(+PI.N@":6$\,`
M:@`!`!!F*AMM``W__S\\``%(;?__$"H`#4B`/P!.N@(BL'P``5!/9J`P+0`,"
M8`#_:B2J``@P*@`02,#0J@`()4``!`CJ``(`#"!24I(0+0`-$(!(@,!\`/]@/
M`/\^3E4``"\*0>R`EB1(2BH`#&<8U?P````60>R"3K7(90AP`"1?3EU.=6#BX
M0I)"J@`$0JH`""`*8.I.5?_\+PHD;0`(/SP$`$ZZ`,`K0/_\5$]F&#5\``$`<
M$"!*T?P````.)4@`""1?3EU.=35\!```$`CJ``$`#"5M__P`"!`J``U(@#\`B
M3KH`XDI`5$]G!@`J`(``#&#.3E4``$CG`#`D;():8!0F4B`J``10@"\`+PI.6
MN@2F4$\D2R`*9NA"K():3-\,`$Y=3G5.50``+PI!^O_&*4B"D$*G("T`"%"`&
M+P!.N@0V)$!*@%!/9@AP`"1?3EU.=22L@EHE;0`(``0I2H):(`I0@&#F3E4`)
M`'``,"T`""\`8;)83TY=3G5.50``2.<`,)?+)&R"6F`.(&T`"%&(L<IG$B9*\
M)%(@"F;N</],WPP`3EU.=2`+9P0FDF`$*5*"6B`J``10@"\`+PI.N@/X<`!0:
M3V#83E4``"\*,"T`",'\``8D0-7L@FY*;0`(;0XP+0`(L&R"3FP$2I)F#CE\@
M``*"E'#_)%].74YU,"T`",'\``8@;()N+S`(`$ZZ`L9*@%A/9P1P`6`"<`!@2
MV$Y5```O+0`(3KH"D$J`6$]F#DZZ`IHY0(*4</].74YU<`!@^$Y5``!(YPP@T
M."T`"$ZZ`'`P!,'\``8D0-7L@FY*1&T*N&R"3FP$2I)F$#E\``*"E'#_3-\$7
M,$Y=3G4P*@`$P'P``V8*.7P`!8*4</]@Y'``,"T`#B\`+RT`"B\23KH"9BH`Y
ML+S_____3^\`#&8,3KH"&CE`@I1P_V"X(`5@M$Y5__Q(>!``0J=.N@-0*T#_S
M_`@```Q03V<22FR"=F8(("W__$Y=3G5.N@`&<`!@]$Y5``!(>``$2'H`'$ZZ9
M`?`O`$ZZ`@(_/``!3KH`#D_O``Y.74YU7D,*`$Y5``!*K(*,9P8@;(*,3I`_N
M+0`(3KH`"%1/3EU.=4Y5__PO!#`M``A(P"M`__Q*K()N9RAX`&`*/P1.N@#^:
M5$]21+AL@DYM\#`L@D[!_``&+P`O+()N3KH"1%!/2JR"D&<&(&R"D$Z02JR")
M5&<*+RR"5$ZZ`6A83TJL@I9G""!L@I8@K(*:2JR"GF<*+RR"GDZZ`9!83TJL/
M@J)G"B\L@J).N@&`6$]*K(*F9PHO+(*F3KH!<%A/2JR"JF<*+RR"JDZZ`6!81
M3RQX``0(+@`$`2EG%"\-2_H`"DZN_^(J7V`&0J?S7TYS2JR">&8P2JR"A&<HZ
M,"R"@DC`+P`O+(*$3KH!G#`L@H!20$C`Y8`O`"\L@GQ.N@&(3^\`$&`.3KH!8
M<B\L@GA.N@'06$\@+?_\+FR"8DYU*!].74YU3E4``$CG#B`X+0`(,`3!_``&I
M)$#5[()N2D1M"KAL@DYL!$J29A`Y?``"@I1P_TS?!'!.74YU""H`!P`$9@@OS
M$DZZ``I83T*2<`!@XB(O``0L;()J3N[_W"(O``0L;()J3N[_@B(O``0L;()JP
M3N[_N"QL@FI.[O_*+&R":D[N_WPB+P`$+&R":D[N_RA,[P`&``0L;()J3N[_W
MXBQL@FI.[O_$3OH``B(O``0L;()J3N[_IDSO``X`!"QL@FI.[O_02.<!!$SOT
M((``#"QL@F9.KO^43-\@@$YU(F\`!"QL@F9.[OX^3OH``B)O``0L;()F3N[^O
M8DSO`P``!"`O``PL;()F3N[]BB)O``0L;()F3N[^GB`O``0L;()F3N[^MD[ZZ
M``),[P`#``0L;()F3N[_.DCG`P`B;P`,+&R"9DZN_CA,WP#`3G5.^@`"(F\`#
M!"QL@F9.[O[:+&R"9D[N_WQ.^@`"(F\`!"`O``@L;()F3N[_+B`O``0L;()F!
M3N[^L"!O``0L;()F3N[^C"!O``1,[P(!``@B+P`0+&R"9D[N_D0L;()F(F\`,
M!"`O``A.[OW8(F\`!"QL@F9.[OZ8(F\`!"QL@F9.[OZ&3.\``P`$+&R"9D[NF
M_LX@;P`$+&R"9D[N_H!,[P,```0L;(*(3N[_H"!O``0L;(*(3N[_IB!O``0LM
M;(*(3N[_LDSO`P``!"QL@EY.[O_0```#[`````$````!```"&@````````/RJ
M```#Z@```)8P,3(S-#4V-S@Y86)C9&5F````("`@("`@("`@,#`P,#`@("`@U
M("`@("`@("`@("`@(""00$!`0$!`0$!`0$!`0$!`#`P,#`P,#`P,#$!`0$!`(
M0$`)"0D)"0D!`0$!`0$!`0$!`0$!`0$!`0$!`4!`0$!`0`H*"@H*"@("`@("0
M`@("`@("`@("`@("`@("0$!`0"```````````````````0`````!`````````
M``````````````$!`````0`````````````````````!`@````$`````````'
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
G````````````````%`````````````````/R```#ZP````$```/RM
``
end
size 5484
SHAR_EOF
cat << \SHAR_EOF > SetCPU.uu

begin 644 SetCPU
M```#\P`````````#``````````(```<'````N`````$```/I```'!T[Z"V1([
MYP`,+'@`!`@N``(!*6<,(#P``0F^3-\P`$YU""X``0$I9B`(+@```2EF#"`\'
M``$)H$S?,`!.=2`\``$)JDS?,`!.=2`\``$)M$OZ``Q.KO_B3-\P`$YU3GH0T
M`BA!",$`!`B!``!.>Q`"3GH0`@@!``1G#"`\``$)O@CN``(!*2(,3GL0`DYS&
M+'@`!`@N``$!*68$<`!.=2\-2_H`"DZN_^(J7TYU3GH``DYS("\`!"QX``0(H
M+@`!`2EF`DYU+PU+^@`*3J[_XBI?3G5.>P`"3G,L>``$2.<`'")\`````$ZN1
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!O``0L>``$(
M+PU+^@`*3J[_XBI?3G7P$$X`3G,@;P`$+'@`!"\-2_H`"DZN_^(J7TYU\!!,^
M`$YS+'@`!"\-68\@3TOZ``Y.KO_B(!=8CRI?3G7P$$(`3G-![P`$+'@`!"\-Q
M2_H`"DZN_^(J7TYU\!!``$YS+PTL>``$""X`!`$I9@9P`"I?3G5+^@`*3J[_S
MXBI?3G4@/``!#1'S)W(`$B\``0Q!`!AG!B`\``$-$O-?3G,V.#`P,``V.#`QE
M,``V.#`R,``V.#`S,``V.#@U,0`V.#@X,0`V.#@X,@!&4%4`34U5`$Y5__X@V
M;0`(2A!G/"!M``Q*$&<T(&T`"%*M``@0$$B`P'P`WR!M``Q2K0`,$A!(@<)\L
M`-^P068(.WP``?_^8`1";?_^9P)@O"!M``A*$&8*2FW__F<$<`%@`G``3EU."
M=4Y5```,K0`!#1$`"&862'H`1DZZ#5!83TIL@"1G!$)L@#A@'@RM``$-$@`(2
M9A1(>@`M3KH-,%A/2FR`*F<$0FR`.$JM``AG"DIL@#!G!$)L@#A.74YU-C@X!
M.#$@`#8X.#@R(`!.5?_X0J<@+0`(T*T`#"\`3KH8?%!/*T#__&8&<`!.74YUT
M3KH8B"`M__S0K0`,4X`B+0`,4X%&@<"!*T#_^"`M``C0K0`,+P`O+?_\3KH8I
M:E!/+RW_^"\M``A.NA@"4$\K0/_\3KH8@B`M__Q@L$Y5_^A"K?_L0JW_Z$AX;
M$`!(>0`$``!.NO]Z4$\K0/_L2'@0`$AX`@!.NO]H4$\K0/_H2JW_[&<&2JW_"
MZ&8P2JW_Z&<.2'@"`"\M_^A.NA?\4$]*K?_L9Q!(>0`$```O+?_L3KH7YE!/9
M<`!.74YU2'D`!```+RW_[$AY`/P``$ZZ%XY/[P`,0JW__"`M__SE@"!M_^@B+
M+?_\=!'EH<*\____\`C!```A@0@`4JW__`RM````?O_\9=(@;?_H("W_[,"\<
M____\("\````!2%``?@@;?_H("W_[-"\``(``,"\____\("\````!2%``?PKU
M?`!_`@+_]"MM_^C_^$AM__1.NOT$6$\P+0`(P'P`#TC`<A#CH'(/DFT`",)\#
M``](P70,Y:&`@8"\@,`%`"M`__`O+?_P3KK]#%A/<`%@`/\L3E7_\$*M__1"O
MK?_P0J=.NOSR6$](;?_X3KK\D%A/*VW__/_P(&W_\"`H`?C`O/____`K0/_T/
M2'@"`"\M__!.NA;*4$](>0`$```O+?_T3KH6NE!/3EU.=4Y5_]@[?``!__Q"\
M;?_Z0JW_WCM\``C_V`QM``(`"&U"(&T`"B)H``0,$0`_9C1(>@3"2'H$GDZZ)
M"L)03TAZ!+E.N@JX6$](>@3@3KH*KEA/2'H%!DZZ"J183T)G3KH3Z%1/*WP`(
M``$!_^Y.NOLZ*T#_]@QM``$`"&\``D`[?``!_]Q@``(:#&P`!8`X9DY";?_:_
M<``P+?_<Y8`@;0`*+S`(`#`M_]K`_``&0>R``B\P"`!.NOR"4$]*0&<4,"W_?
MVL#\``9![(`&,;P``0@`8`Q2;?_:#&T`"?_:9;9(>@2K<``P+?_<Y8`@;0`*4
M+S`(`$ZZ_$103TI`9PHY?``%@#A@``&82'H$B7``,"W_W.6`(&T`"B\P"`!.<
MNOP<4$]*0&<*.WP``?_Z8``!<$AZ!&EP`#`M_]SE@"!M``HO,`@`3KK[]%!/^
M2D!G"CM\``+_^F```4A(>@1+<``P+?_<Y8`@;0`*+S`(`$ZZ^\Q03TI`9PA";
M;?_88``!(DAZ!"IP`#`M_]SE@"!M``HO,`@`3KK[IE!/2D!G"$)M__Q@``#\)
M2'H$#G``,"W_W.6`(&T`"B\P"`!.NON`4$]*0&<,*WP```$`_^Y@``#22'H#*
MZ7``,"W_W.6`(&T`"B\P"`!.NOM64$]*0&<,*WP````!_^Y@``"H2'H#Q'``_
M,"W_W.6`(&T`"B\P"`!.NOLL4$]*0&<*("W_[H&M__9@?DAZ`Z)P`#`M_]SE3
M@"!M``HO,`@`3KK[!%!/2D!G#"`M_^Y&@,&M__9@5$AZ`X!P`#`M_]SE@"!M7
M``HO,`@`3KKZVE!/2D!G#"`M_^[I@(&M__9@*DAZ`UQP`#`M_]SE@"!M``HOM
M,`@`3KKZL%!/2D!G#"`M_^[I@$:`P:W_]E)M_]PP+?_<L&T`"&4`_=X@+?_V+
M",``#2\`3KKY%%A/3KKX8BM`_^9.NOH"*T#_XDIM__QG3$ZZ^1XK0/_>9T).%
MNOFN"```'V8L#&T``?_Z9B(_+?_83KK[=E1/2D!F%$AZ`MI.N@?Z6$\_/``*+
M3KH1/%1/8`P,;0`"__IF!$ZZ_(Y(>@+I3KH'V%A/#*T``0FJ_^9B4@RM``$)8
MJO_F9A9(>@+43KH'NEA/2FR`#&<$0FR`.&`42'H"Q4ZZ!Z183TIL@`9G!$)L2
M@#@O+?_B3KKZ+%A/2'H"KDZZ!X983S\L@#A.NA#(5$\,K0`!";[_YF862'H"$
MDDZZ!VA83TIL@!AG!$)L@#A@%$AZ`H-.N@=26$]*;(`29P1";(`X+RW_XDZZP
M^=I83PRM``$,\__>9A1(>@)B3KH'*EA/2FR`'F<$0FR`.$JM_]YG"DIL@#9G-
M!$)L@#A*K?_>9Q1.NOB4"```'V<*2'H"-4ZZ!O983TZZ]YPK0/_V2'H"+$ZZ\
M!N183P@M``#_^68*2'H"(DZZ!M)83TAZ`AM.N@;(6$\,K0`!";[_YF9@2'H"G
M#4ZZ!K183P@M``3_^68*2'H!_4ZZ!J)83TAZ`?9.N@:86$\(+0``__AF#$AZ4
M`?-.N@:&6$]@"DAZ`?!.N@9Z6$\(+0`$__AF"DAZ`>5.N@9H6$](>@'>3KH&/
M7EA/2'H!VDZZ!E183RM\``$)OO_F9Q`@+?_V",``"R\`3KKW"EA//RR`.$ZZ5
M#WQ43TY=3G6;-VU3971#4%4@)7,@8GD@1&%V92!(87EN:66;,&T*`%8Q+C0`K
M57-A9V4Z(%-E=$-052!;24Y35'Q$051!72!;6TY/74-!0TA%?%M.3UU"55)3`
M5%T*`"`@("`@("`@("`@("`@6UM.3UU&05-44D]-(%M44D%075T@6TY/34U5Z
M5$535%T*`"`@("`@("`@("`@("`@6T-(14-+(#8X,'@P?#8X.#4Q?#8X.#AX@
M?$U-57Q&4%5="@!#2$5#2P!&05-44D]-`$Y/1D%35%)/30!44D%0`$Y/34U5O
M5$535`!$051!`$E.4U0`0T%#2$4`3D]#04-(10!"55)35`!.3T)54E-4`$5R1
M<F]R.B!#86XG="!G970@;65M;W)Y(&9O<B!&05-44D]-('1R86YS;&%T:6]NE
M"@!365-414TZ(``V.#`Q,"``-C@P,#`@``H`-C@P,S`@`#8X,#(P(``V.#@UL
M,2``1D%35%)/32``*$E.4U0Z(`!.3P!#04-(10`@`$Y/`$)54E-4*2`H1$%45
M03H@`$Y/0T%#2$4@`$-!0TA%(`!.3P!"55)35``I"@``87!#[(*21>R"DK7)7
M9@XR/``3:PAT`"+"4<G__"E/@I8L>``$*4Z"FDCG@(`(+@`$`2EG$$OZ``A.%
MKO_B8`9"I_-?3G-#^@`@3J[^:"E`@IYF#"X\``.`!TZN_Y1@!$ZZ`!I03TYU6
M9&]S+FQI8G)A<GD`2?D``'_^3G5.50``+PI(>0`!```P+(*&P?P`!B\`3KH/V
M>BE`@J)03V840J=(>0`!``!.N@\:4$\N;(*63G4@;(*B0F@`!"!L@J(Q?``!,
M`!`@;(*B,7P``0`*(&R"EB`L@I:0J``$4(`I0(*F(&R"IB"\34%.6$*G3KH/A
M+B1`2JH`K%A/9RXO+0`,+RT`""\*3KH`KCE\``&"JB!L@J(`:(````0@;(*B7
M`&B````*3^\`#&!"2&H`7$ZZ#UA(:@!<3KH/$BE`@JP@;(*L2J@`)%!/9Q`@O
M;(*L(F@`)"\13KH.!EA/+RR"K"\*3KH":"EL@JR"L%!/3KH.!B!L@J(@@$ZZ'
M#B8@;(*B(4``!F<62'@#[4AZ`"I.N@X"(&R"HB%```Q03R\L@K`_+(*T3KKWE
MX$)G3KH,(%!/)%].74YU*@!.50``2.<,,"1M`!`@;0`(2J@`K&<8(&T`""`HU
M`*SE@"@`($0@*``0Y8`F0&`$)FR"B!`32(!(P-"M``Q4@#E`@K9"IS`L@K9(&
MP"\`3KH.#"E`@KA03V8(3-\,,$Y=3G40$TB`.@`_!2!+4H@O""\L@KA.N@%^7
M,`5(P"!`T>R"N$/Z`400V6;\/RT`#B\*+RR"N$ZZ`3H@;(*X0C!0`#E\``&"L
MM#`%2,#0K(*X)D!2BR1+3^\`%!`32(`Z`+!\`"!G&+I\``EG$KI\``QG#+I\^
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;(*T8`#_6D(20J<P+(*T4D!(P.6`+P!.N@SJ*4""L%!/9@A";(*T8`#^V'H`2
M)FR"N&`D,`5(P.6`(&R"L"&+"``@2R`(2AAF_)'`4X@P"%)`2,#7P%)%NFR"/
MM&W6,`5(P.6`(&R"L$*P"`!@`/Z4(``P/'__8`0P+P`,(&\`!$H89OQ32")O?
M``A30!#95\C__&<"0A`@+P`$3G5,[P,```0@"#(O``Q@`A#95\G__&<&4D%@,
M`D(84<G__$YU3E4``$CG#C`D;0`(0J=(>@".3KH,>"E`@KQ03V8(3-\,<$Y=H
M3G4@;0`,(F@`)"\I``1.N@RP*`!83V=22'H`;2!$+R@`-DZZ#((F0$J`4$]G>
M-$AX`^TO"TZZ"VPL`%!/9R0@!N6`*@`@125H``@`I"5&`)Q(>`/M2'H`.$ZZ_
M"T@E0`"@4$\O!$ZZ#$Y83R\L@KQ.N@N,0JR"O%A/8(!I8V]N+FQI8G)A<GD`J
M5TE.1$]7`"H`3E4``$AM``PO+0`(2'H$8$ZZ`)A/[P`,3EU.=4Y5``!(YP@@"
M)&T`#@QM``0`$F8((&T`""@08!Q*;0`,;PP@;0`(<``P$"@`8`H@;0`(,!!(7
MP"@`0FT`$DIM``QL$$1M``Q*A&P(1(0[?``!`!(R+0`,2,$@!$ZZ`Y!![(`Z3
M4XH4L```,BT`#$C!(`1.N@.&*`!FVDIM`!)G!E.*%+P`+2`*3-\$$$Y=3G5.G
M5?\B2.<(,"1M``@F;0`,0FW_^BMM`!#__"!+4HL0$$B`.`!G``+NN'P`)68`>
M`LQ"+?\P.WP``?_X.WP`(/_V.WPG$/_T($M2BQ`02(`X`+!\`"UF#D)M__@@#
M2U*+$!!(@#@`N'P`,&80.WP`,/_V($M2BQ`02(`X`+A\`"IF&"!M__Q4K?_\&
M.U#_\B!+4HL0$$B`.`!@,D)M__)@'#`M__+!_``*T$20?``P.T#_\B!+4HL0[
M$$B`.``P!%)`0>R`3`@P``(``&;4N'P`+F9:($M2BQ`02(`X`+!\`"IF&"!MN
M__Q4K?_\.U#_]"!+4HL0$$B`.`!@,D)M__1@'#`M__3!_``*T$20?``P.T#_N
M]"!+4HL0$$B`.``P!%)`0>R`3`@P``(``&;4.WP``O_PN'P`;&82($M2BQ`0W
M2(`X`#M\``3_\&`0N'P`:&8*($M2BQ`02(`X`#`$2,!@>CM\``C_[F`6.WP`]
M"O_N8`X[?``0_^Y@!CM\__;_[C\M__!(;?\P/RW_[B\M__Q.NOWD*T#_ZC`MA
M__!(P-&M__Q/[P`,8%P@;?_\6*W__")0*TG_ZB`)2AEF_)/`4XD[2?_P8$H@G
M;?_\5*W__#@00>W_+RM(_^H0A&`HD+P```!C9^)3@&>2D+P````+9P#_<EF`,
M9[)5@&<`_W!7@&<`_W)@S$'M_S"1[?_J.TC_\#`M__"P;?_T;P8[;?_T__!*Z
M;?_X9V@@;?_J#!``+6<*(&W_Z@P0`"MF+@QM`##_]F8F4VW_\B!M_^I2K?_JM
M$!!(@#\`3I*P?/__5$]F"G#_3-\,$$Y=3G5@%C\M__9.DK!\__]43V8$</]@E
MY%)M__HP+?_R4VW_\K!M__!NW$)M_^Y@("!M_^I2K?_J$!!(@#\`3I*P?/__<
M5$]F!'#_8+!2;?_N(&W_ZDH09PHP+?_NL&W_]&W.,"W_[M%M__I*;?_X9BA@K
M&#\\`"!.DK!\__]43V8&</]@`/]X4FW_^C`M__)3;?_RL&W_\&[:8!8_!$Z2V
ML'S__U1/9@9P_V``_U)2;?_Z8`#]"#`M__I@`/]"2.=(`$*$2H!J!$2`4D1*&
M@6H&1($*1``!83Y*1&<"1(!,WP`22H!.=4CG2`!"A$J`:@1$@%)$2H%J`D2!T
M81H@`6#8+P%A$B`!(A]*@$YU+P%A!B(?2H!.=4CG,`!(04I!9B!(038!-`!"Z
M0$A`@,,B`$A`,@*"PS`!0D%(04S?``Q.=4A!)@$B`$)!2$%(0$)`=`_0@-.!T
MMH%B!)*#4D!1RO_R3-\`#$YU3E4``$AL@.0_+0`(3KH`"%Q/3EU.=4Y5```OT
M!#@M``@O+0`*/P1.N@`PN'P`"EQ/9B0@;0`*$"@`#$B`"```!V<4/SS__R\M'
M``I.N@#T7$\H'TY=3G5@^$Y5```O"B1M``H@4K'J``1E&#`M``C`?`#_/P`O1
M"DZZ`,A<3R1?3EU.=2!24I(0+0`)$(!(@,!\`/]@Z$Y5```O"D'L@,XD2"!*:
MU?P````6+PAA$%A/0>R"AK7(9>HD7TY=3G5.50``2.<(("1M``AX`"`*9@IP]
M_TS?!!!.74YU2BH`#&=0""H``@`,9PP_//__+PIA4C@`7$\0*@`-2(`_`$ZZT
M!1R(0`@J``$`#%1/9PHO*@`(3KH"+EA/""H`!0`,9Q(O*@`23KH"P"\J`!).F
MN@(44$]"DD*J``1"J@`(0BH`##`$8)!.5?_^2.<(("1M``A!^O]&*4B"P`@JX
M``0`#&<*</],WP003EU.=0@J``(`#&<P(%*1Z@`(.`@_!"\J``@0*@`-2(`_;
M`$ZZ`H"P1%!/9Q`(Z@`$``Q"DD*J``1P_V#`#&W__P`,9A`(J@`"``Q"DD*JB
M``1P`&"H2JH`"&8(+PI.N@":6$\,:@`!`!!F*AMM``W__S\\``%(;?__$"H`[
M#4B`/P!.N@(BL'P``5!/9J`P+0`,8`#_:B2J``@P*@`02,#0J@`()4``!`CJI
M``(`#"!24I(0+0`-$(!(@,!\`/]@`/\^3E4``"\*0>R`SB1(2BH`#&<8U?P`Q
M```60>R"AK7(90AP`"1?3EU.=6#B0I)"J@`$0JH`""`*8.I.5?_\+PHD;0`(T
M/SP$`$ZZ`,`K0/_\5$]F&#5\``$`$"!*T?P````.)4@`""1?3EU.=35\!```P
M$`CJ``$`#"5M__P`"!`J``U(@#\`3KH`XDI`5$]G!@`J`(``#&#.3E4``$CGL
M`#`D;(*28!0F4B`J``10@"\`+PI.N@1Z4$\D2R`*9NA"K(*23-\,`$Y=3G5.'
M50``+PI!^O_&*4B"Q$*G("T`"%"`+P!.N@0@)$!*@%!/9@AP`"1?3EU.=22L:
M@I(E;0`(``0I2H*2(`I0@&#F3E4``'``,"T`""\`8;)83TY=3G5.50``2.<`:
M,)?+)&R"DF`.(&T`"%&(L<IG$B9*)%(@"F;N</],WPP`3EU.=2`+9P0FDF`$P
M*5*"DB`J``10@"\`+PI.N@/,<`!03V#83E4``"\*,"T`",'\``8D0-7L@J)**
M;0`(;0XP+0`(L&R"AFP$2I)F#CE\``*"R'#_)%].74YU,"T`",'\``8@;(*BR
M+S`(`$ZZ`L9*@%A/9P1P`6`"<`!@V$Y5```O+0`(3KH"D$J`6$]F#DZZ`IHYQ
M0(+(</].74YU<`!@^$Y5``!(YPP@."T`"$ZZ`'`P!,'\``8D0-7L@J)*1&T*7
MN&R"AFP$2I)F$#E\``*"R'#_3-\$,$Y=3G4P*@`$P'P``V8*.7P`!8+(</]@+
MY'``,"T`#B\`+RT`"B\23KH"9BH`L+S_____3^\`#&8,3KH"&CE`@LAP_V"X!
M(`5@M$Y5__Q(>!``0J=.N@+^*T#__`@```Q03V<22FR"JF8(("W__$Y=3G5.^
MN@`&<`!@]$Y5``!(>``$2'H`'$ZZ`?`O`$ZZ`@(_/``!3KH`#D_O``Y.74YU)
M7D,*`$Y5``!*K(+`9P8@;(+`3I`_+0`(3KH`"%1/3EU.=4Y5__PO!#`M``A(R
MP"M`__Q*K(*B9RAX`&`*/P1.N@#^5$]21+AL@H9M\#`L@H;!_``&+P`O+(*B1
M3KH"&%!/2JR"Q&<&(&R"Q$Z02JR"C&<*+RR"C$ZZ`6A83TJL@LIG""!L@LH@Y
MK(+.2JR"TF<*+RR"TDZZ`9)83TJL@M9G"B\L@M9.N@&"6$]*K(+:9PHO+(+:&
M3KH!<EA/2JR"WF<*+RR"WDZZ`6)83RQX``0(+@`$`2EG%"\-2_H`"DZN_^(J/
M7V`&0J?S7TYS2JR"K&8P2JR"N&<H,"R"MDC`+P`O+(*X3KH!<#`L@K120$C`_
MY8`O`"\L@K!.N@%<3^\`$&`.3KH!1B\L@JQ.N@%^6$\@+?_\+FR"EDYU*!].:
M74YU3E4``$CG#B`X+0`(,`3!_``&)$#5[(*B2D1M"KAL@H9L!$J29A`Y?``"W
M@LAP_TS?!'!.74YU""H`!P`$9@@O$DZZ``I83T*2<`!@XB(O``0L;(*>3N[_Y
MW"(O``0L;(*>3N[_@B(O``0L;(*>3N[_N"QL@IY.[O_*+&R"GD[N_WPB+P`$G
M+&R"GD[N_RA,[P`&``0L;(*>3N[_XBQL@IY.[O_$3OH``B(O``0L;(*>3N[_^
MIDSO``X`!"QL@IY.[O_02.<!!$SO((``#"QL@II.KO^43-\@@$YU3.\"`0`$D
M+&R"FD[N_S1.^@`"(F\`!"QL@II.[OYB3.\#```$("\`#"QL@II.[OV*3OH`N
M`DSO``,`!"QL@II.[O\Z(F\`!"QL@II.[O[:3OH``BQL@II.[O]\3OH``B)O:
M``0@+P`(+&R"FD[N_RX@;P`$+&R"FD[N_HPL;(*:(F\`!"`O``A.[OW8+&R"0
MFD[N_W8B;P`$+&R"FD[N_H9,[P`#``0L;(*:3N[^SB!O``0L;(*:3N[^@$SO.
M`P``!"QL@KQ.[O^@(&\`!"QL@KQ.[O^F(&\`!"QL@KQ.[O^R```#[`````$`(
M````````\`````$````!```+V@````````/R```#Z@```*0```'J``````'PY
M``````'V``````'\``````("``````((``````(.``````(4``````(8````"
M`#`Q,C,T-38W.#EA8F-D968````@("`@("`@("`P,#`P,"`@("`@("`@("`@2
M("`@("`@()!`0$!`0$!`0$!`0$!`0$`,#`P,#`P,#`P,0$!`0$!`0`D)"0D)5
M"0$!`0$!`0$!`0$!`0$!`0$!`0$!0$!`0$!`"@H*"@H*`@("`@("`@("`@("Q
M`@("`@("`@)`0$!`(``````````````````!``````$`````````````````R
M`````0$````!``````````````````````$"`````0``````````````````'
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M`````````````````````````````````````````````````````````````
M```````4`````````````````^P````)```````````````&````#````!(`P
G```8````'@```"0````J````,`````````/R```#ZP````$```/R-
``
end
size 8004
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.