⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 genlib.c

📁 umon bootloader source code, support mips cpu.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* genlib.c:
 *	This file has some of the stuff that is typically pulled in by the c
 *	library.  It is provided as local source so that the monitor can be
 *	built without the need for a library.  Some of this code was taken from
 *	the Berkley source code (see notice below).
 *
 *	General notice:
 *	This code is part of a boot-monitor package developed as a generic base
 *	platform for embedded system designs.  As such, it is likely to be
 *	distributed to various projects beyond the control of the original
 *	author.  Please notify the author of any enhancements made or bugs found
 *	so that all may benefit from the changes.  In addition, notification back
 *	to the author will allow the new user to pick up changes that may have
 *	been made by other users after this version of the code was distributed.
 *
 *	Note1: the majority of this code was edited with 4-space tabs.
 *	Note2: as more and more contributions are accepted, the term "author"
 *		   is becoming a mis-representation of credit.
 *
 *	Original author:	Ed Sutter
 *	Email:				esutter@lucent.com
 *	Phone:				908-582-2351
 */
/*
 * Copyright (c) 1988, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
#include "config.h"
#include "ctype.h"
#include "genlib.h"
#include "stddefs.h"

char *BSDCRN = "Copyright (c) 1988, 1993 The Regents of the University of California.  All rights reserved.";

/* If an application is using this code, then it must define MONAPP
 * when compiling this file.  This deals with a few functions that this
 * code would otherwise call within the monitor itself.
 * For example, in application space we call mon_printf() instead of
 * printf()...
 * Note: this used to be MONPRINTF, and has since been changed because
 * a few other spots not related to mon_printf() must also be modified.
 */
#ifdef MONAPP
extern int mon_printf();
#define printf mon_printf
#endif

int
abs(int arg)
{
	return (arg >= 0 ? arg : -arg);
}

int
atoi(char *p)
{
	int n, c, neg;

	neg = 0;
	if (!isdigit((c = *p))) {
		while (isspace(c))
			c = *++p;
		switch (c) {
		case '-':
			neg++;
			break;
		case '+': /* fall-through */
			c = *++p;
			break;
		}
		if (!isdigit(c))
			return (0);
	}
	for (n = '0' - c; isdigit((c = *++p)); ) {
		n *= 10;		/* two steps to avoid unnecessary overflow */
		n += '0' - c;	/* accum neg to avoid surprises at MAX */
	}
	return (neg ? n : -n);
}

unsigned char	ctypetbl[] = {
	 0,		_C,		_C,		_C,		_C,		_C,		_C,		_C,
	_C,		_S|_C,	_S|_C,	_S|_C,	_S|_C,	_S|_C,	_C,		_C,
	_C,		_C,		_C,		_C,		_C,		_C,		_C,		_C,
	_C,		_C,		_C,		_C,		_C,		_C,		_C,		_C,
	_S|_B,	_P,		_P,		_P,		_P,		_P,		_P,		_P,
	_P,		_P,		_P,		_P,		_P,		_P,		_P,		_P,
	_N|_X,	_N|_X,	_N|_X,	_N|_X,	_N|_X,	_N|_X,	_N|_X,	_N|_X,
	_N|_X,	_N|_X,	_P,		_P,		_P,		_P,		_P,		_P,
	_P,		_U|_X,	_U|_X,	_U|_X,	_U|_X,	_U|_X,	_U|_X,	_U,
	_U,		_U,		_U,		_U,		_U,		_U,		_U,		_U,
	_U,		_U,		_U,		_U,		_U,		_U,		_U,		_U,
	_U,		_U,		_U,		_P,		_P,		_P,		_P,		_P,
	_P,		_L|_X,	_L|_X,	_L|_X,	_L|_X,	_L|_X,	_L|_X,	_L,
	_L,		_L,		_L,		_L,		_L,		_L,		_L,		_L,
	_L,		_L,		_L,		_L,		_L,		_L,		_L,		_L,
	_L,		_L,		_L,		_P,		_P,		_P,		_P,		_C,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0,
	 0,		 0,		 0,		 0,		 0,		 0,		 0,		 0
};

/* memccpy():
 * Copy s2 to s1, stopping if character c is copied. Copy no more than n bytes.
 * Return a pointer to the byte after character c in the copy,
 * or NULL if c is not found in the first n bytes.
 */
char *
memccpy(register char *s1,register char *s2,register int c,register int n)
{
	while (--n >= 0)
		if ((*s1++ = *s2++) == c)
			return (s1);
	return (0);
}

/* memchr():
 * Return the ptr in sp at which the character c appears;
 *   NULL if not found in n chars; don't stop at \0.
 */
char *
memchr(register char *sp, register char c,register int n)
{
	while (--n >= 0)
		if (*sp++ == c)
			return (--sp);
	return (0);
}

/* memcmp():
 * Compare n bytes:  s1>s2: >0  s1==s2: 0  s1<s2: <0
 */
int
memcmp(register char *s1,register char *s2,register int n)
{
	int diff;

	if (s1 != s2)
		while (--n >= 0)
			if ((diff = (*s1++ - *s2++)))
				return (diff);
	return (0);
}

/* memcpy():
 *  Copy n bytes from 'from' to 'to'; return 'to'.
 *	This version of memcpy() tries to take advantage of address alignment.
 *  The goal is to do as many of the copies on 4-byte aligned addresses,
 *  falling back to 2-byte alignment, and finally, if there is no other
 *  way, simple byte-by-byte copy.
 *  Note that there is some point where the amount of overhead may exceed
 *  the byte count; hence, this will take longer for small byte counts.
 *  The assumption here is that small byte count memcpy() calls don't really
 *  care.
 */
char *
memcpy(char *to,char *from,int count)
{
	char	*to_copy, *end;

	to_copy = to;

#if INCLUDE_QUICKMEMCPY
	/* If count is greater than 8, get fancy, else just do byte-copy... */
	if (count > 8) {
		/* Attempt to optimize the transfer here... */
		if (((int)to & 3) && ((int)from & 3)) {
			/* If from and to pointers are both unaligned to the
			 * same degree then we can do a few char copies to get them
			 * 4-byte aligned and then do a lot of 4-byte aligned copies.
			 */
			if (((int)to & 3) == ((int)from & 3)) {
				while((int)to & 3) {
					*to++ = *from++;
					count--;
				}
			}
			/* If from and to pointers are both odd, but different, then
			 * we can increment them both by 1 and do a bunch of 2-byte
			 * aligned copies...
			 */
			else if (((int)to & 1) && ((int)from & 1)) {
				*to++ = *from++;
				count--;
			}
		}
	
		/* If both pointers are now 4-byte aligned or 2-byte aligned,
		 * take advantage of that here...
		 */
		if (!((int)to & 3) && !((int)from & 3)) {
			end = to + (count & ~3);
			count = count & 3;
			while(to < end) {
				*(ulong *)to = *(ulong *)from;
				from += 4;
				to += 4;
			}
		}
		else if (!((int)to & 1) && !((int)from & 1)) {
			end = to + (count & ~1);
			count = count & 1;
			while(to < end) {
				*(ushort *)to = *(ushort *)from;
				from += 2;
				to += 2;
			}
		}
	}
#endif

	if (count) {
		end = to + count;
		while(to < end)
			*to++ = *from++;
	}
	return(to_copy);
}

void
bcopy(char *from, char *to, int size)
{
	memcpy(to,from,size);
}

/* s_memcpy():
 *	Superset of memcpy().  Note, this used to be tfsmemcpy() in tfs.c;
 *  however, since it has no real TFS dependencies, and code outside of
 *  TFS uses it, it has been moved here and the name is changed.
 *
 *  Includes verbose option plus verification after copy.
 *  Takes advantage of address alignment when possible.
 *
 *  Note:
 *  If verbose is greater than one, then this function doesn't
 *  do any memory transfer, it simply displays the memory range
 *  that is to be transferred.  This is used by TFS to dump a map without
 *  actually touching memory.
 * 
 *  Return:
 *  0 if successful, else -1 indicating some part of the copy failed.
 */
int
s_memcpy(char *_to,char *_from,int count, int verbose,int verifyonly)
{
	int	err;
	volatile register char *to, *from, *end;

	to = _to;
	from = _from;

	if (verbose)
		printf("%s %7d bytes from 0x%08lx to 0x%08lx",
			verifyonly ? "vrfy" : "copy", count,(ulong)from,(ulong)to);

	if (count < 0)
		return(-1);

	if (verifyonly) {
		while(count) {
			if (*to != *from)
				break;
			to++;
			from++;
			count--;
#ifdef WATCHDOG_ENABLED
			if ((count & 0xff) == 0)
				WATCHDOG_MACRO;
#endif
		}
		if (count) {
			if (verbose) {
				printf(" FAILED\n");
				printf("            (0x%02x @ 0x%08lx should be 0x%02x)\n",
					*to,(ulong)to,*from);
			}
			return(-1);
		}
		else
			if (verbose)
				printf(" OK\n");
			return(0);
	}

	/* If verbose is greater than 1, then we don't even do a memcpy,
	 * we just let the user know what we would have done...
	 */
	if ((count == 0) || (verbose > 1))
		goto done;

	if (to != from) {

		err = 0;
		if (!((int)to & 3) && !((int)from & 3) && !(count & 3)) {
			volatile register ulong	*lto, *lfrom, *lend;
	
			count >>= 2;
			lto = (ulong *)to;
			lfrom = (ulong *)from;
			lend = lto + count;
			while(lto < lend) {
				*lto = *lfrom;
				if (*lto != *lfrom) {
					err = 1;
					break;
				}
				lto++;
				lfrom++;
#ifdef WATCHDOG_ENABLED
				if (((int)lto & 0xff) == 0)
					WATCHDOG_MACRO;
#endif
			}
		}
		else if (!((int)to & 1) && !((int)from & 1) && !(count & 1)) {
			volatile register ushort	*sto, *sfrom, *send;
	
			count >>= 1;
			sto = (ushort *)to;
			sfrom = (ushort *)from;
			send = sto + count;
			while(sto < send) {
				*sto = *sfrom;
				if (*sto != *sfrom) {
					err = 1;
					break;
				}
				sto++;
				sfrom++;
#ifdef WATCHDOG_ENABLED
				if (((int)sto & 0xff) == 0)
					WATCHDOG_MACRO;
#endif
			}
		}
		else {
			end = to + count;
			while(to < end) {
				*to = *from;
				if (*to != *from) {
					err = 1;
					break;
				}
				to++;
				from++;
#ifdef WATCHDOG_ENABLED
				if (((int)to & 0xff) == 0)
					WATCHDOG_MACRO;
#endif
			}
		}
		if (err) {
			if (verbose)
				printf(" failed\n");
			return(-1);
		}
	}

done:
	if (verbose)
		printf("\n");

	return(0);
}

/* memset():
 * Set an array of n chars starting at sp to the character c.
 * Return sp.
 */
char *
memset(register char *sp, register char c, register int n)
{
	register char *sp0 = sp;

	while (--n >= 0) {
#ifdef WATCHDOG_ENABLED
		if (((ulong)sp & 0xff) == 0)
			WATCHDOG_MACRO;
#endif
		*sp++ = c;
	}
	return (sp0);
}

/* s_memset():
 *	Superset of memset() (used to be tfsmemset()).
 *  Includes verbose option, test to make sure the destination is not
 *	within MicroMonitor's own space, plus verification after set.
 */
int
s_memset(uchar *to,uchar val,int count,int verbose,int verifyonly)
{
	int		failed;
	uchar	*end;

	failed = 0;

#ifndef MONAPP
	if (inUmonBssSpace((char *)to,(char *)to+count))
		return(-1);
#endif

	if (verbose) {
		printf("%s %7d bytes  at  0x%08lx to 0x%02x",
			verifyonly ? "vrfy" : "set ",count,(ulong)to,val);
	}

	if ((count == 0) || (verbose > 1))
		goto done;

	end = to+count;

	if (verifyonly) {
		while(to < end) {
#ifdef WATCHDOG_ENABLED
			if (((ulong)to & 0xff) == 0)
				WATCHDOG_MACRO;
#endif
			if (*to++ != val) {
				failed = 1;
				break;
			}
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -