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

📄 ld-insn.c

📁 这个是LINUX下的GDB调度工具的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* The IGEN simulator generator for GDB, the GNU Debugger.   Copyright 2002 Free Software Foundation, Inc.   Contributed by Andrew Cagney.   This file is part of GDB.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 59 Temple Place - Suite 330,   Boston, MA 02111-1307, USA.  */#include "misc.h"#include "lf.h"#include "table.h"#include "filter.h"#include "igen.h"#include "ld-insn.h"static insn_word_entry *parse_insn_word (line_ref *line, char *string, int word_nr){  char *chp;  insn_word_entry *word = ZALLOC (insn_word_entry);  /* create a leading sentinal */  word->first = ZALLOC (insn_field_entry);  word->first->first = -1;  word->first->last = -1;  word->first->width = 0;  /* and a trailing sentinal */  word->last = ZALLOC (insn_field_entry);  word->last->first = options.insn_bit_size;  word->last->last = options.insn_bit_size;  word->last->width = 0;  /* link them together */  word->first->next = word->last;  word->last->prev = word->first;  /* now work through the formats */  chp = skip_spaces (string);  while (*chp != '\0')    {      char *start_pos;      int strlen_pos;      char *start_val;      int strlen_val;      insn_field_entry *new_field;      /* create / link in the new field */      new_field = ZALLOC (insn_field_entry);      new_field->next = word->last;      new_field->prev = word->last->prev;      new_field->next->prev = new_field;      new_field->prev->next = new_field;      new_field->word_nr = word_nr;      /* break out the first field (if present) */      start_pos = chp;      chp = skip_to_separator (chp, ".,!");      strlen_pos = back_spaces (start_pos, chp) - start_pos;      /* break out the second field (if present) */      if (*chp != '.')	{	  /* assume what was specified was the value (and not the start	     position).  Assume the value length implicitly specifies	     the number of bits */	  start_val = start_pos;	  strlen_val = strlen_pos;	  start_pos = "";	  strlen_pos = 0;	}      else	{	  chp++;		/* skip `.' */	  chp = skip_spaces (chp);	  start_val = chp;	  if (*chp == '/' || *chp == '*')	    {	      do		{		  chp++;		}	      while (*chp == '/' || *chp == '*');	    }	  else if (isalpha (*start_val))	    {	      do		{		  chp++;		}	      while (isalnum (*chp) || *chp == '_');	    }	  else if (isdigit (*start_val))	    {	      do		{		  chp++;		}	      while (isalnum (*chp));	    }	  strlen_val = chp - start_val;	  chp = skip_spaces (chp);	}      if (strlen_val == 0)	error (line, "Empty value field\n");      /* break out any conditional fields - { [ "!" | "=" [ <value> | <field-name> } */      while (*chp == '!' || *chp == '=')	{	  char *start;	  char *end;	  int len;	  insn_field_cond *new_cond = ZALLOC (insn_field_cond);	  /* determine the conditional test */	  switch (*chp)	    {	    case '=':	      new_cond->test = insn_field_cond_eq;	      break;	    case '!':	      new_cond->test = insn_field_cond_ne;	      break;	    default:	      ASSERT (0);	    }	  /* save the value */	  chp++;	  chp = skip_spaces (chp);	  start = chp;	  chp = skip_to_separator (chp, "+,:!=");	  end = back_spaces (start, chp);	  len = end - start;	  if (len == 0)	    error (line, "Missing or invalid conditional value\n");	  new_cond->string = NZALLOC (char, len + 1);	  strncpy (new_cond->string, start, len);	  /* determine the conditional type */	  if (isdigit (*start))	    {	      /* [ "!" | "=" ] <value> */	      new_cond->type = insn_field_cond_value;	      new_cond->value = a2i (new_cond->string);	    }	  else	    {	      /* [ "!" | "=" ] <field>  - check field valid */	      new_cond->type = insn_field_cond_field;	      /* new_cond->field is determined in later */	    }	  /* Only a single `=' is permitted. */	  if ((new_cond->test == insn_field_cond_eq	       && new_field->conditions != NULL)	      || (new_field->conditions != NULL		  && new_field->conditions->test == insn_field_cond_eq))	    error (line, "Only single conditional when `=' allowed\n");	  /* insert it */	  {	    insn_field_cond **last = &new_field->conditions;	    while (*last != NULL)	      last = &(*last)->next;	    *last = new_cond;	  }	}      /* NOW verify that the field was finished */      if (*chp == ',')	{	  chp = skip_spaces (chp + 1);	  if (*chp == '\0')	    error (line, "empty field\n");	}      else if (*chp != '\0')	{	  error (line, "Missing field separator\n");	}      /* copy the value */      new_field->val_string = NZALLOC (char, strlen_val + 1);      strncpy (new_field->val_string, start_val, strlen_val);      if (isdigit (new_field->val_string[0]))	{	  if (strlen_pos == 0)	    {	      /* when the length/pos field is omited, an integer field	         is always binary */	      unsigned64 val = 0;	      int i;	      for (i = 0; i < strlen_val; i++)		{		  if (new_field->val_string[i] != '0'		      && new_field->val_string[i] != '1')		    error (line, "invalid binary field %s\n",			   new_field->val_string);		  val = (val << 1) + (new_field->val_string[i] == '1');		}	      new_field->val_int = val;	      new_field->type = insn_field_int;	    }	  else	    {	      new_field->val_int = a2i (new_field->val_string);	      new_field->type = insn_field_int;	    }	}      else if (new_field->val_string[0] == '/')	{	  new_field->type = insn_field_reserved;	}      else if (new_field->val_string[0] == '*')	{	  new_field->type = insn_field_wild;	}      else	{	  new_field->type = insn_field_string;	  if (filter_is_member (word->field_names, new_field->val_string))	    error (line, "Field name %s is duplicated\n",		   new_field->val_string);	  filter_parse (&word->field_names, new_field->val_string);	}      if (new_field->type != insn_field_string	  && new_field->conditions != NULL)	error (line, "Conditionals can only be applied to named fields\n");      /* the copy the position */      new_field->pos_string = NZALLOC (char, strlen_pos + 1);      strncpy (new_field->pos_string, start_pos, strlen_pos);      if (strlen_pos == 0)	{	  new_field->first = new_field->prev->last + 1;	  if (new_field->first == 0	/* first field */	      && *chp == '\0'	/* no further fields */	      && new_field->type == insn_field_string)	    {	      /* A single string without any position, assume that it	         represents the entire instruction word */	      new_field->width = options.insn_bit_size;	    }	  else	    {	      /* No explicit width/position, assume value implicitly	         supplies the width */	      new_field->width = strlen_val;	    }	  new_field->last = new_field->first + new_field->width - 1;	  if (new_field->last >= options.insn_bit_size)	    error (line, "Bit position %d exceed instruction bit size (%d)\n",		   new_field->last, options.insn_bit_size);	}      else if (options.insn_specifying_widths)	{	  new_field->first = new_field->prev->last + 1;	  new_field->width = a2i (new_field->pos_string);	  new_field->last = new_field->first + new_field->width - 1;	  if (new_field->last >= options.insn_bit_size)	    error (line, "Bit position %d exceed instruction bit size (%d)\n",		   new_field->last, options.insn_bit_size);	}      else	{	  new_field->first = target_a2i (options.hi_bit_nr,					 new_field->pos_string);	  new_field->last = new_field->next->first - 1;	/* guess */	  new_field->width = new_field->last - new_field->first + 1;	/* guess */	  new_field->prev->last = new_field->first - 1;	/*fix */	  new_field->prev->width = new_field->first - new_field->prev->first;	/*fix */	}    }  /* fiddle first/last so that the sentinals disapear */  ASSERT (word->first->last < 0);  ASSERT (word->last->first >= options.insn_bit_size);  word->first = word->first->next;  word->last = word->last->prev;  /* check that the last field goes all the way to the last bit */  if (word->last->last != options.insn_bit_size - 1)    {      if (options.warn.width)	options.warning (line, "Instruction format is not %d bits wide\n",			 options.insn_bit_size);      word->last->last = options.insn_bit_size - 1;    }  /* now go over this again, pointing each bit position at a field     record */  {    insn_field_entry *field;    for (field = word->first;	 field->last < options.insn_bit_size; field = field->next)      {	int i;	for (i = field->first; i <= field->last; i++)	  {	    word->bit[i] = ZALLOC (insn_bit_entry);	    word->bit[i]->field = field;	    switch (field->type)	      {	      case insn_field_invalid:		ASSERT (0);		break;	      case insn_field_int:		word->bit[i]->mask = 1;		word->bit[i]->value = ((field->val_int					& ((insn_uint) 1 <<					   (field->last - i))) != 0);	      case insn_field_reserved:	      case insn_field_wild:	      case insn_field_string:		/* if we encounter a constant conditional, encode		   their bit value. */		if (field->conditions != NULL		    && field->conditions->test == insn_field_cond_eq		    && field->conditions->type == insn_field_cond_value)		  {		    word->bit[i]->mask = 1;		    word->bit[i]->value = ((field->conditions->value					    & ((insn_uint) 1 <<					       (field->last - i))) != 0);		  }		break;	      }	  }      }  }  return word;}static voidparse_insn_words (insn_entry * insn, char *formats){  insn_word_entry **last_word = &insn->words;  char *chp;  /* now work through the formats */  insn->nr_words = 0;  chp = formats;  while (1)    {      char *start_pos;      char *end_pos;      int strlen_pos;      char *format;      insn_word_entry *new_word;      /* skip leading spaces */      chp = skip_spaces (chp);      /* break out the format */      start_pos = chp;      chp = skip_to_separator (chp, "+");      end_pos = back_spaces (start_pos, chp);      strlen_pos = end_pos - start_pos;      /* check that something was there */      if (strlen_pos == 0)	error (insn->line, "missing or empty instruction format\n");      /* parse the field */      format = NZALLOC (char, strlen_pos + 1);      strncpy (format, start_pos, strlen_pos);      new_word = parse_insn_word (insn->line, format, insn->nr_words);      insn->nr_words++;      if (filter_is_common (insn->field_names, new_word->field_names))	error (insn->line, "Field name duplicated between two words\n");      filter_add (&insn->field_names, new_word->field_names);      /* insert it */      *last_word = new_word;      last_word = &new_word->next;      /* last format? */      if (*chp == '\0')	break;      ASSERT (*chp == '+');      chp++;    }  /* create a quick access array (indexed by word) of the same structure */  {    int i;    insn_word_entry *word;    insn->word = NZALLOC (insn_word_entry *, insn->nr_words + 1);    for (i = 0, word = insn->words;	 i < insn->nr_words; i++, word = word->next)      insn->word[i] = word;  }  /* Go over all fields that have conditionals refering to other     fields.  Link the fields up.  Verify that the two fields have the     same size. Verify that the two fields are different */  {    int i;    for (i = 0; i < insn->nr_words; i++)      {	insn_word_entry *word = insn->word[i];	insn_field_entry *f;	for (f = word->first; f->last < options.insn_bit_size; f = f->next)	  {	    insn_field_cond *cond;	    for (cond = f->conditions; cond != NULL; cond = cond->next)	      {		if (cond->type == insn_field_cond_field)		  {		    int j;		    if (strcmp (cond->string, f->val_string) == 0)		      error (insn->line,			     "Conditional `%s' of field `%s' refers to its self\n",			     cond->string, f->val_string);		    for (j = 0; j <= i && cond->field == NULL; j++)		      {			insn_word_entry *refered_word = insn->word[j];			insn_field_entry *refered_field;			for (refered_field = refered_word->first;			     refered_field != NULL && cond->field == NULL;			     refered_field = refered_field->next)			  {			    if (refered_field->type == insn_field_string				&& strcmp (refered_field->val_string,					   cond->string) == 0)			      {				/* found field being refered to by conditonal */				cond->field = refered_field;				/* check refered to and this field are				   the same size */

⌨️ 快捷键说明

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