www.pudn.com > ASM86_64.rar > operand.c


/*
 *
 *
*/

#include "a64-2.h"
#include "operand.h"
#include "error.h"
#include "label.h"

#include 



int is_variable(char *s)
{
	return 0;
}



/********************************************************* 
 example: 
 parameter: s = "(dword)es:[eax+ecx*8+0xc]" (one operand)
	    o_key = get a operand's key word

 return value: error if errno is set
	       successed if errno is 0

last change: 02-17-2006 21:24 by mik
last change: 02-19-2006 21:05 by mik
**********************************************************/

errno_t get_o_key(o_key_t *o_key, char *s) 
{
	if (!s || !s[0]) return 0;

	errno_t errno = 0; 	/* return value */

	char *p = s;
	char str[80];
	int i = 0;

	unsigned char c = 0;

	if (!o_key) 
		return ERR_OPERAND;

	/* the operand is a memory operand */
	if (get_c(s, '[') == 1)
		o_key->mem = (mem_t *)a64_malloc(sizeof(mem_t));
		 
	/* parse operand 
	 *
	 * for example: (dword)es:[ecx*8+eax+0xc]
	 */


	char tmp_msg[120];
	char *msg = get_err_msg_addr();

	while (*p) {
		if (is_c(*p) || is_n(*p)) {
			str[i++] = *p;
		} else switch (*p) {
		case '(':
			if (p != s) {	/* it's not head */ 
				sprintf(tmp_msg, "at %d: %s\n", line,
					"parse error at before '('");	

				if (str_len(msg) + str_len(tmp_msg) 
					< ERR_MSG_SIZE) 
				{
					str_cat(msg, tmp_msg);
				}
			}

			if (get_c(s,')') != 1) 
				errno |= ERR_SLBRACKET;
			i = 0; break;
		case ')':
			/* get operand size cast value */
			if (get_c(s, '(') != 1) 
				errno |= ERR_SRBRACKET;		
			str[i] = 0;

			unsigned char cast = get_castid(str);
			if (!check_cast(cast))
				errno |= ERR_CAST;

			if (o_key->mem) {
				if (cast == NEAR_ID || cast == FAR_ID)
					o_key->mem->transfer_cast = cast;
				else 
					/* it's a memory cast */
					o_key->mem->cast = cast;
			} else {
				/* it's a immediate cast */
				o_key->imme = 
					(imme_t *)a64_malloc(sizeof(mem_t));

				o_key->imme->cast = cast;
			}
			

			i = 0; break;
		case ':':	/* segment override */
			/* get segment override size byte */
			str[i] = 0;
			o_key->mem->oseg = get_osegid(str);
			if (!check_oseg(o_key->mem->oseg)) {
				if (current_bits == 64) {
					sprintf(tmp_msg, "error at %d: %s\n",
						line, "in 64-bit mode: the "
						"prefix illegal! ");
					mount_err_link(0, 0, tmp_msg);
					errno |= ERR_ERROR;
				} else 
					errno |= ERR_PREFIX;
			}

			i = 0; break;
		case '[':		/* memory operand */
			/*******************************
			 TO DO: this is reserved for var ....
			 example: var1[eax]
			 this is same as [eax + var1]
			*****************************/
		#ifdef RESERVED_VAR
			str[i] = 0;
			/* check var at var table */
			if (!check_var(str)) 
				errno |= ERR_OPERAND;

			p++; 	/* skip '[' */
		#else
			/* xxx[...] is error */
			if (i) errno |= ERR_OPERAND;
		#endif

			if (get_c(s, ']') != 1) 
				errno |= ERR_MRBRACKET;
		
			i = 0; break;
		case '+':
		case ']':
			if (*p == ']') {
				if (get_c(s, '[') != 1) 
					errno |= ERR_MLBRACKET;

				if ((*(p+1) != 0) && (*(p+1) != '!')) {	
					/* not tail and not comment */
					/* errno |= ERR_OPERAND; */
					sprintf(tmp_msg, "at %d: %s\n",
						line, 
						"parse error at after ']'");

					if (str_len(msg) + str_len(tmp_msg)
						< ERR_MSG_SIZE)
					{
						str_cat(msg, tmp_msg);	
					}
				}
			}

			str[i] = 0;
			c = get_regid(str);
			if (check_mreg(c)) {	/* it's valid register */
				if (!o_key->mem->base) 
					o_key->mem->base = c;
				else if (!o_key->mem->index) 
					o_key->mem->index = c;
				else
					errno |= ERR_BASE;
	
				/* check base register and index register */
				if (o_key->mem->base && o_key->mem->index)
					if ((o_key->mem->base & 0xf0) !=
						(o_key->mem->index & 0xf0))
						errno |= ERR_BASE;

			/* this is a disp value or scale value */
			} else if (is_numeric(str)) {
				if (is_n(*(p-1)) && (*(p-2) == '*')) {
					/* scale value */
					o_key->mem->scale = get_scaleid(str);
					if (!o_key->mem->scale)
						errno |= ERR_SCALE;
				} else if (!o_key->mem->disp) {
					/* displacement value */
					o_key->mem->disp = str_to_n(str);
				} else 
					errno |= ERR_DISP;
			} else 	{ /* illegal operand */
				/* errno |= ERR_OPERAND; */
				sprintf(tmp_msg, "at %d: parse error at %s\n",
					line, str); 

				if (str_len(msg) + str_len(tmp_msg)
					< ERR_MSG_SIZE)
				{
					str_cat(msg, tmp_msg);
				}
			}
		
			i = 0; break;
		case '-':
			str[i] = 0;
			c = get_regid(str);
			if (check_mreg(c)) {	/* valid regiser */
				if (!o_key->mem->base) 
					o_key->mem->base = c;
				else if (!o_key->mem->index) 
					o_key->mem->index = c;
				else 
					errno |= ERR_BASE;

				if (o_key->mem->base && o_key->mem->index)
					if ((o_key->mem->base & 0xf0) !=
						(o_key->mem->index & 0xf0))
						errno != ERR_BASE;
		
			/*********************************** 
			 * TODO: reserved for disp or scale value 
			 ***********************************/
			} else {
				/* errno |= ERR_OPERAND; */
				sprintf(tmp_msg, "at %d: parse error at %s\n",
					line, str);

				if (str_len(msg) + str_len(tmp_msg)
						< ERR_MSG_SIZE) 
					str_cat(msg, tmp_msg);
			}

			
			/***************************************/
			char *tp = p + 1;
			i = 0;
			while (*tp && *tp != ']')
				str[i++] = *tp++;
			str[i] = 0;

			if (is_numeric(str) && (!o_key->mem->disp)) 
					o_key->mem->disp = -str_to_n(str);
			else 
				return errno | ERR_OPERAND;
			
			p = tp;	

			i = 0; break;

		case '*':
			/* it's a index register */
			str[i] = 0;
			c = get_regid(str);
			if (check_mreg(c) && !o_key->mem->index) {
				/* it's index register */
				o_key->mem->index = c;

				if (o_key->mem->base && 
					((o_key->mem->base & 0xf0) !=
					(o_key->mem->index & 0xf0)))
					errno |= ERR_BASE;
			} else 
				errno |= ERR_INDEX;	
		
			i = 0; break;
		case '@':  			/* it's a label string */
		
			if (i) errno |= ERR_OPERAND;
/*
			while (*p != ' ')
				str[i++] = *p++;	
			str[i] = 0;
*/			
			/****************
			 *	mount_hole_link()
			 ***************/
			

			i = 0; break;
		case 0x09: 			/* it's a tab */
			i = 0; break;

		case '!':
			while (*p) p++;
			continue;
		default:
			errno |= ERR_CHARACTER;
		}	

		p++;
	}
	

	if (errno || str_len(msg)) {
		if (str_len(msg) == 0) {
			sprintf(msg, "at %d: ", line);
		}	

		mount_err_link(errno, ops_errmsg, msg);

		goto do_error;
	}

	str[i] = 0;


	if (o_key->mem) {				/* memory operand */
		mem_t *mem = o_key->mem;

		/* check base register invalid */
		/* example: [esp*4+ecx]	is invalid */
		if (((mem->index == ESP) || (mem->index == RSP)) && mem->scale) 
		{
			sprintf(msg, "at %d: %s\n",
				line,
				"When index register is \"sp\"" 
				"the scale value error");

			mount_err_link(0, 0, msg);

			/* errno |= ERR_BASE; */
			goto do_error;
		}	

		/**** check 16-bit address size ****/

		/*
		  In 16-bit address size mode:
	          [bx+bp] or [si+di] are error
		*/
		if (((mem->base == BX) && (mem->index == BP))
			|| ((mem->base == SI) && (mem->index == DI)))
		{
			errno |= ERR_BASE;

			mount_err_link(errno, ops_errmsg, 0);

			goto do_error;
		}

		if (mem->disp) {
			/* the disp example: [eax+0x0808004] */

			/* example: disp is 8bytes and size is 32bit */
			if (get_sizeof(o_key->mem->disp) > 
					(current_bits >> 3)) 
			{
				union {
					long long ll; /* 64-bit */
					short word;   /* 16-bit */
					int dword;    /* 32-bit */
				} u;
				u.ll = o_key->mem->disp;

				switch (current_bits) {
				case 16:
					o_key->mem->disp = u.word;
					break;
				case 32:
					o_key->mem->disp = u.dword;
					break;
				}
			}
			
		} /* if: disp */

		if (o_key->mem->base)
			o_key->mem->addr = (o_key->mem->base & 0xf0) >> 1;
		else if (o_key->mem->index)
			o_key->mem->addr = (o_key->mem->index & 0xf0) >> 1;
/*
		else
			o_key->mem->addr = current_bits;
*/
		
		return errno;

	} else if (o_key->reg = get_regid(str)) {	/* register operand */
		/********************
		 TODO: check_reg()
                ********************/
			
	} else if (is_numeric(str)) {			/* immedeate operand */
		/*******************
		TODO: check_imme()
                ********************/
		if (!o_key->imme)
			o_key->imme = (imme_t *)a64_malloc(sizeof(imme_t));

		o_key->imme->imme_value = (long long)str_to_n(str); 

/*
		union{
			long l[2];
			long long ll;
		}u;

		u.ll = o_key->imme->imme_value;
		printf("--%x%x--\n",u.l[1],u.l[0]);
*/
		unsigned int imme_size = 0;

		if (o_key->imme->cast > current_bits)
			errno |= ERR_CAST;

		else if (o_key->imme->cast)
			imme_size = o_key->imme->cast; 

		else
			o_key->imme->cast = 
				get_sizeof(o_key->imme->imme_value) * 8;

#if 0
		else if (get_sizeof(o_key->imme->imme_value) > 
					(current_bits >> 3)) 
		{
			imme_size = current_bits;
		}
		
		if (imme_size) {
			union {
				long long ll;
				int dword;
				short word;
			} u;
			u.ll = o_key->imme->imme_value;

			switch (current_bits) {
			case 16:
				o_key->imme->imme_value = u.word;
				break;
			case 32: 
				o_key->imme->imme_value = u.dword;
			}
		}

#endif
	} else if (is_label(str)) {
		/* this is a label for "jmp" or "call" */

	} else if (is_variable(str)) { /* is a variable value */
		/**********************************
                 * TODO: reserved for is_variable()
		 *********************************/
	} else {
		errno |= ERR_OPERAND;

		mount_err_link(errno, ops_errmsg, 0);
	}
	
do_error:
	/* it's not memory operand, so free o_key->mem */
	if (o_key->mem) {
		a64_free(o_key->mem);
		o_key->mem = 0;
	}


	return errno;
}


/*************************************************************
 example:
 parameter: s = "eax,(dword)es:[eax+ecx*8+0xc]"
	    ops_key = get the ops_key_t value for parameter s;
	
 return value:  error if errno value is set
		succssed if errno is 0

last change: 02-18-2006 14:20 by mik
**************************************************************/

errno_t get_ops_key(ops_key_t *ops_key, char *s) 
{
	/* have no operands */
	if (!s || !*s) return 0;


	int i = 0;
	char str[80];
	char trims[200];

	errno_t errno = 0;	/* return value */
		
	if (!trim_space(trims, s) || !ops_key)
		return ERR_OPERAND;

	s = trims;
	char *p = s + str_len(s) - 1;
	char *q = s;
	


	char tmp_msg[80];
	char *msg = get_err_msg_addr();

	/* find operands and get operand key word */
	while (*p) {
		q = p;

		while (*p != ',') {		/* search last ',' */
			if (p <= s) break;
			p--;
		}

		i = 0;
		if (*p == ',') {
			while (p+i+1 <= q) {
				str[i] = *(p+i+1);  i++;
			}
		} else if (p == s) {		/* head */
			while (p+i <= q) {
				str[i] = *(p+i); i++;
			}
		}
		str[i] = 0;
	

		o_key_t *okey = (o_key_t *)a64_malloc(sizeof(o_key_t));

		/* get operands key word */ 

		if (!ops_key->so_key) {		/* this is a source operand */
			ops_key->so_key = okey;	

		} else if (!ops_key->do_key) {  /* this is a dest operand */
			ops_key->do_key = okey;

		} else if (!ops_key->to_key) {	/* this is a three operand */
			ops_key->to_key = okey;

		} else {
			a64_free(okey);

			sprintf(tmp_msg, "at %d: %s\n",
				line, "operands over three");
			
			if (str_len(msg) + str_len(tmp_msg)
					< ERR_MSG_SIZE)
			{
				str_cat(msg, tmp_msg);	

				mount_err_link(0, 0, msg);
			} else {
				errno |= ERR_OPERAND;

				mount_err_link(errno, ops_errmsg, 0);

				return errno;
			}
		}		

		errno |= get_o_key(okey, str);

		if (p <= s) break;
		p--;			/*  search next operand */
	}
		
	return errno;
}


/***********************************************************************
 function: unsigned int get_attr(o_key_t* o_key);

 parameter: 
	   o_key: a operand key word

 return value: 
		unsigned int operand attribute word

last change: 02-17-2006 21:10 by mik
***********************************************************************/

unsigned int get_attr(o_key_t *o_key)
{
	if (!o_key) return 0;

	unsigned int o_attr = 0;

	if (o_key->reg) {
		o_attr |= 0x80000000 >> (o_key->reg & 0x07);

		switch (o_key->reg & 0xf0) {
		case 0x10:
		case 0x20:
		case 0x40:
		case 0x80:
			o_attr |= GPR | ((o_key->reg & 0xf0) >> 4);
			break;
		case 0xa0: o_attr |= SREG | SIZE16; break;
		case 0xc0: o_attr |= CREG | SIZE32; break;
		case 0xd0: o_attr |= DREG | SIZE32; break;
		case 0xe0: o_attr |= MMX | SIZE64; break;
		case 0xf0: o_attr |= XMM | SIZE128; break;
		}	
	} else if (o_key->mem) {
		if (!o_key->mem->base && !o_key->mem->index) {
			if (o_key->mem->disp)
				o_attr |= MOFFSET;
		} else 
			o_attr |= MEM;
		/* get memory operand size */
		/* example: case is 32 chang to SIZE32 = cast >> 3 */
		o_attr |=  o_key->mem->cast >> 3;
	} else if (o_key->imme) {
		/* immediate operand not size */
		if (o_key->imme->imme_value == 1)
			o_attr |= IMME_1; 
		else
			o_attr |= IMME;
	
		unsigned int size = get_sizeof(o_key->imme->imme_value);

		/******************************
	 	 * TODO: reserved for imme size 
		 * example: (dword)0x0c
		 ******************************/

		if (o_key->imme->cast) {
			o_attr |= (o_key->imme->cast >> 3);
		} else {
			if (size == 1)
				o_attr |= 0x01;
			else if (size <= current_bits) {
				o_attr |= current_bits >> 3;
				o_key->imme->cast = current_bits;
			}
				
		}
	}

	return o_attr;
}



/************************************************************************
  function: errno get_ops_attr(ops_attr_t *ops_attr, ops_key_t *ops_key);

  parameter:
	    ops_key: operands key words

  return value: 
	        error if errno is set
                successed if errno is 0

last change: 02-17-2006 21:32 by mik
************************************************************************/

errno_t get_ops_attr(ops_attr_t *ops_attr, ops_key_t *ops_key)
{
	
	if (!ops_attr) 
		return ERR_OPERAND;

	if (!ops_key) {		/* no operands */
		ops_attr->so_attr = 0;
		ops_attr->do_attr = 0;
		ops_attr->to_attr = 0;

		return 0;
	}
	
	/* 
	   source operand is immediate. 
	   dest operand is register
	*/
	if (ops_key->so_key && ops_key->so_key->imme 
		&& ops_key->do_key && ops_key->do_key->reg) {
		if (get_sizeof(ops_key->so_key->imme->imme_value) > 
				((ops_key->do_key->reg & 0xf0) >> 4)) 
		{

			mount_err_link(ERR_OPERAND, ops_errmsg, 0);

			return ERR_OPERAND;
		}
	}

	ops_attr->so_attr = get_attr(ops_key->so_key);
	ops_attr->do_attr = get_attr(ops_key->do_key);
	ops_attr->to_attr = get_attr(ops_key->to_key);

	if (((OPTYPE(ops_attr->so_attr) == MEM) && 
		(OPTYPE(ops_attr->do_attr) == MEM)) || 
		((OPTYPE(ops_attr->so_attr) == IMME) &&
		(OPTYPE(ops_attr->do_attr) == IMME)))
	{
		mount_err_link(ERR_OPERAND, ops_errmsg, 0);

		return ERR_OPERAND;
	}

	return 0;
}



/************** the function get operands type ************
last change: 02-18-2006 12:11 by mik
***********************************************************/
ops_type_t get_ops_type(ops_key_t *ops_key)
{
	ops_type_t ops_type = 0;

	if (!ops_key) return 0;
	
	o_key_t *so_key = ops_key->so_key;
	o_key_t *do_key = ops_key->do_key;
	o_key_t *to_key = ops_key->to_key;

	/* get source operand type */
	if (so_key) 
		ops_type |= so_key->reg ? S_R : so_key->mem ? S_M : 
			so_key->imme ? S_I : 0;
	

	/* get dest operand type */
	if (do_key) 
		ops_type |= do_key->reg ? D_R : do_key->mem ? D_M :
			do_key->imme ? D_I : 0;
	

	/* get three operand type */
	if (to_key) 
		ops_type |= to_key->reg ? T_R : to_key->mem ? T_M : 
			to_key->imme ? T_I : 0;
	

	return ops_type;
}



unsigned int get_o_size(o_key_t *o_key)
{
	unsigned int o_size = 0;

	if (!o_key)
		return 0;

	if (o_key->reg)
		o_size = get_reg_size(o_key->reg);
	else if (o_key->mem) 
		o_size = o_key->mem->cast;
	else if (o_key->imme) {
		if (o_key->imme->cast)
			o_size = o_key->imme->cast;
		else if (o_key->imme->imme_value == 0)
			o_size = current_bits;
		else
			o_size = get_sizeof(o_key->imme->imme_value) * 8;
	}
	
	
	return o_size;
}

/*****************************************************************
the function get operands size

last change: 02-17-2006 21:54 by mik
******************************************************************/
unsigned int get_ops_size(ops_key_t *ops_key)
{
	unsigned int ops_size = 0;

	if (!ops_key) return 0;

	o_key_t *so_key = ops_key->so_key;
	o_key_t *do_key = ops_key->do_key;
	o_key_t *to_key = ops_key->to_key;

	if (so_key && !do_key && !to_key) { 	/* only one operand */
		if (so_key->reg) {
			ops_size = get_reg_size(so_key->reg);
			
		} else if (so_key->mem) {		
			/* only one operand case: 
			 * the operand size must be casted */
			ops_size = so_key->mem->cast;

		} else if (so_key->imme) {
			/**************************************
			* TODO: reserver for check imme size 
			**************************************/
			if (so_key->imme->cast) {
				ops_size = so_key->imme->cast;

			} else if (so_key->imme->imme_value == 0) {
				ops_size = current_bits;
			} else 
			     ops_size = 
				get_sizeof(so_key->imme->imme_value) * 8;
		}

	} else if (so_key && do_key && !to_key) { 	/* two operands */
		unsigned int reg_size = 0;

		if (so_key->reg && do_key->reg) {
			reg_size = get_reg_size(so_key->reg);
			if (get_reg_size(do_key->reg) > reg_size)
				reg_size = get_reg_size(do_key->reg);
		} else if (so_key->reg) 
			reg_size = get_reg_size(so_key->reg);
		else if (do_key->reg) 
			reg_size = get_reg_size(do_key->reg);

		unsigned int mem_size = so_key->mem ? so_key->mem->cast : 
			do_key->mem ? do_key->mem->cast : 0;

		unsigned int imme_size = so_key->imme ? 
			get_sizeof(so_key->imme->imme_value) * 8 : 
			do_key->imme ? get_sizeof(do_key->imme->imme_value) * 8 
				: 0; 
		
		if (reg_size) {
			if ((mem_size > reg_size) || (imme_size > reg_size))
				ops_size = 0;
			else
				ops_size = reg_size;
		} else if (mem_size) {
			if (imme_size > mem_size)
				ops_size = 0;
			else 
				ops_size = mem_size;
		} else
			ops_size = 0;

	} else if (so_key && do_key && to_key) {	/* three operands */
		ops_size = get_reg_size(to_key->reg);
	}

	return ops_size;
}


/******************************************************
* the function get operands address size
*
* last change: 02-18-2006 14:40 by mik
******************************************************/
unsigned int get_ops_addr(ops_key_t *ops_key)
{
	unsigned int addr = 0;
	
	if (!ops_key) return 0;

	mem_t *mem = ops_key->so_key && ops_key->so_key->mem ?
	 	ops_key->so_key->mem : ops_key->do_key && 
		ops_key->do_key->mem ? ops_key->do_key->mem :
		ops_key->to_key && ops_key->to_key->mem ? 
		ops_key->to_key->mem : 0;
	
/*	
	if (mem) {
		addr = mem->base ? (mem->base & 0xf0) >> 1 :
			mem->index ? (mem->index & 0xf0) >> 1:
			mem->disp ? get_sizeof(mem->disp) * 8 : 0;
	}

*/
	addr = mem ? mem->addr : 0;


	return addr;
}


/*********************************************************
 * the function check operand valid
 *
 * last change: 02-18-2006 14:15 by mik
 ********************************************************/

int check_ops_key(ops_key_t *ops_key)
{
	/* have no operand */
	if (!ops_key)
		return 1;
	
	int ops_size = get_ops_size(ops_key);
	int so_size = get_o_size(ops_key->so_key);
	int do_size = get_o_size(ops_key->do_key);
	int to_size = get_o_size(ops_key->to_key);
	int addr = get_ops_addr(ops_key);

	o_key_t *so_key = ops_key->so_key;
	o_key_t *do_key = ops_key->do_key;
	o_key_t *to_key = ops_key->to_key;


	if ((ops_size >= 64) && (current_bits != 64))
		return 0;

	if ((addr >= 64) && (current_bits != 64))
		return 0;

	if ((so_key && is_eGPR(so_key->reg)) || (do_key && is_eGPR(do_key->reg))
			|| (to_key && is_eGPR(to_key->reg)))
		if (current_bits != 64)
			return 0;


	switch (get_ops_type(ops_key)) {
	case D_R|S_R:
		if (do_size < so_size)
			return 0;
		break;
	case D_M|S_R:
		if (do_size && (do_size != so_size))
			return 0;
		break;
	case T_R|D_R|S_I:	/* this case for imul Gv, Ev, Iv */
	case T_R|D_M|S_I:
	case T_M|D_R|S_I:	/* this case for shld Ev,Gv,Ib */
		if (to_size < do_size)
			return 0;
		break;
	case T_M|D_R|S_R:
		if (do_size < so_size || to_size < do_size)
			return 0;
		break;
	}

#if 0
	if (ops_size && (ops_size <= current_bits) && (addr <= current_bits))
	{
		if ((current_bits == 64) && addr && (addr <= 16))	
			return 0;
		return 1;
	} else if ((current_bits == 16) && (ops_size < 64))
		return 1;	
#endif

	return 1;
}



/***************************************************

 follow for test....

***************************************************/

void release_o_key(o_key_t *o_key);

void release_ops_key(ops_key_t *ops_key) {
	if (ops_key->so_key) release_o_key(ops_key->so_key);
	if (ops_key->do_key) release_o_key(ops_key->do_key);
	if (ops_key->to_key) release_o_key(ops_key->to_key);
}


void release_o_key(o_key_t *o_key) 
{
	if (o_key) {
		if (o_key->mem)
			free(o_key->mem);
		free(o_key);
	}	
}


/****************************************************************/



void print_okey(o_key_t* o_key) {
	printf("-----------------------------------\n");
	printf("reg is %x\n", o_key->reg);
	printf("imme is %f\n", o_key->imme);
	union {
		long long ll;
		long l[2];
	} l;
	if (o_key->mem) {
		printf("---base is %x\n", o_key->mem->base);
		printf("---index is %x\n", o_key->mem->index);
		printf("---scale is %x\n", o_key->mem->scale);
		l.ll = o_key->mem->disp;	
		printf("---disp is %x\n", l.l[1]);
		printf("---disp is %x\n", l.l[0]);
		printf("---oseg is %x\n", o_key->mem->oseg);
		printf("---cast is %d\n", o_key->mem->cast);
		printf("---addr is %d\n", o_key->mem->addr);
	}
	printf("-----------------------------------------\n");
}

void print_ops(ops_key_t *ops) {
	if (ops) {
		if (ops->so_key) print_okey(ops->so_key);
		if (ops->do_key) print_okey(ops->do_key);
		if (ops->to_key) print_okey(ops->to_key);
	}
//	release_ops_key(ops);
}

void print_ops_attr(ops_attr_t *ops_attr)
{
	printf("so_attr: %x\n", ops_attr->so_attr);
	printf("do_attr: %x\n", ops_attr->do_attr);
	printf("to_attr: %x\n", ops_attr->to_attr);
}


static void print_ekey(e_key_t *e_key)
{
	while (e_key) {
		print_ops(e_key->ops_key);
		puts("**************************************");
		e_key = e_key->next;
	}
}