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

📄 vax.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* vax.c - vax-specific -   Copyright (C) 1987 Free Software Foundation, Inc.This file is part of GAS, the GNU Assembler.GAS is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GAS; see the file COPYING.  If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *//* JF I moved almost all the vax specific stuff into this one file 'cuz RMS   seems to think its a good idea.  I hope I managed to get all the VAX-isms */#include "as.h"#include "read.h"#include "flonum.h"#include "vax-inst.h"#include "md.h"#include "obstack.h"		/* For FRAG_APPEND_1_CHAR macro in "frags.h" */#include "frags.h"#include "struc-symbol.h"#include "expr.h"#include "symbols.h"/* This is the number to put at the beginning of the a.out file */long omagic = OMAGIC;/* 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[] = "#";/* 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. */static expressionS		/* Hold details of an operand expression */ exp_of_operand[VIT_MAX_OPERANDS];static struct vit v;				/* A vax instruction after decoding. */LITTLENUM_TYPE big_operand_bits[VIT_MAX_OPERANDS][SIZE_OF_LARGE_NUMBER]; /* Hold details of big operands. */FLONUM_TYPE float_operand[VIT_MAX_OPERANDS]; /* Above is made to point into */ /* big_operand_bits by md_begin(). *//* * 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, long2a.	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		bbssi		e6		bbcci		e7	Always, you complement 0th bit to reverse condition.	Always, 1-byte opcde, longword-address, byte-address, 1-byte-displacement2c.	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 instructionto 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 outafter 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))const relax_typeSmd_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 */};#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))voidmd_begin (){  char *vip_begin ();  char *errtxt;  FLONUM_TYPE *fP;  int i;  if (*(errtxt = vip_begin (TRUE, "$", "*", "`")))    {      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_end (){  vip_end ();}void				/* Knows about order of bytes in address. */md_number_to_chars (con, value, nbytes)     char con[];		/* Return 'nbytes' of chars here. */     long int value;		/* The value of the bits. */     int nbytes;		/* Number of bytes in the output. */{  int n;  long v;  n = nbytes;  v = value;  while (nbytes--)    {      *con++ = value;		/* Lint wants & MASK_CHAR. */      value >>= BITS_PER_CHAR;    }  /* XXX line number probably botched for this warning message. */  if (value != 0 && value != -1)    as_warn ("Displacement (%ld) long for instruction field length (%d).", v, n);}void				/* Knows about order of bytes in address. */md_number_to_imm (con, value, nbytes)     char con[];		/* Return 'nbytes' of chars here. */     long int value;		/* The value of the bits. */     int nbytes;		/* Number of bytes in the output. */{  int n;  long v;  n = nbytes;  v = value;  while (nbytes--)    {      *con++ = value;		/* Lint wants & MASK_CHAR. */      value >>= BITS_PER_CHAR;    }  /* XXX line number probably botched for this warning message. */  if (value != 0 && value != -1)    as_warn ("Displacement (%ld) too long for instruction field length (%d).", v, n);}void				/* Knows about order of bytes in address. */md_number_to_disp (con, value, nbytes)     char con[];		/* Return 'nbytes' of chars here. */     long int value;		/* The value of the bits. */     int nbytes;		/* Number of bytes in the output. */{  abort ();  while (nbytes--)    {      *con++ = value;		/* Lint wants & MASK_CHAR. */      value >>= BITS_PER_CHAR;    }  /* XXX line number probably botched for this warning message. */  if (value != 0 && value != -1)    as_warn ("Displacement too long for instruction field length.");}void				/* Knows about order of bytes in address. */md_number_to_field (con, value, nbytes)     char con[];		/* Return 'nbytes' of chars here. */     long int value;		/* The value of the bits. */     int nbytes;		/* Number of bytes in the output. */{  abort ();  while (nbytes--)    {      *con++ = value;		/* Lint wants & MASK_CHAR. */      value >>= BITS_PER_CHAR;    }  /* XXX line number probably botched for this warning message. */  if (value != 0 && value != -1)    as_warn ("Displacement too long for instruction field length.");}long int			/* Knows about the byte order in a word. */md_chars_to_number (con, nbytes)     unsigned char con[];	/* Low order byte 1st. */     int nbytes;		/* Number of bytes in the input. */{  long int 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. */{  char *p;  register struct vop *operandP;/* An operand. Scans all operands. */  char *save_input_line_pointer;  char c_save;			/* What used to live after an expression. */  struct frag *fragP;		/* Fragment of code we just made. */  register int goofed;		/* TRUE: instruction_string bad for all passes. */  register struct vop *end_operandP;	/* -> slot just after last operand */  /* Limit of the for (each operand). */  register expressionS *expP;	/* -> expression values for this operand */  /* These refer to an instruction operand expression. */  segT to_seg;			/* Target segment of the address.	 */  register valueT this_add_number;  register struct symbol *this_add_symbol;	/* +ve (minuend) symbol. */  register struct symbol *this_subtract_symbol;	/* -ve(subtrahend) symbol. */  long int opcode_as_number;	/* As a number. */  char *opcode_as_chars;	/* Least significant byte 1st. */  /* As an array of characters. */  char *opcode_low_byteP;	/* Least significant byte 1st */  struct details *detP;		/* The details of an ADxxx frag. */

⌨️ 快捷键说明

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