/*
 * lib.h
 *
 * Copyright 2002, Minoru Murashima. All rights reserved.
 * Distributed under the terms of the BSD License.
 *
 * lib.c、lib.S用ヘッダーファイル
 */


#ifndef lib_h
#define lib_h


#include <types.h>
#include <segment.h>
#include <sys/uio.h>


#ifndef ASM_FILE


enum{
	BYTE_BIT=8,		/* 1バイトのビット数。 */
};


#define ROUNDUP(a, b) (((uint)(a) + (b) - 1) / (b) * (b))
#define ROUNDDOWN(a, b) ((uint)(a) / (b) * (b))
#define ROUNDUP_DIV(a, b) (((uint)(a) + (b) - 1) / (b))
#define OFFSETOF(type, member) ((size_t) &((type*)0)->member)
#define	MAX(a, b)		(((a) < (b))? (b) : (a))
#define	MIN(a, b)		(((a) < (b))? (a) : (b))
#define ARRAY_LENGTH(x)	(sizeof(x) / sizeof(x[0]))
#define SWAP(a, b)	{int tmp = b; b = a; a = tmp;}
#define WAIT_LOOP(condition)	{LOOP:	if (condition){goto LOOP;}}

extern int (*write_tty)(void*,size_t,size_t);
extern void printk(const char*,...);
extern int sprintk(char *,const char*,...);
extern void idle();
extern int read_tr();
extern uint64 rdtsc();
extern void fpuSave(uint);
extern void fpuStore(uint);
extern void clearTs();
extern void setTs();
extern uint getFualtAddr();
extern void micro_timer(uint);
extern void mili_timer(uint);
extern char *strcpy(char*,const char*);
extern int strcmp(const char*,const char*);
extern int atoi(const char*);
extern void *memcpy(void*,const void*, size_t);
extern void memCpyBack(void*,const void*, size_t);
extern void *memset(void*,int,size_t);
extern void *memcpy_to_user(void *,const void*,size_t);
extern void *memcpy_from_user(void *,const void*,size_t);
extern int copyIovec(const char*,const int,struct iovec*,const int,int*,int*);

#ifdef DEBUG
extern void printDebug(int,const char*,...);
#endif

extern inline void outb(int port,uchar value)
{
	asm volatile(
		"outb	%%dx"
		::"d"(port),"a"(value)
	);
}

extern inline uchar inb(int port)
{
	uchar rest;


	asm volatile(
		"inb	%%dx"
		:"=a"(rest):"d"(port)
	);

	return rest;
}

extern inline void outw(int port,ushort value)
{
	asm volatile(
		"outw	%%dx"
		::"d"(port),"a"(value)
	);
}

extern inline ushort inw(int port)
{
	ushort rest;


	asm volatile(
		"inw	%%dx"
		:"=a"(rest):"d"(port)
	);

	return rest;
}

extern inline void outdw(int port,uint value)
{
	asm volatile(
		"outl	%%dx"
		::"d"(port),"a"(value)
	);
}

extern inline uint indw(int port)
{
	uint rest;


	asm volatile(
		"inl	%%dx"
		:"=a"(rest):"d"(port)
	);

	return rest;
}

extern inline void *memmove(void *s1,const void *s2,size_t n)
{
	if((s1>s2)&&((char*)s1<(char*)s2+n))memCpyBack(s1,s2,n);
	else memcpy(s1,s2,n);

	return s1;
}

extern inline int memcmp(const void *s1,const void *s2,size_t n)
{
	int i=0;


	while(((char*)s1)[i]==((char*)s2)[i])
		if(++i>=n)return 0;

	if(((char*)s1)[i]>((char*)s2)[i])return 1;
	return -1;
}

extern inline char *strcpy(char *s1,const char *s2)
{
	char *p=s1;


	while((*p++=*s2++)!='\0');

	return s1;
}

extern inline size_t strlen(const char *s)
{
	const char *p = s;


	while(*p++ != '\0');

	return (size_t)(p-s-1);
}

extern inline int strcmp(const char *s1, const char *s2)
{
	while (*s1 == *s2++){
		if (*s1++ == '\0'){
			return 0;
		}
	}
	if ((uchar)*s1 > (uchar)*--s2){
		return 1;
	}
	return -1;
}

extern inline char *strcat(char *s1,const char *s2)
{
	char *p=s1;


	for(;*p!='\0';++p);
	while((*p++=*s2++)!='\0');

	return s1;
}


#endif


#endif
