New one for me: LLVM ERROR: Cannot encode high byte register in REX-prefixed instruction

Post Reply
User avatar

Topic author
tlovern
Active Contributor
Posts: 40
Joined: Tue Jul 21, 2020 10:44 am
Reputation: 0
Status: Offline

New one for me: LLVM ERROR: Cannot encode high byte register in REX-prefixed instruction

Post by tlovern » Sat Nov 18, 2023 11:43 am

trying to compile a module that have compiled successfully in the past....
sorry for the module size, but I couldn't add a .tlb as an attachment....

cannot even get a listing of where the error is. (cc/noop/list/show=all)

Code: Select all

//------------------------------------------------------------------------------
//
// rtl_c_virmem.c              	This module is responsible for mapping and
//                              allocating virtual memory zones (caches) for
//                              use by the application.
//
//                              Zone allocation is maintained in a linked List
//                              each node in the list contains a pointer to the
//                              linked list of blocks, which are the actual
//                              blocks of memory that has been allotted to the
//                              zone.
//
//                              Cached records are mapped to address ranges
//                              within each block. Holes are left at the end
//                              of the blocks when the record size is not
//                              an integer factor of the blocksize
//
// This routine builds a linked list of virutal memory zone data structures.
// Each node in the linked list corresponds to a virtual memory zone allocated
// from VMS. Each structure contains a pointer to a linked list of block
// data structures. Each block structure represents memory from a zone that
// has been allocated for use by the application. Records are written and
// read from the memory blocks. The program translates the record number into
// a block number and an offset into the block. This was necessary as VMS
// does not guarantee that blocks will be contiguous within a zone, or that
// they will be in order of allocation.
//
// Parameter                Data type       Description
//------------------------- --------------- ------------------------------
// (1) dscInstruction           *descriptor_s   Instruction to be performed
//                                              'W'  - write a record
//                                              'R'  - read a record
//                                              'C'  - clear a zone
//                                              'F'  - free a zone
//                                              'S'  - search a zone
//                                              'SX' - search a zone at the beginning
//                                              'M'  - move a zone into a buffer
//
// (2) dscZoneName              *descriptor_s   string with the name of the zone
//
// (3) dscRecordNumber          *descriptor_s   Record number to read/write
//
// (4) dscBuffer                *descriptor_s   Buffer holding record
//
// (5) dscSearch                *descriptor_s   Value to search for
//
// (6) dscStartRecord           *descriptor_s   Starting record number for search
//
// (7) dscFilChar               *descriptor_s   Char to init memory blocks to
//
// (8) dscDebugFlag             *descriptor_s   Debug flags
//
//
//
//date        Author           Modification(s)
//----------- ---------------- ---------------------------------------------
// 8-OCT-1999 Tim Lovern       New module as of this date. Written as direct
//                             replacement for mds$vir_mem (the DBL version)
//                             This was due the large number of incorrect
//                             assumptions made in that module about how
//                             memory is actually allocated.
//
//21-OCT-1999 Tim Lovern        Modified FindZone routine to use strcmp instead
//                              of strncmp
//
//------------------------------------------------------------------------------
//
//  Zone------------>Zone------------>Zone------------>NULL
//   |                |                |
//   +-->Block        +-->Block        +-->Block
//        |                |                |
//        +-->Block        +-->Block        +-->NULL
//             |                |
//             +-->NULL         +-->NULL
//------------------------------------------------------------------------------


#ifdef __DECC
# pragma module rtl_c_virmem
#else
# module rtl_c_virmem                
#endif

//------------------------------------------------------------------------------
// include header files as required
//------------------------------------------------------------------------------

#define __NEW_STARLET	1

#include <ctype.h>
#include <ints.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <varargs.h>

#include <lib$routines.h>
#include <libvmdef.h>
#include <libdef.h>
#include <descrip.h>
#include <starlet.h>
#include <ssdef.h>


//------------------------------------------------------------------------------
// typedef's an other misc declarations
//------------------------------------------------------------------------------

#define FOREVER		for(;;)	// infinite loop keyword

typedef struct dsc$descriptor_s DSCS_S;

//-------------------------------------------------------
// define the structure to hold a VM Block
//-------------------------------------------------------
typedef struct rVirMemBlock
{
	int64	iBaseAddress;			// base memory address for block
	int32	iRecordCount;			// count of records in block

	struct	rVirMemBlock	*prNext;	// pointer to next block in list

}	VIR_MEM_BLOCK;

//-------------------------------------------------------
// define the structure to hold a zone definition
//-------------------------------------------------------
typedef struct rVirMemZone
{
	char	*psName;			// VM zone name
	int64	iZoneId;       			// VM memory zone id
	int	iBlockCount;			// number of blocks in this zone
	int32	iRecordSize;			// (fixed) record size for block
	int32	iRecordsPerBlock;		// how many records fit in a block?

	struct rVirMemBlock	*prMemBlock;	// pointer to first block in zone
	struct rVirMemZone	*prNext;	// pointer to next VMZone

}	VIR_MEM_ZONE;

//-------------------------------------------------------
// constants for processing
//-------------------------------------------------------

const int64	kVM_Algorithm  = LIB$K_VM_FIXED;	// fixed size zones

const int64	kVM_Argument   = 16384;			// 16k blocks per request

const int64	kVM_Flags      = LIB$M_VM_GET_FILL0 &
				 LIB$M_VM_FREE_FILL0;	// bits 1 and 3 are set

const int64	kVM_ExtendSize = 32;		// extend size in pagelets

const int64	kVM_InitSize   = 32;		// initial size in pagelets

const int64	kVM_BlockSize  = 16384;		// 16k blocks per request

const int64	kVM_AllocBlockSize  = 512;	// 512 byte blocks per request

const int64	kVM_Alignment  = 16;		// quadword alignment

const int64	kVM_PageLimit  = 0;		// default to process limits

//------------------------------------------------------------------------------
// function prototypes for internal routines
//------------------------------------------------------------------------------

VIR_MEM_ZONE * FindZone(char *, VIR_MEM_ZONE *);

int CreateZone(VIR_MEM_ZONE **, char *);

int AddBlock2Zone(VIR_MEM_ZONE *, VIR_MEM_BLOCK **);

int AddRecord2Block(VIR_MEM_ZONE *, int, void *, int );

int GetRecordFromBlock(VIR_MEM_ZONE *, int, void *, int);

int RemoveVirMemZone(char *, VIR_MEM_ZONE **);

int RemoveBlock(VIR_MEM_ZONE *, int);

int FindDataInBlock(VIR_MEM_ZONE *, VIR_MEM_BLOCK *, void *, int, void **, int, int);

int FindDataInBlockStart(VIR_MEM_ZONE *, VIR_MEM_BLOCK *, void *, int, void **, int, int);

void KillBlockStructures(VIR_MEM_BLOCK *);

void TruncateString(char *);

int MoveZone2Buffer(char *, VIR_MEM_ZONE *, void *, int, int);

void DebugZoneDump(VIR_MEM_ZONE *);

//------------------------------------------------------------------------------
// module scope visible definitions
//------------------------------------------------------------------------------

int	igFATAL_VIR_MEM_ERROR = 0;	// could not do without one module scope variable
int	igDEBUG_FLAGS         = 0;	// had to put debug flags at module scope
int	igFillChar            = 0;	// fill character ended up lots of places

FILE *pfDEBUG_OUT = NULL;

//------------------------------------------------------------------------------
// mainline code starts here
//------------------------------------------------------------------------------
int  rtl_c_virmem(va_alist)
va_dcl
{
va_list	ArgPtr;				// for walking thru the optional stuff

int	iArgumentCount   = 0,		// number of arguments
	iCurrentArg      = 0,		// which one are we dealing with
	iStatus          = 0,		// return status variable
	iLoop            = 0,		// loop counter
	iBufferSize      = 0,		// size of the passed record
	iRecordNumber    = 0,		// record number to process
	iSearchForSize   = 0,		// size of the binary object to be searched for
	iSearchStart     = 0,		// starting record for search
	iRecordSearch    = 0,		// record within first block in search
	iCurrentRecord   = 0,		// current record number
	iCurrentBlock    = 0,		// current block number
	iBlockNumber     = 0,		// block number
	iRecordsPerBlock = 0,		// how many records are in a block
	iDebugFlags      = 0;		// used for debug purposes

char	*prFillChar    = NULL,
	*psInstruction = NULL,		// instruction for the call to this routine
	*psZoneName    = NULL;		// name of the VM zone we are dealing with

void	*prBuffer      = NULL,		// pointer to passed record
	*prSearchFor   = NULL;		// search for value

int64	iZoneId        = 0;		// current zone id

static VIR_MEM_ZONE	*prRootZone = NULL;	// root of our linked list

VIR_MEM_ZONE		*prThisZone = NULL;	// current zone

VIR_MEM_BLOCK		*prThisBlock = NULL;	// current block

DSCS_S		*dscInstruction  = NULL,
		*dscZoneName     = NULL,
		*dscRecordNumber = NULL,
		*dscBuffer       = NULL,
		*dscSearch       = NULL,
		*dscStartRecord  = NULL,
		*dscFilChar      = NULL,
		*dscDebugFlag    = NULL;

struct dsc64$descriptor dscCvtRecordNumber =
	{
		(short) 1,			// must be one
		DSC$K_DTYPE_L,			// data type (32 bit signed)
		DSC$K_CLASS_S,			// fixed size class
		(long) -1,			// must be -1
	  	(int64) sizeof(iRecordNumber),	// size in bytes
		(char *) &iRecordNumber		// ptr to the data
	};

struct dsc64$descriptor dscCvtStartRecord =
	{
		(short) 1,			// must be one
		DSC$K_DTYPE_L,			// data type (32 bit signed)
		DSC$K_CLASS_S,			// fixed size class
		(long) -1,			// must be -1
	  	(int64) sizeof(iSearchStart),	// size in bytes
		(char *) &iSearchStart		// ptr to the data
	};


	//-------------------------------------------------------
	// Go thru and figure out all the arguments
	//-------------------------------------------------------

	va_start(ArgPtr);
	va_count(iArgumentCount);

	psInstruction   = NULL;		// instruction for the call to this routine
	psZoneName      = NULL;		// name of the VM zone we are dealing with
	prBuffer        = NULL;		// pointer to passed record
	prSearchFor     = NULL;		// search for value

	prThisZone      = NULL;		// current zone
	prThisBlock     = NULL;		// current block

	dscInstruction  = NULL;
	dscZoneName     = NULL;
	dscRecordNumber = NULL;
	dscBuffer       = NULL;
	dscSearch       = NULL;
	dscStartRecord  = NULL;

	igFillChar = 0;

	if (iArgumentCount)
	{
		for (iCurrentArg = 0; iCurrentArg < iArgumentCount; iCurrentArg++)
			switch (iCurrentArg)
			{
			//-----------------------------------
			//--- instruction
			//-----------------------------------
			case 0:
				dscInstruction  = va_arg(ArgPtr, struct dsc$descriptor_s *);
				psInstruction   = malloc(dscInstruction->dsc$w_length + 1);
				memset(psInstruction, 0, dscInstruction->dsc$w_length + 1);
				strncpy(psInstruction, dscInstruction->dsc$a_pointer, dscInstruction->dsc$w_length);

				*psInstruction = toupper(*psInstruction);

				break;

			//-----------------------------------
			//--- Zone (cache) name
			//-----------------------------------
			case 1:
				dscZoneName = va_arg(ArgPtr, struct dsc$descriptor_s *);
				psZoneName  = malloc(dscZoneName->dsc$w_length + 1);
				memset(psZoneName, 0, dscZoneName->dsc$w_length + 1);
				strncpy(psZoneName, dscZoneName->dsc$a_pointer, dscZoneName->dsc$w_length);

				TruncateString(psZoneName);

				break;

			//-----------------------------------
			//--- record number
			//-----------------------------------
			case 2:
				dscRecordNumber = va_arg(ArgPtr, struct dsc$descriptor_s *);
				if (dscRecordNumber != NULL)
				{
					iStatus         = LIB$CVT_DX_DX((void *) dscRecordNumber, (void *) &dscCvtRecordNumber);
					if (iStatus != SS$_NORMAL)
						return 1;
				}

				break;

			//-----------------------------------
			//--- Buffer (record) information
			//-----------------------------------
			case 3:
				dscBuffer   = va_arg(ArgPtr, struct dsc$descriptor_s *);
				if (dscBuffer != NULL)
				{
					prBuffer    = dscBuffer->dsc$a_pointer;	// get the pointer to our record
					iBufferSize = dscBuffer->dsc$w_length;	// get the size of the record
				}
				break;

			//-----------------------------------
			//--- Search for data
			//-----------------------------------
			case 4:
			  	dscSearch       = va_arg(ArgPtr, struct dsc$descriptor_s *);

				if (dscSearch != NULL)
				{
					prSearchFor    = dscSearch->dsc$a_pointer;
					iSearchForSize = dscSearch->dsc$w_length;
				}

				break;

			//-----------------------------------
			//--- Search for start record number
			//-----------------------------------
			case 5:
				dscStartRecord  = va_arg(ArgPtr, struct dsc$descriptor_s *);

				if (dscStartRecord != NULL)
				{
					iStatus        = LIB$CVT_DX_DX((void *) dscStartRecord, (void *) &dscCvtStartRecord);
					if (iStatus != SS$_NORMAL)
						return 1;
				}

				break;

			//-----------------------------------
			//--- Fill Char
			//-----------------------------------
			case 6:
				dscFilChar = va_arg(ArgPtr, struct dsc$descriptor_s *);
				if (dscFilChar != NULL)
				{
					prFillChar = dscFilChar->dsc$a_pointer;	// get the pointer to our char
				      	igFillChar = *prFillChar;
				}
				break;

			//-----------------------------------
			//--- Debug Flags
			//-----------------------------------
			case 7:
				dscDebugFlag    = va_arg(ArgPtr, struct dsc$descriptor_s *);
				igDEBUG_FLAGS = 1;
				break;
			}
	}

	va_end(ArgPtr);

	//-------------------------------------------------------
	// check for debug information
	//-------------------------------------------------------

	if (igDEBUG_FLAGS)
	{
		if (pfDEBUG_OUT == NULL)
			pfDEBUG_OUT = fopen("debug_mem.dmp", "w");

		if (dscDebugFlag != NULL)
			if (strncmp(dscDebugFlag->dsc$a_pointer, "DUMP", dscDebugFlag->dsc$w_length) == 0)
				DebugZoneDump(prRootZone);

		if (strcmp(psInstruction, "SX"))
			fprintf(pfDEBUG_OUT,"\nI (%2.2s) %s #%i -> %50.50s",
				psInstruction, psZoneName, iRecordNumber, (char *)prBuffer);
		else
			fprintf(pfDEBUG_OUT,"\nI (%2.2s) %s #%i >> %50.50s",
				psInstruction, psZoneName, iRecordNumber, (char *)prSearchFor);
	}


	//-------------------------------------------------------
	// load any processing assumptions here
	//-------------------------------------------------------

//	APLDEF.ERRNB = 0;	// start out with success

	//-------------------------------------------------------
	// check the instruction (what are we supposed to do?)
	//-------------------------------------------------------
	switch(*psInstruction)
	{

	//---------------------------------------------
	// read a record from a cache
	//---------------------------------------------
	case 'R':

		//-----------------------------------
		// step one find the zone
		//-----------------------------------

		if (prRootZone == NULL)
		{
			memset(prBuffer, (int) ' ', (size_t) iBufferSize);
			iStatus = 0;
			break;
		}
		else
		{
			prThisZone = FindZone(psZoneName, prRootZone);
			if (prThisZone == NULL)
			{
				memset(prBuffer, (int) ' ', (size_t) iBufferSize);
				iStatus = 0;
				break;
			}

			//-----------------------------------
			// step two get the record
	  		//-----------------------------------

			iStatus = GetRecordFromBlock(prThisZone, iRecordNumber, prBuffer, iBufferSize);
			if (iStatus)
			{
				// couldn't get the record from the zone
				if (igFATAL_VIR_MEM_ERROR)
				{
					iStatus               = 1;
					igFATAL_VIR_MEM_ERROR = 1;

					break;
				}
			}
		}
		break;

	//---------------------------------------------
	// write a record to a cache
	//---------------------------------------------
	case 'W':

		//-----------------------------------
		// step one find zone
		// (create it if it doesn't exist)
		//-----------------------------------

		if (prRootZone == NULL)
		{
			iStatus = CreateZone(&prRootZone, psZoneName);
			if (iStatus)
			{
				igFATAL_VIR_MEM_ERROR = 1;	// we errored
				iStatus = 1;

				break;
			}

			prThisZone = prRootZone;
		}
		else
		{
			prThisZone = FindZone(psZoneName, prRootZone);
			if (prThisZone == NULL)
			{
				iStatus = CreateZone(&prRootZone, psZoneName);
				if (iStatus)
				{
					igFATAL_VIR_MEM_ERROR = 1;	// we errored
					iStatus = 1;

					break;
				}

				prThisZone = FindZone(psZoneName, prRootZone);
				if (prThisZone == NULL)
				{
					igFATAL_VIR_MEM_ERROR = 1;	// we errored
					iStatus = 1;

					break;
				}

			}

		}

		//-----------------------------------
		// step two write record
		//-----------------------------------

		iStatus = AddRecord2Block(prThisZone, iRecordNumber,
				prBuffer, iBufferSize);
		if (iStatus)
		{
			igFATAL_VIR_MEM_ERROR = 1;	// we errored
			iStatus = 1;

			break;
		}

		break;

	//---------------------------------------------
	// clear a zone (cache)
	//---------------------------------------------
	case 'C':

		//-----------------------------------
		// step one find the zone
		//-----------------------------------

		if (prRootZone == NULL)
		{
			iStatus = 0;	// nothing to do but call it
			break;		// an unqualified success
		}

		prThisZone = FindZone(psZoneName, prRootZone);
		if (prThisZone == NULL)
		{
			iStatus = 0;
			break;
		}


		iZoneId = prThisZone->iZoneId;

		iStatus = LIB$RESET_VM_ZONE_64((void *) &iZoneId);
		if (iStatus == SS$_NORMAL)
		{
			if (prThisZone->prMemBlock != NULL)
				KillBlockStructures(prThisZone->prMemBlock);

			iStatus = 0;

			prThisZone->iBlockCount = 0;
			prThisZone->prMemBlock  = NULL;

		}
		else
		{
			// we hosed
			igFATAL_VIR_MEM_ERROR = 1;	// we errored
			iStatus = 1;

			break;
		}


		break;

	//---------------------------------------------
	// free up a cache
	//---------------------------------------------
	case 'F':

		if (prRootZone == NULL)
		     	iStatus = 0;	// nothing to do...
		else
			iStatus = RemoveVirMemZone(psZoneName, &prRootZone);

		break;

	//---------------------------------------------
	// search a cache
	//---------------------------------------------
	case 'S':

		//-----------------------------------
		// find the zone first
		//-----------------------------------

		if (prRootZone == NULL)	// no zones to search
		{
			memset((void *) prBuffer, (int) ' ', (size_t) iBufferSize);
			iStatus = 0;
			break;
		}

		prThisZone = FindZone(psZoneName, prRootZone);
		if (prThisZone == NULL)				// our zone doesn't exist
		{
			memset((void *) prBuffer, (int) ' ', (size_t) iBufferSize);
			iStatus       = 0;
			iRecordNumber = 0;
			break;
		}


		//-----------------------------------
		// search buffer
		//-----------------------------------

		prThisBlock = prThisZone->prMemBlock;

		// need to deal with the starting record number...
		iRecordsPerBlock =  prThisZone->iRecordsPerBlock;

		if (iSearchStart < 1)
			iSearchStart = 1;

		iBlockNumber  = (iSearchStart - 1) / iRecordsPerBlock;
		iCurrentBlock = 0;

		iRecordSearch = (iSearchStart - 1) - (iBlockNumber * iRecordsPerBlock);

		if (iRecordSearch < 0)
			iRecordSearch = 0;

		while (iCurrentBlock != iBlockNumber)
		{
			prThisBlock = prThisBlock->prNext;
			if (prThisBlock == NULL)
				break;

			iCurrentBlock++;
		}

		if (prThisBlock == NULL)
		{
			memset((void *) prBuffer, (int) ' ', (size_t) iBufferSize);
			iStatus       = 0;
			iRecordNumber = 0;
			break;
		}


		FOREVER
		{

			if (strncmp(psInstruction, "SX", 2) == 0)
				iStatus = FindDataInBlockStart(prThisZone,
						prThisBlock,
						prSearchFor,
						iSearchForSize,
						&prBuffer,
						iBufferSize, iRecordSearch);

			else
				iStatus = FindDataInBlock(prThisZone,
						prThisBlock,
						prSearchFor,
						iSearchForSize,
						&prBuffer,
						iBufferSize, iRecordSearch);

			//-----------------------------------
			// iStatus will contain the record number
			// within the block if we get a hit
			//-----------------------------------
			if (iStatus)
				break;

			prThisBlock = prThisBlock->prNext;
			if (prThisBlock == NULL)
			{
				memset((void *) prBuffer, (int) ' ', (size_t) iBufferSize);
				iStatus       = 0;
				iRecordNumber = 0;

				//---------------------------------------------
				// convert record number to type of passed
				// record number and load the descriptor
				//---------------------------------------------
				iStatus       = LIB$CVT_DX_DX((void *) &dscCvtRecordNumber, (void *) dscRecordNumber);
				if (iStatus != SS$_NORMAL)
				{
					iStatus               = 1;
					igFATAL_VIR_MEM_ERROR = 1;
				}
				else
					iStatus = 0;

				break;
			}

			iCurrentBlock++;
		}

		//---------------------------------------------
		// If we got a hit then iStatus is holding the
		// record number. Otherwise it is 0. It is
		// possible that we have an error, so we look
		// igFATAL_VIR_MEM_ERROR
		//---------------------------------------------
		if (iStatus && !igFATAL_VIR_MEM_ERROR)
			iRecordNumber = (iStatus + (iCurrentBlock * iRecordsPerBlock));
		else
			iRecordNumber = 0;

		//---------------------------------------------
		// convert record number to type of passed
		// record number and load the descriptor
		//---------------------------------------------
		iStatus       = LIB$CVT_DX_DX((void *) &dscCvtRecordNumber, (void *) dscRecordNumber);
		if (iStatus != SS$_NORMAL)
		{
			iStatus               = 1;
			igFATAL_VIR_MEM_ERROR = 1;
		}
		else
			iStatus = 0;

		break;

	//---------------------------------------------
	// Move a cache
	//---------------------------------------------
	case 'M':

		iStatus = MoveZone2Buffer(psZoneName, prRootZone,
			  	prBuffer, iBufferSize, iRecordNumber);
		break;

	//---------------------------------------------
	// sort a cache
	//---------------------------------------------
	case 'O':
		break;

	//---------------------------------------------
	// error, unknown instruction
	//---------------------------------------------
	default:
		break;
	};

	//-------------------------------------------------------
	// here we need to sort out the error conditions and
	// return values before returning to our caller
	//-------------------------------------------------------

	if ((iStatus == 1) || (igFATAL_VIR_MEM_ERROR == 1))
	{
		//-----------------------------------
		// return an empty buffer on an error
		//-----------------------------------
		memset(prBuffer, (int) ' ', (size_t) iBufferSize);

		iStatus = 1;	// error
	}
	else
		iStatus = 0;	// success


	if (igDEBUG_FLAGS)
	{
		if (pfDEBUG_OUT == NULL)
			pfDEBUG_OUT = fopen("debug_mem.dmp", "w");

		fprintf(pfDEBUG_OUT,"\nO (%2.2s) %s #%i -> %50.50s",psInstruction, psZoneName, iRecordNumber, (char *)prBuffer);
	}

	//---------------------------------------------
	// release allocated data structures that are
	// non-persistent
	//---------------------------------------------

	free(psInstruction);
	free(psZoneName);


	return iStatus;

}

//-------------------------------------------------------
//find a zone by name
//-------------------------------------------------------
VIR_MEM_ZONE* FindZone(char *psName, VIR_MEM_ZONE *prZone)
{
VIR_MEM_ZONE *prThisZone = prZone;

	FOREVER
	{
		if (prThisZone == NULL)
			break;

		if (prThisZone->psName == NULL)
			break;

		if (!strcmp(prThisZone->psName, psName))
			break;

		prThisZone = prThisZone->prNext;

	}

	if (prThisZone != NULL)
	{
		if (prThisZone->psName == NULL)
			return NULL;
	}

		return prThisZone;

}
//-------------------------------------------------------
//create a new zone
//-------------------------------------------------------
int CreateZone(VIR_MEM_ZONE **prRoot, char *psName)
{
int	iStatus = 0;
int64	iZoneId = 0;		//64 bit zone id for vm call

VIR_MEM_ZONE	*prThisZone = NULL;


	//-------------------------------------------------------
	// first we need to find the end of the linked list
	// of zones so we can add our new zone
	//-------------------------------------------------------
	prThisZone = *prRoot;

	if (prThisZone == NULL)
	{
		prThisZone = malloc(sizeof(VIR_MEM_ZONE));
		if (prThisZone == NULL)
		{
			igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
			iStatus = -1;

			return iStatus;
		}

		*prRoot = prThisZone;
	}
	else
	{
		while(prThisZone->prNext != NULL)
			prThisZone = prThisZone->prNext;

		//-------------------------------------------------------
		// now we need to allocate the new node in the linked list
		// and set the pointer to it.
		//-------------------------------------------------------
		prThisZone->prNext = malloc(sizeof(VIR_MEM_ZONE));
		if (prThisZone->prNext == NULL)
		{
			igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
			iStatus = -1;

			return iStatus;
		}

		//-------------------------------------------------------
		// set the pointer (to simplify the reference) and
		// initialize to nulls (we always want to init to a known
		// value whenever we allocate anything from memory
		//-------------------------------------------------------
		prThisZone = prThisZone->prNext;
	}

	memset(prThisZone, 0, sizeof(VIR_MEM_ZONE));


	//-------------------------------------------------------
	// allocate space to hold the name and load it
	//-------------------------------------------------------
	prThisZone->psName = malloc(strlen(psName)+1);
	if (prThisZone->psName == NULL)
	{
		igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
		iStatus = -1;

		return iStatus;
	}

	strcpy(prThisZone->psName, psName);


	//-------------------------------------------------------
	// now we are ready to do the deed and create the VM zone
	//-------------------------------------------------------


	iStatus = LIB$CREATE_VM_ZONE_64((void *) &iZoneId,
			&kVM_Algorithm,
			&kVM_Argument,
			&kVM_Flags,
			&kVM_ExtendSize,
			&kVM_InitSize,
			&kVM_AllocBlockSize,
			&kVM_Alignment,
			&kVM_PageLimit);


	switch (iStatus)
	{
	//---------------------------------------------
	// successful completion
	//---------------------------------------------
	case SS$_NORMAL:

		prThisZone->iZoneId = iZoneId;

		iStatus = 0;	// our idea of success flag
		break;

	//---------------------------------------------
	// insufficient virtual memory
	//---------------------------------------------
	case LIB$_INSVIRMEM:

		igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
		iStatus = -1;

		break;

	//---------------------------------------------
	// invald argument
	//---------------------------------------------
	case LIB$_INVARG:

		igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
		iStatus = -1;

		break;

	//---------------------------------------------
	// invalid string descriptor for zone name
	//---------------------------------------------
	case LIB$_INVSTRDES:

		igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
		iStatus = -1;

		break;
	};


	return iStatus;
}

//-------------------------------------------------------
// add a memory block to a zone
//the zone must have already been found or created and
//is passed to us.
//-------------------------------------------------------
int AddBlock2Zone(VIR_MEM_ZONE *prZone, VIR_MEM_BLOCK **pprVmBlock)
{
VIR_MEM_BLOCK	*prThisBlock = NULL;

int	iStatus = 0;

int64	iBlockRequestSize = 0,
	iBaseAddress      = 0,
	iZoneId           = 0;

	//-------------------------------------------------------
	// need to figure out where this block needs to be added
	// is it the very first block in a zone, or a new block
	// being added to the end of the linked list of blocks
	//-------------------------------------------------------
	if (prZone->prMemBlock == NULL)
	{
		prZone->prMemBlock = malloc(sizeof(VIR_MEM_BLOCK));
		if (prZone->prMemBlock == NULL)
		{
			igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
			iStatus = -1;

			return iStatus;
		}

		prThisBlock = prZone->prMemBlock;
	}
	else	// we are adding to the end of the linked list
	{

		prThisBlock = prZone->prMemBlock;
		while (prThisBlock->prNext != NULL)
			prThisBlock = prThisBlock->prNext;

		prThisBlock->prNext = malloc(sizeof(VIR_MEM_BLOCK));
		if (prThisBlock->prNext == NULL)
		{
			igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
			iStatus = -1;

			return iStatus;
		}

		prThisBlock = prThisBlock->prNext;
	}

	//-------------------------------------------------------
	// always init allocated structure to a known state
	//-------------------------------------------------------
	memset(prThisBlock, 0, sizeof(VIR_MEM_BLOCK));

	//-------------------------------------------------------
	// now we ask for the memory...
	//-------------------------------------------------------

	iBlockRequestSize = kVM_BlockSize;
	iZoneId           = prZone->iZoneId;

	iStatus = LIB$GET_VM_64(&iBlockRequestSize, (void *) &iBaseAddress, &iZoneId);
	switch(iStatus)
	{
	//---------------------------------------------
	// we were successful in our request for memory
	//---------------------------------------------
	case SS$_NORMAL:

		prThisBlock->iBaseAddress = iBaseAddress;
		prZone->iBlockCount++;

		*pprVmBlock = prThisBlock;

		memset((void *) iBaseAddress, igFillChar, (size_t) iBlockRequestSize);

		iStatus = 0;	// our idea of success flag
		break;

	//---------------------------------------------
	// Invalid Zone id or the zone is corrupt
	//---------------------------------------------
	case LIB$_BADBLOADR:

		igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
		iStatus = -1;

		break;

	//---------------------------------------------
	// bad block size
	//---------------------------------------------
	case LIB$_BADBLOSIZ:

		igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
		iStatus = -1;

		break;

	//---------------------------------------------
	// insufficient virtual memory (VMS said no)
	//---------------------------------------------
	case LIB$_INSVIRMEM:

		igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
		iStatus = -1;

		break;

	//---------------------------------------------
	// Allocation exceeds the page limit defined
	// by the zone at create time
	//---------------------------------------------
	case LIB$_PAGLIMEXC:

		igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
		iStatus = -1;

		break;

	};


	return iStatus;
}
//-------------------------------------------------------
// add a record to a block in a zone
// the zone must have already been found (or created)
// and we are passed a pointer to the correct zone
//-------------------------------------------------------
int AddRecord2Block(VIR_MEM_ZONE *prZone, int iRecordNumber, void *prRecord, int iRecordSize)
{
int		iStatus          = 0,	// return status variable
		iRecordsPerBlock = 0,	// how many records fit in a block?
		iCurrentBlock    = 0,	// what is the current block we're on
		iBlockNumber     = 0;	// block number to use

VIR_MEM_BLOCK	*prThisBlock = NULL;	// block to use

int64		iOffsetIntoBlock = 0;	// used to calculate offset into block

	//-------------------------------------------------------
	// determine which block we want to get to...
	//-------------------------------------------------------

	if (prZone->iRecordSize == 0)
	{
		if (iRecordSize > kVM_BlockSize)
		{

			igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
			iStatus = -1;

			return iStatus;
		}
		prZone->iRecordSize = iRecordSize;
	}

	//-------------------------------------------------------
	// calculate a number of useful values
	// blocks are numbered starting at 0
	//-------------------------------------------------------

	if (prZone->iRecordsPerBlock == 0)
	{
		iRecordsPerBlock = (kVM_BlockSize/ iRecordSize);
		prZone->iRecordsPerBlock = iRecordsPerBlock;
	}
	else
		iRecordsPerBlock = prZone->iRecordsPerBlock;

	iBlockNumber     = (iRecordNumber - 1) / iRecordsPerBlock;
	iOffsetIntoBlock = iRecordNumber - (iBlockNumber * iRecordsPerBlock);
	iOffsetIntoBlock--;
	iOffsetIntoBlock *= prZone->iRecordSize;

	if ((iBlockNumber + 1) > prZone->iBlockCount)
	{
		//-------------------------------------------------------
		// we need to add blocks until we get to the block number
		// desired
		//-------------------------------------------------------
		while((iBlockNumber + 1) > prZone->iBlockCount)
		{
			iStatus = AddBlock2Zone(prZone, &prThisBlock);
			if (iStatus != 0)
			{

				igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
				iStatus = -1;

				return iStatus;
			}
		}
	}
	else
	{
		//-------------------------------------------------------
		//walk thru linked list until we find our block
		//-------------------------------------------------------

		iCurrentBlock = 0;
		prThisBlock   = prZone->prMemBlock;

		while (iCurrentBlock != iBlockNumber)
		{
			prThisBlock = prThisBlock->prNext;
			iCurrentBlock++;

			if (prThisBlock == NULL)
			{
				//-----------------------------------
				// we need to add blocks until we get
				// to the block number desired
				//-----------------------------------
				while (iBlockNumber > iCurrentBlock)
				{
					iStatus = AddBlock2Zone(prZone, &prThisBlock);
					if (iStatus != 0)
					{

						igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
						iStatus = -1;

						return iStatus;
					}

					iCurrentBlock++;
				}
				break;
			}
		}
	}

	//-------------------------------------------------------
	// at this point we now have all the info we need to
	// write the record to the record within the current block
	// of the current virtual memory zone.
	//-------------------------------------------------------

	if (iRecordSize > prZone->iRecordSize)
		iRecordSize = prZone->iRecordSize;

	memset((void *) (prThisBlock->iBaseAddress + iOffsetIntoBlock),
		(int) ' ', (size_t) prZone->iRecordSize);


	//-------------------------------------------------------
	// the use of LIB$MOVC3 is an artifact from the original
	// DIBOL version of this routine (plus originally I did not
	// know how to get the pointers to be 64 bits in size.)
	//-------------------------------------------------------
	LIB$MOVC3 ((void *) &iRecordSize, (void *) prRecord,
		(void *) (prThisBlock->iBaseAddress + iOffsetIntoBlock));


	return iStatus;
}


//-------------------------------------------------------
// get a record from a block within a zone
// the zone must be set and the exist,
// if the block doesn't exist then an empty record is
// loaded
//-------------------------------------------------------
int GetRecordFromBlock(VIR_MEM_ZONE *prZone, int iRecordNumber, void *prRecord, int iRecordSize)
{
int		iStatus          = 0,	// return status variable
		iRecordsPerBlock = 0,	// how many records fit in a block?
		iCurrentBlock    = 0,	// what is the current block we're on
		iBlockNumber     = 0;	// block number to use

VIR_MEM_BLOCK	*prThisBlock = NULL;	// block to use

int64		iOffsetIntoBlock = 0;	// used to calculate offset into block


	//-------------------------------------------------------
	// calculate a number of useful values
	// blocks are numbered starting at 0!
	//-------------------------------------------------------

	iRecordsPerBlock = prZone->iRecordsPerBlock;
	iBlockNumber     = (iRecordNumber - 1) / iRecordsPerBlock;
	iOffsetIntoBlock = iRecordNumber - (iBlockNumber * iRecordsPerBlock);
	iOffsetIntoBlock--;
	iOffsetIntoBlock *= prZone->iRecordSize;

	if ((iBlockNumber + 1) > prZone->iBlockCount)
	{
		memset(prRecord, (int) ' ', iRecordSize);
		iStatus = 0;
		return iStatus;
	}
	else
	{
		//-------------------------------------------------------
		//walk thru linked list until we find our block
		//-------------------------------------------------------

		iCurrentBlock = 0;
		prThisBlock   = prZone->prMemBlock;

		while (iCurrentBlock != iBlockNumber)
		{
			prThisBlock = prThisBlock->prNext;
			iCurrentBlock++;

			if (prThisBlock == NULL)
			{
				memset(prRecord, (int) ' ', iRecordSize);
				iStatus = 0;
				return iStatus;
			}
		}
	}

	//-------------------------------------------------------
	// at this point we now have all the info we need to
	// get the record to the record within the current block
	// of the current virtual memory zone.
	//-------------------------------------------------------
	if (iRecordSize > prZone->iRecordSize)
		iRecordSize = prZone->iRecordSize;

	//-------------------------------------------------------
	// the use of LIB$MOVC3 is an artifact from the original
	// DIBOL version of this routine (plus originally I did not
	// know how to get the pointers to be 64 bits in size.)
	//-------------------------------------------------------
	LIB$MOVC3((void *) &iRecordSize,
		(void *) (prThisBlock->iBaseAddress + iOffsetIntoBlock),
		(void *) prRecord);


	return iStatus;
}

//-------------------------------------------------------
// remove zone
// this routine uses the zone name to remove an entry
// from the linked list and free up the entire memory zone
//-------------------------------------------------------

int RemoveVirMemZone( char *psZoneName, VIR_MEM_ZONE **pprRootZone)
{

int	iStatus = 0;			// return status variable

VIR_MEM_ZONE	*prThisZone = NULL,	// current zone
		*prTheRoot = NULL,	// dereference for **prRootZone
		*prPrevZone = NULL;	// previous zone

int64	iZoneId           = 0;

	//-------------------------------------------------------
	// find the zone structure we want to free up
	//-------------------------------------------------------

	prTheRoot = *pprRootZone;

	if (!strcmp(prTheRoot->psName, psZoneName))
	{
		prThisZone = prTheRoot;
		*pprRootZone = prThisZone->prNext;
	}
	else
	{
		prThisZone = prTheRoot->prNext;
		prPrevZone = prTheRoot;

		if (prThisZone == NULL)
		{
			//-----------------------------------
			// no zone, so there's nothing to do
			//-----------------------------------
			iStatus = 0;
			return iStatus;
		}

		while (strcmp(prThisZone->psName, psZoneName))
		{
			prPrevZone = prThisZone;
			prThisZone = prThisZone->prNext;
			if (prThisZone == NULL)
			{
				//-----------------------------------
				// no zone, so there's nothing to do
				//-----------------------------------
				iStatus = 0;
				return iStatus;
			}

		}	// while

		prPrevZone->prNext = prThisZone->prNext;

		if (prPrevZone == prTheRoot)
			*pprRootZone = prPrevZone;

	}	// else


	//-------------------------------------------------------
	// ok, let's blow the zone away...
	//-------------------------------------------------------

	if (prThisZone)
	{
		iZoneId = prThisZone->iZoneId;

		iStatus = LIB$DELETE_VM_ZONE_64((void *) &iZoneId);

		switch (iStatus)
		{

		//---------------------------------------------
		// normal completion, the zone is toast
		//---------------------------------------------

		case SS$_NORMAL:

			if (prThisZone->prMemBlock != NULL)
				KillBlockStructures(prThisZone->prMemBlock);

			free(prThisZone);	// free up the memory that was malloc'd
			iStatus = 0;		// set the status to our version of success

			break;

		//---------------------------------------------
		// zone id was bad or the zone is corrupted
		//---------------------------------------------

		case LIB$_BADBLOADR:

			igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
			iStatus = -1;

			break;

		};
	}

	//-------------------------------------------------------
	// return to the caller
	//-------------------------------------------------------

 	return iStatus;
}

//-------------------------------------------------------
// remove block of memory from linked list
//-------------------------------------------------------

int RemoveBlock(VIR_MEM_ZONE *prZone, int iBlockNumber)
{
int	iStatus       = 0,		// return status variable
	iCurrentBlock = 0;		// current block we're on

VIR_MEM_BLOCK	*prThisBlock  = NULL,	// pointer to current block
		*prPriorBlock = NULL;	// pointer to prior block

int64	iBlockRequestSize = 0,
	iBaseAddress      = 0,
	iZoneId           = 0;

	//-------------------------------------------------------
	//
	//-------------------------------------------------------

	if ((iBlockNumber + 1) > prZone->iBlockCount)
	{
		iStatus = 0;
		return iStatus;
	}

	//-------------------------------------------------------
	// get the block and adjust the linked list pointers
	//-------------------------------------------------------

	if (iBlockNumber == 0)
	{
		prThisBlock        = prZone->prMemBlock;
		prZone->prMemBlock = prThisBlock->prNext;

		prZone->iBlockCount--;

	}
	else
	{
		prThisBlock = prZone->prMemBlock;
		while (iCurrentBlock != iBlockNumber)
		{
			prPriorBlock = prThisBlock;
			prThisBlock  = prThisBlock->prNext;

			iCurrentBlock++;

			if (prThisBlock == NULL)
			{

// we hosed the linked list somehow...

			}
		}

		prPriorBlock->prNext = prThisBlock->prNext;

		prZone->iBlockCount--;
	}


	//-------------------------------------------------------
	// now let's free up that sucker...
	//-------------------------------------------------------

	iBlockRequestSize = kVM_BlockSize;
	iBaseAddress      = prThisBlock->iBaseAddress;
	iZoneId           = prZone->iZoneId;

	memset((void *) iBaseAddress, 0, (size_t) iBlockRequestSize);
	iStatus = LIB$FREE_VM_64((void *) &iBlockRequestSize, (void *) &iBaseAddress, (void *) &iZoneId);

	switch(iStatus)
	{

	//---------------------------------------------
	// successful, normal completion
	//---------------------------------------------

	case SS$_NORMAL:


		free(prThisBlock);		// release the malloc'd memory
		iStatus = 0;			// return our version of success

		break;

	//---------------------------------------------
	// the base address argument had an invalid
	// address, the zone was corrupt, or the alignment
	// was incorrect.
	//---------------------------------------------

	case LIB$_BADBLOADR:

		igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
		iStatus = -1;

		break;

	//---------------------------------------------
	// the block size was wrong
	//---------------------------------------------

	case LIB$_BADBLOSIZ:

		igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
		iStatus = -1;

		break;

	//---------------------------------------------
	// the boundary tag field(s) is/are corrupted
	//---------------------------------------------

	case LIB$_BADTAGVAL:

		igFATAL_VIR_MEM_ERROR = 1;	// WE FATALED
		iStatus = -1;

		break;

	};

	//-------------------------------------------------------
	// return to the caller
	//-------------------------------------------------------

	return iStatus;
}

//-------------------------------------------------------
// search a block for some binary data
//
// we are writing records into the cache as is. There
// can be embedded integers, floating point, and other
// binary values. For this reason, we cannot use string
// searches but have to do memcmp's as we walk thru the
// memory held by the zone.
//
//-------------------------------------------------------

int FindDataInBlock(VIR_MEM_ZONE *prZone, VIR_MEM_BLOCK *prThisBlock, void *prLookFor,
	int iByteCount, void **prFound, int iBufferSize, int iStartRecord)
{

int	iStatus          = 0,	// return status variable
	iRecordNumber    = 0,	// what is the record number we found it in?
	iFoundOne        = 0,	// flag for success in search
	iRecordSize      = 0,	// get the recordsize (without the pointer)
	iRecordsPerBlock = 0;	// how many records fit in a block?

int64	iByteRange       = 0,	// what is the last position we can look at
	iRangeStart      = 0,	// start of block (sans pointer)
	iSearchOffset    = 0;	// offset for memcmp into block

	//-------------------------------------------------------
	// get some useful values
	//-------------------------------------------------------

	iRecordSize      = prZone->iRecordSize;
	iRecordsPerBlock = prZone->iRecordsPerBlock;
	iByteRange       = iRecordSize * iRecordsPerBlock;
	iRangeStart      = prThisBlock->iBaseAddress;

	//-------------------------------------------------------
	//  Do the search
	//-------------------------------------------------------

	iSearchOffset = iRangeStart;	// start for search
	iFoundOne     = 0;		// make sure flag is reset each time

	//-------------------------------------------------------
	// adjust start range for first search by starting record value
	//-------------------------------------------------------
	iSearchOffset = iSearchOffset + (iRecordSize * iStartRecord);

	FOREVER
	{
		if (!memcmp((void *) iSearchOffset, prLookFor, (size_t)iByteCount))
		{
			iFoundOne = 1;	// we got a hit!
			break;		// bail from loop
		}

		iSearchOffset++;		// next position

		//-------------------------------------------------------
		// if the remaining bytes in the block is less than the
		// size of the search for object, then bail
		//-------------------------------------------------------

		if (((iSearchOffset - iRangeStart) + iByteCount) > iByteRange)
			break;
	}

	//-------------------------------------------------------
	// did we find a match?
	//-------------------------------------------------------

	if (!iFoundOne)
	{
	 	iStatus = 0;		// not found
		return iStatus;		// bail
	}

	//-------------------------------------------------------
	// now we need to figure out which record it is within
	// the block
	//-------------------------------------------------------

    	iRecordNumber = ((iSearchOffset - prThisBlock->iBaseAddress) / iRecordSize) + 1;


	if (iRecordSize <= iBufferSize)
		memmove((void *)*prFound,
			(void *) (prThisBlock->iBaseAddress + ((iRecordNumber - 1) * iRecordSize)),
			(size_t) iRecordSize);
	else
		memmove((void *)*prFound,
			(void *) (prThisBlock->iBaseAddress + ((iRecordNumber - 1) * iRecordSize)),
			(size_t) iBufferSize);


	iStatus = iRecordNumber;	// return the record number to the caller

	//-------------------------------------------------------
	// return to caller
	//-------------------------------------------------------

	return iStatus;
}
//-------------------------------------------------------
// search a block for some binary data at the start of
// each record
//
// we are writing records into the cache as is. There
// can be embedded integers, floating point, and other
// binary values. For this reason, we cannot use string
// searches but have to do memcmp's as we walk thru the
// memory held by the zone.
//
//-------------------------------------------------------

int FindDataInBlockStart(VIR_MEM_ZONE *prZone, VIR_MEM_BLOCK *prThisBlock, void *prLookFor,
	int iByteCount, void **prFound, int iBufferSize, int iStartRecord)
{

int	iStatus          = 0,	// return status variable
	iRecordNumber    = 0,	// what is the record number we found it in?
	iFoundOne        = 0,	// flag for success in search
	iRecordSize      = 0,	// get the recordsize (without the pointer)
	iRecordsPerBlock = 0;	// how many records fit in a block?

int64	iByteRange       = 0,	// what is the last position we can look at
	iRangeStart      = 0,	// start of block (sans pointer)
	iSearchOffset    = 0;	// offset for memcmp into block

	//-------------------------------------------------------
	// get some useful values
	//-------------------------------------------------------

	iRecordSize      = prZone->iRecordSize;
	iRecordsPerBlock = prZone->iRecordsPerBlock;
	iByteRange       = iRecordSize * iRecordsPerBlock;
	iRangeStart      = prThisBlock->iBaseAddress;

	//-------------------------------------------------------
	//  Do the search
	//-------------------------------------------------------

	iSearchOffset = iRangeStart;	// start for search
	iFoundOne     = 0;		// make sure flag is reset each time

	//-------------------------------------------------------
	// adjust start range for first search by starting record value
	//-------------------------------------------------------
	iSearchOffset = iSearchOffset + (iRecordSize * iStartRecord);

	FOREVER
	{
		if (!memcmp((void *) iSearchOffset, prLookFor, (size_t)iByteCount))
		{
			iFoundOne = 1;	// we got a hit!
			break;		// bail from loop
		}

		iSearchOffset += iRecordSize;	// next position (we go by yhe size of the record)

		//-------------------------------------------------------
		// if the remaining bytes in the block is less than the
		// size of the search for object, then bail
		//-------------------------------------------------------

		if (((iSearchOffset - iRangeStart) + iByteCount) > iByteRange)
			break;
	}

	//-------------------------------------------------------
	// did we find a match?
	//-------------------------------------------------------

	if (!iFoundOne)
	{
	 	iStatus = 0;		// not found
		return iStatus;		// bail
	}

	//-------------------------------------------------------
	// now we need to figure out which record it is within
	// the block
	//-------------------------------------------------------

    	iRecordNumber = ((iSearchOffset - prThisBlock->iBaseAddress) / iRecordSize) + 1;

	if (iRecordSize > iBufferSize)
		iRecordSize = iBufferSize;

	memmove((void *)*prFound,
		(void *) (prThisBlock->iBaseAddress + ((iRecordNumber - 1) * iRecordSize)),
		(size_t) iRecordSize);

	iStatus = iRecordNumber;	// return the record number to the caller

	//-------------------------------------------------------
	// return to caller
	//-------------------------------------------------------

	return iStatus;
}
//-------------------------------------------------------
// recursive routine to free up all the VM block
// data structures
//-------------------------------------------------------
void	KillBlockStructures(VIR_MEM_BLOCK *prBlock)
{
	if (prBlock->prNext != NULL)
		KillBlockStructures(prBlock->prNext);


	memset((void *) prBlock->iBaseAddress, 0, (size_t) kVM_BlockSize);
	free(prBlock);

	return;
}
//-------------------------------------------------------
// truncate string
//-------------------------------------------------------
void TruncateString(char *psString)
{
int	iLength = 0,
	iIndex  = 0;

char *psThisChar = NULL;


	iLength = strlen(psString);
	iIndex = iLength - 1;

 	if (!iLength)
		return;

	psThisChar = psString + iIndex;

	while ((*psThisChar == ' ') || (*psThisChar == 0))
	{
		*psThisChar = 0;
		iIndex--;

		if (iIndex < 0)
			break;

		psThisChar--;
	}

	return;
}
//-------------------------------------------------------
//move (copy) the contents of the entire zone into a buffer
//-------------------------------------------------------
int MoveZone2Buffer(char *psZoneName, VIR_MEM_ZONE *prRootZone,
			void *prBuffer, int iBufferSize, int iRecordCount)
{

int	iBail       = 0,			// we're done flag
	iMovedCount = 0,		// howmany records have we moved
	iStatus     = 0;			// return status variable

int64	iBaseAddress      = 0,		// dereference the base address
	iOffsetIntoBlock  = 0,		// offset into block
	iOffsetIntoBuffer = 0,		// for computing record starts
	iBlockByteCount   = 0,		// total useable bytes in block
	iBytes2Move       = 0;		// number of bytes to copy

char	*psBlankString    = NULL,	// to use to load spaces
	*psNullString     = NULL;	// for a block of NULLs

VIR_MEM_ZONE  *prThisZone = NULL;	// pointer to zone we are using
VIR_MEM_BLOCK *prThisBlock = NULL;	// pointer to current VM Block

	//---------------------------------------------
	// find the virtual memory zone we need
	//---------------------------------------------
	prThisZone = FindZone(psZoneName, prRootZone);

	if (prThisZone == NULL)
	{
		// fill the buffer with spaces and return
		memset((void *)prBuffer, (int) ' ', (size_t) iBufferSize);

		iStatus = 0;
		return iStatus;
	}

	//---------------------------------------------
	// calc the number of bytes in a zone
	//---------------------------------------------

	iBytes2Move       = prThisZone->iRecordSize;
	iBlockByteCount   = iBytes2Move * (prThisZone->iRecordsPerBlock);
	iOffsetIntoBuffer = (int64) prBuffer;

	psNullString  = malloc((size_t) iBytes2Move);
	psBlankString = malloc((size_t) iBytes2Move);

	if ((psNullString == NULL) || (psBlankString == NULL))
	{
		free(psNullString);
		free(psBlankString);

		iStatus               = 1;
		igFATAL_VIR_MEM_ERROR = 1;

		return iStatus;
	}

	memset((void *)psNullString,          0, (size_t) iBytes2Move);
	memset((void *)psBlankString, (int) ' ', (size_t) iBytes2Move);

	//---------------------------------------------
	// find the first block within the zone
	//---------------------------------------------
	prThisBlock = prThisZone->prMemBlock;
	if (prThisBlock == NULL)
	{
		// fill the buffer with spaces and return
		memset((void *)prBuffer, (int) ' ', (size_t) iBufferSize);

		iStatus = 0;
		return iStatus;
	}

	//---------------------------------------------
	// loop thru the blocks and grab the data
	//---------------------------------------------

	iBail       = 0;
	iMovedCount = 0;

	while ((prThisBlock != NULL) && (!iBail))
	{
		iBaseAddress     = prThisBlock->iBaseAddress;
		iOffsetIntoBlock = iBaseAddress;

	      	while((iOffsetIntoBlock - iBaseAddress) < iBlockByteCount)
		{
			if (memcmp(	(void *) psNullString,
					(void *)(iOffsetIntoBlock),
					(size_t) iBytes2Move))
			{
				LIB$MOVC3((void *) &iBytes2Move,
					(void *) iOffsetIntoBlock,
					(void *) iOffsetIntoBuffer);

				iMovedCount++;
				if (iRecordCount)
					if (iMovedCount == iRecordCount)
					{
						iBail = 1;
						break;
					}
			}
			else
			{
				iBail = 1;
				break;
			}

		 	iOffsetIntoBuffer += iBytes2Move;
			iOffsetIntoBlock  += iBytes2Move;
		}

		prThisBlock = prThisBlock->prNext;
	}

	free(psBlankString);
	free(psNullString);

	return iStatus;
}
//-------------------------------------------------------
//debug dump of data structures
//-------------------------------------------------------
void DebugZoneDump(VIR_MEM_ZONE *prRootZone)
{
VIR_MEM_ZONE	*prThisZone  = NULL;
VIR_MEM_BLOCK	*prThisBlock = NULL;

int	iStatus = 0,
	iRecNum = 0;

unsigned short	iOutLen = 0;

int64	iArgList[2] = {0,0};

char	szTempStr[50 + 1],
	szOutBuff[80+1];

DSCS_S		dscControlStr  = { 3, DSC$K_DTYPE_T, DSC$K_CLASS_S, "!ZQ"},
		dscControlStr2 = { 3, DSC$K_DTYPE_T, DSC$K_CLASS_S, "!XQ"},
		dscOutStr      = {80, DSC$K_DTYPE_T, DSC$K_CLASS_S, szOutBuff};

	memset(szOutBuff, 0, 81);

	prThisZone = prRootZone;

	//-------------------------------------------------------
	// walk thru the list of VM zones we have in use
	//-------------------------------------------------------
	while(prThisZone != NULL)
	{
		iArgList[0] = prThisZone->iZoneId;
		iStatus     = sys$faol_64(&dscControlStr, &iOutLen, &dscOutStr, &iArgList[0]);

		fprintf (pfDEBUG_OUT, "\n %s [%s] blks: %d rsiz: %d fit: %d",
			prThisZone->psName, szOutBuff,
			prThisZone->iBlockCount, prThisZone->iRecordSize,
			prThisZone->iRecordsPerBlock);

		prThisBlock = prThisZone->prMemBlock;

		//-------------------------------------------------------
		// walk thru the blocks in this zone
		//-------------------------------------------------------
		while (prThisBlock != NULL)
		{
			iRecNum++;

			memset(szOutBuff, 0, 81);

			iArgList[0] = prThisBlock->iBaseAddress;
			iStatus     = sys$faol_64(&dscControlStr2, &iOutLen, &dscOutStr, &iArgList[0]);

			fprintf(pfDEBUG_OUT, "\n  #%04d [%s] cnt: %04d ",
				iRecNum, szOutBuff,
				prThisBlock->iRecordCount);

			//-------------------------------------------------------
			// print the first 50 bytes of data
			//-------------------------------------------------------
			memset (szTempStr, 0, 51);
			if (prThisZone->iRecordSize >= 50)
				memcpy (szTempStr, (void*) prThisBlock->iBaseAddress, 50);
			else
				memcpy (szTempStr, (void*) prThisBlock->iBaseAddress, prThisZone->iRecordSize);

			fprintf(pfDEBUG_OUT, "%s", szTempStr);

			prThisBlock = prThisBlock->prNext;
		}

		prThisZone = prThisZone->prNext;
	}

	return;
}



mgdaniel
Valued Contributor
Posts: 62
Joined: Mon Feb 28, 2022 5:16 pm
Reputation: 0
Location: Adelaide, South Australia
Status: Offline
Contact:

Re: New one for me: LLVM ERROR: Cannot encode high byte register in REX-prefixed instruction

Post by mgdaniel » Sat Nov 18, 2023 3:55 pm


User avatar

Topic author
tlovern
Active Contributor
Posts: 40
Joined: Tue Jul 21, 2020 10:44 am
Reputation: 0
Status: Offline

Re: New one for me: LLVM ERROR: Cannot encode high byte register in REX-prefixed instruction

Post by tlovern » Sun Nov 19, 2023 12:24 pm

Thanks! Obviously I'm searching the wrong places...did a google search and nothing useful turned up....

I guess I need to search here first.

Post Reply