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

📄 tc-i960.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
        The following supports generation of branch-prediction instrumentation        (turned on by -b switch).  The instrumentation collects counts        of branches taken/not-taken for later input to a utility that will        set the branch prediction bits of the instructions in accordance with        the behavior observed.  (Note that the KX series does not have        brach-prediction.)        The instrumentation consists of:        (1) before and after each conditional branch, a call to an external            routine that increments and steps over an inline counter.  The            counter itself, initialized to 0, immediately follows the call            instruction.  For each branch, the counter following the branch            is the number of times the branch was not taken, and the difference            between the counters is the number of times it was taken.  An            example of an instrumented conditional branch:                                call    BR_CNT_FUNC                                .word   0                LBRANCH23:      be      label                                call    BR_CNT_FUNC                                .word   0        (2) a table of pointers to the instrumented branches, so that an            external postprocessing routine can locate all of the counters.            the table begins with a 2-word header: a pointer to the next in            a linked list of such tables (initialized to 0);  and a count            of the number of entries in the table (exclusive of the header.            Note that input source code is expected to already contain calls            an external routine that will link the branch local table into a            list of such tables. *//* Number of branches instrumented so far.  Also used to generate   unique local labels for each instrumented branch.  */static int br_cnt;#define BR_LABEL_BASE	"LBRANCH"/* Basename of local labels on instrumented branches, to avoid   conflict with compiler- generated local labels.  */#define BR_CNT_FUNC	"__inc_branch"/* Name of the external routine that will increment (and step over) an   inline counter.  */#define BR_TAB_NAME	"__BRANCH_TABLE__"/* Name of the table of pointers to branches.  A local (i.e.,   non-external) symbol.  *//*****************************************************************************   md_begin:  One-time initialization.  	Set up hash tables.  *************************************************************************** */voidmd_begin (){  int i;			/* Loop counter */  const struct i960_opcode *oP;	/* Pointer into opcode table */  const char *retval;		/* Value returned by hash functions */  op_hash = hash_new ();  reg_hash = hash_new ();  areg_hash = hash_new ();  /* For some reason, the base assembler uses an empty string for "no     error message", instead of a NULL pointer.  */  retval = 0;  for (oP = i960_opcodes; oP->name && !retval; oP++)    retval = hash_insert (op_hash, oP->name, (PTR) oP);  for (i = 0; regnames[i].reg_name && !retval; i++)    retval = hash_insert (reg_hash, regnames[i].reg_name,			  (char *) &regnames[i].reg_num);  for (i = 0; aregs[i].areg_name && !retval; i++)    retval = hash_insert (areg_hash, aregs[i].areg_name,			  (char *) &aregs[i].areg_num);  if (retval)    as_fatal (_("Hashing returned \"%s\"."), retval);}/*****************************************************************************   md_assemble:  Assemble an instruction   Assumptions about the passed-in text:  	- all comments, labels removed  	- text is an instruction  	- all white space compressed to single blanks  	- all character constants have been replaced with decimal  *************************************************************************** */voidmd_assemble (textP)     char *textP;		/* Source text of instruction */{  /* Parsed instruction text, containing NO whitespace: arg[0]->opcode     mnemonic arg[1-3]->operands, with char constants replaced by     decimal numbers.  */  char *args[4];  int n_ops;			/* Number of instruction operands */  /* Pointer to instruction description */  struct i960_opcode *oP;  /* TRUE iff opcode mnemonic included branch-prediction suffix (".f"     or ".t").  */  int branch_predict;  /* Setting of branch-prediction bit(s) to be OR'd into instruction     opcode of CTRL/COBR format instructions.  */  long bp_bits;  int n;			/* Offset of last character in opcode mnemonic */  const char *bp_error_msg = _("branch prediction invalid on this opcode");  /* Parse instruction into opcode and operands */  memset (args, '\0', sizeof (args));  n_ops = i_scan (textP, args);  if (n_ops == -1)    {      return;			/* Error message already issued */    }  /* Do "macro substitution" (sort of) on 'ldconst' pseudo-instruction */  if (!strcmp (args[0], "ldconst"))    {      n_ops = parse_ldconst (args);      if (n_ops == -1)	{	  return;	}    }  /* Check for branch-prediction suffix on opcode mnemonic, strip it off */  n = strlen (args[0]) - 1;  branch_predict = 0;  bp_bits = 0;  if (args[0][n - 1] == '.' && (args[0][n] == 't' || args[0][n] == 'f'))    {      /* We could check here to see if the target architecture	 supports branch prediction, but why bother?  The bit will	 just be ignored by processors that don't use it.  */      branch_predict = 1;      bp_bits = (args[0][n] == 't') ? BP_TAKEN : BP_NOT_TAKEN;      args[0][n - 1] = '\0';	/* Strip suffix from opcode mnemonic */    }  /* Look up opcode mnemonic in table and check number of operands.     Check that opcode is legal for the target architecture.  If all     looks good, assemble instruction.  */  oP = (struct i960_opcode *) hash_find (op_hash, args[0]);  if (!oP || !targ_has_iclass (oP->iclass))    {      as_bad (_("invalid opcode, \"%s\"."), args[0]);    }  else if (n_ops != oP->num_ops)    {      as_bad (_("improper number of operands.  expecting %d, got %d"),	      oP->num_ops, n_ops);    }  else    {      switch (oP->format)	{	case FBRA:	case CTRL:	  ctrl_fmt (args[1], oP->opcode | bp_bits, oP->num_ops);	  if (oP->format == FBRA)	    {	      /* Now generate a 'bno' to same arg */	      ctrl_fmt (args[1], BNO | bp_bits, 1);	    }	  break;	case COBR:	case COJ:	  cobr_fmt (args, oP->opcode | bp_bits, oP);	  break;	case REG:	  if (branch_predict)	    {	      as_warn (bp_error_msg);	    }	  reg_fmt (args, oP);	  break;	case MEM1:	  if (args[0][0] == 'c' && args[0][1] == 'a')	    {	      if (branch_predict)		{		  as_warn (bp_error_msg);		}	      mem_fmt (args, oP, 1);	      break;	    }	case MEM2:	case MEM4:	case MEM8:	case MEM12:	case MEM16:	  if (branch_predict)	    {	      as_warn (bp_error_msg);	    }	  mem_fmt (args, oP, 0);	  break;	case CALLJ:	  if (branch_predict)	    {	      as_warn (bp_error_msg);	    }	  /* Output opcode & set up "fixup" (relocation); flag	     relocation as 'callj' type.  */	  know (oP->num_ops == 1);	  get_cdisp (args[1], "CTRL", oP->opcode, 24, 0, 1);	  break;	default:	  BAD_CASE (oP->format);	  break;	}    }}				/* md_assemble() *//*****************************************************************************   md_number_to_chars:  convert a number to target byte order  *************************************************************************** */voidmd_number_to_chars (buf, value, n)     char *buf;     valueT value;     int n;{  number_to_chars_littleendian (buf, value, n);}/*****************************************************************************   md_chars_to_number:  convert from target byte order to host byte order.  *************************************************************************** */intmd_chars_to_number (val, n)     unsigned char *val;	/* Value in target byte order */     int n;			/* Number of bytes in the input */{  int retval;  for (retval = 0; n--;)    {      retval <<= 8;      retval |= val[n];    }  return retval;}#define MAX_LITTLENUMS	6#define LNUM_SIZE	sizeof (LITTLENUM_TYPE)/*****************************************************************************   md_atof:	convert ascii to floating point   Turn a string at input_line_pointer into a floating point constant of type   'type', and store the appropriate bytes at *litP.  The number of LITTLENUMS   emitted is returned at 'sizeP'.  An error message is returned, or a pointer   to an empty message if OK.   Note we call the i386 floating point routine, rather than complicating   things with more files or symbolic links.  *************************************************************************** */char *md_atof (type, litP, sizeP)     int type;     char *litP;     int *sizeP;{  LITTLENUM_TYPE words[MAX_LITTLENUMS];  LITTLENUM_TYPE *wordP;  int prec;  char *t;  char *atof_ieee ();  switch (type)    {    case 'f':    case 'F':      prec = 2;      break;    case 'd':    case 'D':      prec = 4;      break;    case 't':    case 'T':      prec = 5;      type = 'x';		/* That's what atof_ieee() understands */      break;    default:      *sizeP = 0;      return _("Bad call to md_atof()");    }  t = atof_ieee (input_line_pointer, type, words);  if (t)    {      input_line_pointer = t;    }  *sizeP = prec * LNUM_SIZE;  /* Output the LITTLENUMs in REVERSE order in accord with i80960     word-order.  (Dunno why atof_ieee doesn't do it in the right     order in the first place -- probably because it's a hack of     atof_m68k.)  */  for (wordP = words + prec - 1; prec--;)    {      md_number_to_chars (litP, (long) (*wordP--), LNUM_SIZE);      litP += sizeof (LITTLENUM_TYPE);    }  return 0;}/*****************************************************************************   md_number_to_imm  *************************************************************************** */voidmd_number_to_imm (buf, val, n)     char *buf;     long val;     int n;{  md_number_to_chars (buf, val, n);}/*****************************************************************************   md_number_to_disp  *************************************************************************** */voidmd_number_to_disp (buf, val, n)     char *buf;     long val;     int n;{  md_number_to_chars (buf, val, n);}/*****************************************************************************   md_number_to_field:  	Stick a value (an address fixup) into a bit field of  	previously-generated instruction.  *************************************************************************** */voidmd_number_to_field (instrP, val, bfixP)     char *instrP;		/* Pointer to instruction to be fixed */     long val;			/* Address fixup value */     bit_fixS *bfixP;		/* Description of bit field to be fixed up */{  int numbits;			/* Length of bit field to be fixed */  long instr;			/* 32-bit instruction to be fixed-up */  long sign;			/* 0 or -1, according to sign bit of 'val' */  /* Convert instruction back to host byte order.  */  instr = md_chars_to_number (instrP, 4);  /* Surprise! -- we stored the number of bits to be modified rather     than a pointer to a structure.  */  numbits = (int) bfixP;  if (numbits == 1)    {      /* This is a no-op, stuck here by reloc_callj() */      return;    }  know ((numbits == 13) || (numbits == 24));  /* Propagate sign bit of 'val' for the given number of bits.  Result     should be all 0 or all 1.  */  sign = val >> ((int) numbits - 1);  if (((val < 0) && (sign != -1))      || ((val > 0) && (sign != 0)))    {      as_bad (_("Fixup of %ld too large for field width of %d"),	      val, numbits);    }  else    {      /* Put bit field into instruction and write back in target         * byte order.       */      val &= ~(-1 << (int) numbits);	/* Clear unused sign bits */      instr |= val;      md_number_to_chars (instrP, instr, 4);    }}				/* md_number_to_field() *//*****************************************************************************   md_parse_option  	Invocation line includes a switch not recognized by the base assembler.  	See if it's a processor-specific option.  For the 960, these are:  	-norelax:  		Conditional branch instructions that require displacements  		greater than 13 bits (or that have external targets) should  		generate errors.  The default is to replace each such  		instruction with the corresponding compare (or chkbit) and  		branch instructions.  Note that the Intel "j" cobr directives  		are ALWAYS "de-optimized" in this way when necessary,  		regardless of the setting of this option.  	-b:  		Add code to collect information about branches taken, for  		later optimization of branch prediction bits by a separate  		tool.  COBR and CNTL format instructions have branch  		prediction bits (in the CX architecture);  if "BR" represents  		an instruction in one of these classes, the following rep-  		resents the code generated by the assembler:  			call	<increment routine>  			.word	0	# pre-counter  		Label:  BR  			call	<increment routine>  			.word	0	# post-counter  		A table of all such "Labels" is also generated.  	-AKA, -AKB, -AKC, -ASA, -ASB, -AMC, -ACA:  		Select the 80960 architecture.  Instructions or features not  		supported by the selected architecture cause fatal errors.  		The default is to generate code for any instruction or feature  		that is supported by SOME version of the 960 (even if this  		means mixing architectures!).  ****************************************************************************/CONST char *md_shortopts = "A:b";struct option md_longopts[] ={#define OPTION_LINKRELAX (OPTION_MD_BASE)  {"linkrelax", no_argument, NULL, OPTION_LINKRELAX},  {"link-relax", no_argument, NULL, OPTION_LINKRELAX},#define OPTION_NORELAX (OPTION_MD_BASE + 1)  {"norelax", no_argument, NULL, OPTION_NORELAX},  {"no-relax", no_argument, NULL, OPTION_NORELAX},  {NULL, no_argument, NULL, 0}};size_t md_longopts_size = sizeof (md_longopts);struct tabentry  {    char *flag;

⌨️ 快捷键说明

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