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

📄 tc-vax.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 5 页
字号:
/* tc-vax.c - vax-specific -   Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1998, 2000, 2001   Free Software Foundation, Inc.   This file is part of GAS, the GNU Assembler.   GAS 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, or (at your option)   any later version.   GAS 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 GAS; see the file COPYING.  If not, write to the Free   Software Foundation, 59 Temple Place - Suite 330, Boston, MA   02111-1307, USA.  */#include "as.h"#include "vax-inst.h"#include "obstack.h"		/* For FRAG_APPEND_1_CHAR macro in "frags.h" *//* These chars start a comment anywhere in a source file (except inside   another comment */const char comment_chars[] = "#";/* These chars only start a comment at the beginning of a line.  *//* Note that for the VAX the are the same as comment_chars above.  */const char line_comment_chars[] = "#";const char line_separator_chars[] = ";";/* Chars that can be used to separate mant from exp in floating point nums */const char EXP_CHARS[] = "eE";/* Chars that mean this number is a floating point constant *//* as in 0f123.456 *//* or    0H1.234E-12 (see exp chars above) */const char FLT_CHARS[] = "dDfFgGhH";/* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be   changed in read.c .  Ideally it shouldn't have to know about it at all,   but nothing is ideal around here.  *//* Hold details of an operand expression */static expressionS exp_of_operand[VIT_MAX_OPERANDS];static segT seg_of_operand[VIT_MAX_OPERANDS];/* A vax instruction after decoding.  */static struct vit v;/* Hold details of big operands.  */LITTLENUM_TYPE big_operand_bits[VIT_MAX_OPERANDS][SIZE_OF_LARGE_NUMBER];FLONUM_TYPE float_operand[VIT_MAX_OPERANDS];/* Above is made to point into big_operand_bits by md_begin().  */int flag_hash_long_names;	/* -+ */int flag_one;			/* -1 */int flag_show_after_trunc;	/* -H */int flag_no_hash_mixed_case;	/* -h NUM *//* * For VAX, relative addresses of "just the right length" are easy. * The branch displacement is always the last operand, even in * synthetic instructions. * For VAX, we encode the relax_substateTs (in e.g. fr_substate) as: * *		    4       3       2       1       0	     bit number *	---/ /--+-------+-------+-------+-------+-------+ *		|     what state ?	|  how long ?	| *	---/ /--+-------+-------+-------+-------+-------+ * * The "how long" bits are 00=byte, 01=word, 10=long. * This is a Un*x convention. * Not all lengths are legit for a given value of (what state). * The "how long" refers merely to the displacement length. * The address usually has some constant bytes in it as well. * groups for VAX address relaxing. 1.	"foo" pc-relative. length of byte, word, long 2a.	J<cond> where <cond> is a simple flag test. length of byte, word, long. VAX opcodes are:	(Hex) bneq/bnequ	12 beql/beqlu	13 bgtr		14 bleq		15 bgeq		18 blss		19 bgtru		1a blequ		1b bvc		1c bvs		1d bgequ/bcc	1e blssu/bcs	1f Always, you complement 0th bit to reverse condition. Always, 1-byte opcode, then 1-byte displacement. 2b.	J<cond> where cond tests a memory bit. length of byte, word, long. Vax opcodes are:	(Hex) bbs		e0 bbc		e1 bbss		e2 bbcs		e3 bbsc		e4 bbcc		e5 Always, you complement 0th bit to reverse condition. Always, 1-byte opcde, longword-address, byte-address, 1-byte-displacement 2c.	J<cond> where cond tests low-order memory bit length of byte,word,long. Vax opcodes are:	(Hex) blbs		e8 blbc		e9 Always, you complement 0th bit to reverse condition. Always, 1-byte opcode, longword-address, 1-byte displacement. 3.	Jbs/Jbr. length of byte,word,long. Vax opcodes are:	(Hex) bsbb		10 brb		11 These are like (2) but there is no condition to reverse. Always, 1 byte opcode, then displacement/absolute. 4a.	JacbX length of word, long. Vax opcodes are:	(Hex) acbw		3d acbf		4f acbd		6f abcb		9d acbl		f1 acbg	      4ffd acbh	      6ffd Always, we cannot reverse the sense of the branch; we have a word displacement. The double-byte op-codes don't hurt: we never want to modify the opcode, so we don't care how many bytes are between the opcode and the operand. 4b.	JXobXXX length of long, long, byte. Vax opcodes are:	(Hex) aoblss		f2 aobleq		f3 sobgeq		f4 sobgtr		f5 Always, we cannot reverse the sense of the branch; we have a byte displacement. The only time we need to modify the opcode is for class 2 instructions. After relax() we may complement the lowest order bit of such instruction to reverse sense of branch. For class 2 instructions, we store context of "where is the opcode literal". We can change an opcode's lowest order bit without breaking anything else. We sometimes store context in the operand literal. This way we can figure out after relax() what the original addressing mode was. *//* These displacements are relative to the start address of the   displacement.  The first letter is Byte, Word.  2nd letter is   Forward, Backward.  */#define BF (1+ 127)#define BB (1+-128)#define WF (2+ 32767)#define WB (2+-32768)/* Dont need LF, LB because they always reach. [They are coded as 0.] */#define C(a,b) ENCODE_RELAX(a,b)/* This macro has no side-effects.  */#define ENCODE_RELAX(what,length) (((what) << 2) + (length))#define RELAX_STATE(s) ((s) >> 2)#define RELAX_LENGTH(s) ((s) & 3)const relax_typeS md_relax_table[] ={  {1, 1, 0, 0},			/* error sentinel   0,0	*/  {1, 1, 0, 0},			/* unused	    0,1	*/  {1, 1, 0, 0},			/* unused	    0,2	*/  {1, 1, 0, 0},			/* unused	    0,3	*/  {BF + 1, BB + 1, 2, C (1, 1)},/* B^"foo"	    1,0 */  {WF + 1, WB + 1, 3, C (1, 2)},/* W^"foo"	    1,1 */  {0, 0, 5, 0},			/* L^"foo"	    1,2 */  {1, 1, 0, 0},			/* unused	    1,3 */  {BF, BB, 1, C (2, 1)},	/* b<cond> B^"foo"  2,0 */  {WF + 2, WB + 2, 4, C (2, 2)},/* br.+? brw X	    2,1 */  {0, 0, 7, 0},			/* br.+? jmp X	    2,2 */  {1, 1, 0, 0},			/* unused	    2,3 */  {BF, BB, 1, C (3, 1)},	/* brb B^foo	    3,0 */  {WF, WB, 2, C (3, 2)},	/* brw W^foo	    3,1 */  {0, 0, 5, 0},			/* Jmp L^foo	    3,2 */  {1, 1, 0, 0},			/* unused	    3,3 */  {1, 1, 0, 0},			/* unused	    4,0 */  {WF, WB, 2, C (4, 2)},	/* acb_ ^Wfoo	    4,1 */  {0, 0, 10, 0},		/* acb_,br,jmp L^foo4,2 */  {1, 1, 0, 0},			/* unused	    4,3 */  {BF, BB, 1, C (5, 1)},	/* Xob___,,foo      5,0 */  {WF + 4, WB + 4, 6, C (5, 2)},/* Xob.+2,brb.+3,brw5,1 */  {0, 0, 9, 0},			/* Xob.+2,brb.+6,jmp5,2 */  {1, 1, 0, 0},			/* unused	    5,3 */};#undef C#undef BF#undef BB#undef WF#undef WBvoid float_cons ();const pseudo_typeS md_pseudo_table[] ={  {"dfloat", float_cons, 'd'},  {"ffloat", float_cons, 'f'},  {"gfloat", float_cons, 'g'},  {"hfloat", float_cons, 'h'},  {0},};#define STATE_PC_RELATIVE		(1)#define STATE_CONDITIONAL_BRANCH	(2)#define STATE_ALWAYS_BRANCH		(3)	/* includes BSB...  */#define STATE_COMPLEX_BRANCH	        (4)#define STATE_COMPLEX_HOP		(5)#define STATE_BYTE			(0)#define STATE_WORD			(1)#define STATE_LONG			(2)#define STATE_UNDF			(3)	/* Symbol undefined in pass1 */#define min(a, b)	((a) < (b) ? (a) : (b))int flonum_gen2vax PARAMS ((char format_letter, FLONUM_TYPE * f,			    LITTLENUM_TYPE * words));static const char *vip_begin PARAMS ((int, const char *, const char *,				      const char *));static void vip_op_defaults PARAMS ((const char *, const char *, const char *));static void vip_op PARAMS ((char *, struct vop *));static void vip PARAMS ((struct vit *, char *));voidmd_begin (){  const char *errtxt;  FLONUM_TYPE *fP;  int i;  if ((errtxt = vip_begin (1, "$", "*", "`")) != 0)    {      as_fatal (_("VIP_BEGIN error:%s"), errtxt);    }  for (i = 0, fP = float_operand;       fP < float_operand + VIT_MAX_OPERANDS;       i++, fP++)    {      fP->low = &big_operand_bits[i][0];      fP->high = &big_operand_bits[i][SIZE_OF_LARGE_NUMBER - 1];    }}voidmd_number_to_chars (con, value, nbytes)     char con[];     valueT value;     int nbytes;{  number_to_chars_littleendian (con, value, nbytes);}/* Fix up some data or instructions after we find out the value of a symbol   that they reference.  */void				/* Knows about order of bytes in address.  */md_apply_fix (fixP, value)     fixS *fixP;     long value;{  number_to_chars_littleendian (fixP->fx_where + fixP->fx_frag->fr_literal,				(valueT) value, fixP->fx_size);}longmd_chars_to_number (con, nbytes)     unsigned char con[];	/* Low order byte 1st.  */     int nbytes;		/* Number of bytes in the input.  */{  long retval;  for (retval = 0, con += nbytes - 1; nbytes--; con--)    {      retval <<= BITS_PER_CHAR;      retval |= *con;    }  return retval;}/* vax:md_assemble() emit frags for 1 instruction */voidmd_assemble (instruction_string)     char *instruction_string;	/* A string: assemble 1 instruction.  */{  /* Non-zero if operand expression's segment is not known yet.  */  int is_undefined;  int length_code;  char *p;  /* An operand. Scans all operands.  */  struct vop *operandP;  char *save_input_line_pointer;			/* What used to live after an expression.  */  char c_save;  /* 1: instruction_string bad for all passes.  */  int goofed;  /* Points to slot just after last operand.  */  struct vop *end_operandP;  /* Points to expression values for this operand.  */  expressionS *expP;  segT *segP;  /* These refer to an instruction operand expression.  */  /* Target segment of the address.	 */  segT to_seg;  valueT this_add_number;  /* Positive (minuend) symbol.  */  symbolS *this_add_symbol;  /* As a number.  */  long opcode_as_number;  /* Least significant byte 1st.  */  char *opcode_as_chars;  /* As an array of characters.  */  /* Least significant byte 1st */  char *opcode_low_byteP;  /* length (bytes) meant by vop_short.  */  int length;  /* 0, or 1 if '@' is in addressing mode.  */  int at;  /* From vop_nbytes: vax_operand_width (in bytes) */  int nbytes;  FLONUM_TYPE *floatP;  LITTLENUM_TYPE literal_float[8];  /* Big enough for any floating point literal.  */  vip (&v, instruction_string);  /*   * Now we try to find as many as_warn()s as we can. If we do any as_warn()s   * then goofed=1. Notice that we don't make any frags yet.   * Should goofed be 1, then this instruction will wedge in any pass,   * and we can safely flush it, without causing interpass symbol phase   * errors. That is, without changing label values in different passes.   */  if ((goofed = (*v.vit_error)) != 0)    {      as_warn (_("Ignoring statement due to \"%s\""), v.vit_error);    }  /*   * We need to use expression() and friends, which require us to diddle   * input_line_pointer. So we save it and restore it later.   */  save_input_line_pointer = input_line_pointer;  for (operandP = v.vit_operand,       expP = exp_of_operand,       segP = seg_of_operand,       floatP = float_operand,       end_operandP = v.vit_operand + v.vit_operands;       operandP < end_operandP;       operandP++, expP++, segP++, floatP++)    {				/* for each operand */      if (operandP->vop_error)	{	  as_warn (_("Ignoring statement because \"%s\""), operandP->vop_error);	  goofed = 1;	}      else	{	  /* Statement has no syntax goofs: let's sniff the expression.  */	  int can_be_short = 0;	/* 1 if a bignum can be reduced to a short literal.  */	  input_line_pointer = operandP->vop_expr_begin;	  c_save = operandP->vop_expr_end[1];	  operandP->vop_expr_end[1] = '\0';	  /* If to_seg == SEG_PASS1, expression() will have set need_pass_2 = 1.  */	  *segP = expression (expP);	  switch (expP->X_op)	    {	    case O_absent:	      /* for BSD4.2 compatibility, missing expression is absolute 0 */	      expP->X_op = O_constant;	      expP->X_add_number = 0;	      /* For SEG_ABSOLUTE, we shouldn't need to set X_op_symbol,		 X_add_symbol to any particular value.  But, we will program		 defensively. Since this situation occurs rarely so it costs		 us little to do, and stops Dean worrying about the origin of		 random bits in expressionS's.  */	      expP->X_add_symbol = NULL;	      expP->X_op_symbol = NULL;	      break;	    case O_symbol:	    case O_constant:	      break;	    default:	      /*	       * Major bug. We can't handle the case of a	       * SEG_OP expression in a VIT_OPCODE_SYNTHETIC	       * variable-length instruction.	       * We don't have a frag type that is smart enough to	       * relax a SEG_OP, and so we just force all	       * SEG_OPs to behave like SEG_PASS1s.	       * Clearly, if there is a demand we can invent a new or

⌨️ 快捷键说明

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