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

📄 gen.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"#include "ld-decode.h"#include "gen.h"static insn_uintsub_val (insn_uint val, int val_last_pos, int first_pos, int last_pos){  return ((val >> (val_last_pos - last_pos))	  & (((insn_uint) 1 << (last_pos - first_pos + 1)) - 1));}static voidupdate_depth (lf *file, gen_entry *entry, int depth, void *data){  int *max_depth = (int *) data;  if (*max_depth < depth)    *max_depth = depth;}intgen_entry_depth (gen_entry *table){  int depth = 0;  gen_entry_traverse_tree (NULL, table, 1, NULL,	/*start */			   update_depth, NULL,	/*end */			   &depth);	/* data */  return depth;}static voidprint_gen_entry_path (line_ref *line, gen_entry *table, error_func *print){  if (table->parent == NULL)    {      if (table->top->model != NULL)	print (line, "%s", table->top->model->name);      else	print (line, "");    }  else    {      print_gen_entry_path (line, table->parent, print);      print (NULL, ".%d", table->opcode_nr);    }}static voidprint_gen_entry_insns (gen_entry *table,		       error_func *print,		       char *first_message, char *next_message){  insn_list *i;  char *message;  message = first_message;  for (i = table->insns; i != NULL; i = i->next)    {      insn_entry *insn = i->insn;      print_gen_entry_path (insn->line, table, print);      print (NULL, ": %s.%s %s\n", insn->format_name, insn->name, message);      if (next_message != NULL)	message = next_message;    }}/* same as strcmp */static intinsn_field_cmp (insn_word_entry *l, insn_word_entry *r){  while (1)    {      int bit_nr;      if (l == NULL && r == NULL)	return 0;		/* all previous fields the same */      if (l == NULL)	return -1;		/* left shorter than right */      if (r == NULL)	return +1;		/* left longer than right */      for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)	{	  if (l->bit[bit_nr]->field->type != insn_field_string)	    continue;	  if (r->bit[bit_nr]->field->type != insn_field_string)	    continue;	  if (l->bit[bit_nr]->field->conditions == NULL)	    continue;	  if (r->bit[bit_nr]->field->conditions == NULL)	    continue;	  if (0)	    printf ("%s%s%s VS %s%s%s\n",		    l->bit[bit_nr]->field->val_string,		    l->bit[bit_nr]->field->conditions->test ==		    insn_field_cond_eq ? "=" : "!",		    l->bit[bit_nr]->field->conditions->string,		    r->bit[bit_nr]->field->val_string,		    r->bit[bit_nr]->field->conditions->test ==		    insn_field_cond_eq ? "=" : "!",		    r->bit[bit_nr]->field->conditions->string);	  if (l->bit[bit_nr]->field->conditions->test == insn_field_cond_eq	      && r->bit[bit_nr]->field->conditions->test ==	      insn_field_cond_eq)	    {	      if (l->bit[bit_nr]->field->conditions->type ==		  insn_field_cond_field		  && r->bit[bit_nr]->field->conditions->type ==		  insn_field_cond_field)		/* somewhat arbitrary */		{		  int cmp = strcmp (l->bit[bit_nr]->field->conditions->string,				    r->bit[bit_nr]->field->conditions->				    string);		  if (cmp != 0)		    return cmp;		  else		    continue;		}	      if (l->bit[bit_nr]->field->conditions->type ==		  insn_field_cond_field)		return +1;	      if (r->bit[bit_nr]->field->conditions->type ==		  insn_field_cond_field)		return -1;	      /* The case of both fields having constant values should have	         already have been handled because such fields are converted	         into normal constant fields. */	      continue;	    }	  if (l->bit[bit_nr]->field->conditions->test == insn_field_cond_eq)	    return +1;		/* left = only */	  if (r->bit[bit_nr]->field->conditions->test == insn_field_cond_eq)	    return -1;		/* right = only */	  /* FIXME: Need to some what arbitrarily order conditional lists */	  continue;	}      l = l->next;      r = r->next;    }}/* same as strcmp */static intinsn_word_cmp (insn_word_entry *l, insn_word_entry *r){  while (1)    {      int bit_nr;      if (l == NULL && r == NULL)	return 0;		/* all previous fields the same */      if (l == NULL)	return -1;		/* left shorter than right */      if (r == NULL)	return +1;		/* left longer than right */      for (bit_nr = 0; bit_nr < options.insn_bit_size; bit_nr++)	{	  if (l->bit[bit_nr]->mask < r->bit[bit_nr]->mask)	    return -1;	  if (l->bit[bit_nr]->mask > r->bit[bit_nr]->mask)	    return 1;	  if (l->bit[bit_nr]->value < r->bit[bit_nr]->value)	    return -1;	  if (l->bit[bit_nr]->value > r->bit[bit_nr]->value)	    return 1;	}      l = l->next;      r = r->next;    }}/* same as strcmp */static intopcode_bit_cmp (opcode_bits *l, opcode_bits *r){  if (l == NULL && r == NULL)    return 0;			/* all previous bits the same */  if (l == NULL)    return -1;			/* left shorter than right */  if (r == NULL)    return +1;			/* left longer than right */  /* most significant word */  if (l->field->word_nr < r->field->word_nr)    return +1;			/* left has more significant word */  if (l->field->word_nr > r->field->word_nr)    return -1;			/* right has more significant word */  /* most significant bit? */  if (l->first < r->first)    return +1;			/* left as more significant bit */  if (l->first > r->first)    return -1;			/* right as more significant bit */  /* nr bits? */  if (l->last < r->last)    return +1;			/* left as less bits */  if (l->last > r->last)    return -1;			/* right as less bits */  /* value? */  if (l->value < r->value)    return -1;  if (l->value > r->value)    return 1;  return 0;}/* same as strcmp */static intopcode_bits_cmp (opcode_bits *l, opcode_bits *r){  while (1)    {      int cmp;      if (l == NULL && r == NULL)	return 0;		/* all previous bits the same */      cmp = opcode_bit_cmp (l, r);      if (cmp != 0)	return cmp;      l = l->next;      r = r->next;    }}/* same as strcmp */static opcode_bits *new_opcode_bits (opcode_bits *old_bits,		 int value,		 int first,		 int last, insn_field_entry *field, opcode_field *opcode){  opcode_bits *new_bits = ZALLOC (opcode_bits);  new_bits->field = field;  new_bits->value = value;  new_bits->first = first;  new_bits->last = last;  new_bits->opcode = opcode;  if (old_bits != NULL)    {      opcode_bits *new_list;      opcode_bits **last = &new_list;      new_list = new_opcode_bits (old_bits->next,				  old_bits->value,				  old_bits->first,				  old_bits->last,				  old_bits->field, old_bits->opcode);      while (*last != NULL)	{	  int cmp = opcode_bit_cmp (new_bits, *last);	  if (cmp < 0)		/* new < new_list */	    {	      break;	    }	  if (cmp == 0)	    {	      ERROR ("Duplicated insn bits in list");	    }	  last = &(*last)->next;	}      new_bits->next = *last;      *last = new_bits;      return new_list;    }  else    {      return new_bits;    }}/* Same as strcmp().  */static intname_cmp (const char *l, const char *r){  if (l == NULL && r == NULL)    return 0;  if (l != NULL && r == NULL)    return -1;  if (l == NULL && r != NULL)    return +1;  return strcmp (l, r);}typedef enum{  merge_duplicate_insns,  report_duplicate_insns,}duplicate_insn_actions;static insn_list *insn_list_insert (insn_list **cur_insn_ptr,		  int *nr_insns,		  insn_entry * insn,		  opcode_bits *expanded_bits,		  opcode_field *opcodes,		  int nr_prefetched_words,		  duplicate_insn_actions duplicate_action){  /* insert it according to the order of the fields & bits */  for (; (*cur_insn_ptr) != NULL; cur_insn_ptr = &(*cur_insn_ptr)->next)    {      int cmp;      /* key#1 sort according to the constant fields of each instruction */      cmp = insn_word_cmp (insn->words, (*cur_insn_ptr)->insn->words);      if (cmp < 0)	break;      else if (cmp > 0)	continue;      /* key#2 sort according to the expanded bits of each instruction */      cmp = opcode_bits_cmp (expanded_bits, (*cur_insn_ptr)->expanded_bits);      if (cmp < 0)	break;      else if (cmp > 0)	continue;      /* key#3 sort according to the non-constant fields of each instruction */      cmp = insn_field_cmp (insn->words, (*cur_insn_ptr)->insn->words);      if (cmp < 0)	break;      else if (cmp > 0)	continue;      if (duplicate_action == merge_duplicate_insns)	{	  /* key#4: If we're going to merge duplicates, also sort	     according to the format_name.  Two instructions with	     identical decode patterns, but different names, are	     considered different when merging.  Duplicates are only	     important when creating a decode table (implied by	     report_duplicate_insns) as such a table only has the	     instruction's bit code as a way of differentiating	     between instructions.  */	  int cmp = name_cmp (insn->format_name,			      (*cur_insn_ptr)->insn->format_name);	  if (cmp < 0)	    break;	  else if (cmp > 0)	    continue;	}      if (duplicate_action == merge_duplicate_insns)	{	  /* key#5: If we're going to merge duplicates, also sort	     according to the name.  See comment above for	     format_name.  */	  int cmp = name_cmp (insn->name, (*cur_insn_ptr)->insn->name);	  if (cmp < 0)	    break;	  else if (cmp > 0)	    continue;	}      /* duplicate keys, report problem */      switch (duplicate_action)	{	case report_duplicate_insns:	  /* It would appear that we have two instructions with the	     same constant field values across all words and bits.	     This error can also occure when insn_field_cmp() is	     failing to differentiate between two instructions that	     differ only in their conditional fields. */	  warning (insn->line,		   "Two instructions with identical constant fields\n");	  error ((*cur_insn_ptr)->insn->line,		 "Location of duplicate instruction\n");	case merge_duplicate_insns:	  /* Add the opcode path to the instructions list */	  if (options.trace.insn_insertion)	    {	      notify ((*cur_insn_ptr)->insn->line,		      "%s.%s: insert merge %s.%s\n",		      (*cur_insn_ptr)->insn->format_name,		      (*cur_insn_ptr)->insn->name,		      insn->format_name,		      insn->name);	    }	  if (opcodes != NULL)	    {	      insn_opcodes **last = &(*cur_insn_ptr)->opcodes;	      while (*last != NULL)		{		  last = &(*last)->next;		}	      (*last) = ZALLOC (insn_opcodes);	      (*last)->opcode = opcodes;	    }	  /* Use the larger nr_prefetched_words */	  if ((*cur_insn_ptr)->nr_prefetched_words < nr_prefetched_words)	    (*cur_insn_ptr)->nr_prefetched_words = nr_prefetched_words;	  return (*cur_insn_ptr);	}    }  /* create a new list entry and insert it */  {    insn_list *new_insn = ZALLOC (insn_list);    if (options.trace.insn_insertion)      {	notify (insn->line,		"%s.%s: insert new\n",		insn->format_name,		insn->name);      }    new_insn->insn = insn;    new_insn->expanded_bits = expanded_bits;    new_insn->next = (*cur_insn_ptr);    new_insn->nr_prefetched_words = nr_prefetched_words;    if (opcodes != NULL)      {	new_insn->opcodes = ZALLOC (insn_opcodes);	new_insn->opcodes->opcode = opcodes;

⌨️ 快捷键说明

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