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

📄 vax.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* You should use ".word ..." statements after the "case ...". */  {"", ""}			/* empty is end sentinel */};				/* synthetic_votstrs *//* *                  v i p _ b e g i n ( ) * * Call me once before you decode any lines. * I decode votstrs into a hash table at op_hash (which I create). * I return an error text: hopefully "". * If you want, I will include the 'synthetic' jXXX instructions in the * instruction table. * You must nominate metacharacters for eg DEC's "#", "@", "^". */char *vip_begin (synthetic_too, immediate, indirect, displen)     int synthetic_too;		/* TRUE means include jXXX op-codes. */     char *immediate, *indirect, *displen;{  register const struct vot *vP;	/* scan votstrs */  register char *retval;	/* error text */  char *hash_insert ();		/*  */  char *hash_new ();		/* lies */  if ((op_hash = hash_new ()))    {      retval = "";		/* OK so far */      for (vP = votstrs; *vP->vot_name && !*retval; vP++)	{	  retval = hash_insert (op_hash, vP->vot_name, &vP->vot_detail);	}      if (synthetic_too)	{	  for (vP = synthetic_votstrs; *vP->vot_name && !*retval; vP++)	    {	      retval = hash_insert (op_hash, vP->vot_name, &vP->vot_detail);	    }	}    }  else    {      retval = "virtual memory exceeded";    }#ifndef CONST_TABLE  vip_op_defaults (immediate, indirect, displen);#endif  return (retval);}/* *                  v i p _ e n d ( ) * * Call me once after you have decoded all lines. * I do any cleaning-up needed. * * We don't have to do any cleanup ourselves: all of our operand * symbol table is static, and free()ing it is naughty. */vip_end (){}/* *                  v i p ( ) * * This converts a string into a vax instruction. * The string must be a bare single instruction in dec-vax (with BSD4 frobs) * format. * It provides some error messages: at most one fatal error message (which * stops the scan) and at most one warning message for each operand. * The vax instruction is returned in exploded form, since we have no * knowledge of how you parse (or evaluate) your expressions. * We do however strip off and decode addressing modes and operation * mnemonic. * * The exploded instruction is returned to a struct vit of your choice. * #include "vax-inst.h" to know what a struct vit is. * * This function's value is a string. If it is not "" then an internal * logic error was found: read this code to assign meaning to the string. * No argument string should generate such an error string: * it means a bug in our code, not in the user's text. * * You MUST have called vip_begin() once and vip_end() never before using * this function. */char *				/* "" or bug string */vip (vitP, instring)     struct vit *vitP;		/* We build an exploded instruction here. */     char *instring;		/* Text of a vax instruction: we modify. */{  register struct vot_wot *vwP;	/* How to bit-encode this opcode. */  register char *p;		/* 1/skip whitespace.2/scan vot_how */  register char *q;		/*  */  register char *bug;		/* "" or program logic error */  register unsigned char count;	/* counts number of operands seen */  register struct vop *operandp;/* scan operands in struct vit */  register char *alloperr;	/* error over all operands */  register char c;		/* Remember char, (we clobber it */  /* with '\0' temporarily). */  register vax_opcodeT oc;	/* Op-code of this instruction. */  struct vot_wot *hash_find ();  char *vip_op ();  bug = "";  if (*instring == ' ')    ++instring;			/* Skip leading whitespace. */  for (p = instring; *p && *p != ' '; p++)    ;				/* MUST end in end-of-string or exactly 1 space. */  /* Scanned up to end of operation-code. */  /* Operation-code is ended with whitespace. */  if (p - instring == 0)    {      vitP->vit_error = "No operator";      count = 0;      bzero (vitP->vit_opcode, sizeof (vitP->vit_opcode));    }  else    {      c = *p;      *p = '\0';      /*       * Here with instring pointing to what better be an op-name, and p       * pointing to character just past that.       * We trust instring points to an op-name, with no whitespace.       */      vwP = hash_find (op_hash, instring);      *p = c;			/* Restore char after op-code. */      if (vwP == 0)	{	  vitP->vit_error = "Unknown operator";	  count = 0;	  bzero (vitP->vit_opcode, sizeof (vitP->vit_opcode));	}      else	{	  /*	   * We found a match! So lets pick up as many operands as the	   * instruction wants, and even gripe if there are too many.	   * We expect comma to seperate each operand.	   * We let instring track the text, while p tracks a part of the	   * struct vot.	   */	  /*	   * The lines below know about 2-byte opcodes starting FD,FE or FF.	   * They also understand synthetic opcodes. Note:	   * we return 32 bits of opcode, including bucky bits, BUT	   * an opcode length is either 8 or 16 bits for vit_opcode_nbytes.	   */	  oc = vwP->vot_code;	/* The op-code. */	  vitP->vit_opcode_nbytes = (oc & 0xFF) >= 0xFD ? 2 : 1;	  md_number_to_chars (vitP->vit_opcode, oc, 4);	  count = 0;		/* no operands seen yet */	  instring = p;		/* point just past operation code */	  alloperr = "";	  for (p = vwP->vot_how, operandp = vitP->vit_operand;	       !*alloperr && !*bug && *p;	       operandp++, p += 2	    )	    {	      /*	       * Here to parse one operand. Leave instring pointing just	       * past any one ',' that marks the end of this operand.	       */	      if (!p[1])		bug = "p";	/* ODD(!!) number of bytes in vot_how?? */	      else if (*instring)		{		  for (q = instring; (c = *q) && c != ','; q++)		    ;		  /*		   * Q points to ',' or '\0' that ends argument. C is that		   * character.		   */		  *q = 0;		  operandp->vop_width = p[1];		  operandp->vop_nbytes = vax_operand_width_size[p[1]];		  operandp->vop_access = p[0];		  bug = vip_op (instring, operandp);		  *q = c;	/* Restore input text. */		  if (*(operandp->vop_error))		    alloperr = "Bad operand";		  instring = q + (c ? 1 : 0);	/* next operand (if any) */		  count++;	/*  won another argument, may have an operr */		}	      else		alloperr = "Not enough operands";	    }	  if (!*alloperr)	    {	      if (*instring == ' ')		instring++;	/* Skip whitespace. */	      if (*instring)		alloperr = "Too many operands";	    }	  vitP->vit_error = alloperr;	}    }  vitP->vit_operands = count;  return (bug);}#ifdef test/* * Test program for above. */struct vit myvit;		/* build an exploded vax instruction here */char answer[100];		/* human types a line of vax assembler here */char *mybug;			/* "" or an internal logic diagnostic */int mycount;			/* number of operands */struct vop *myvop;		/* scan operands from myvit */int mysynth;			/* TRUE means want synthetic opcodes. */char my_immediate[200];char my_indirect[200];char my_displen[200];char *vip ();main (){  char *p;  char *vip_begin ();  printf ("0 means no synthetic instructions.   ");  printf ("Value for vip_begin?  ");  gets (answer);  sscanf (answer, "%d", &mysynth);  printf ("Synthetic opcodes %s be included.\n", mysynth ? "will" : "will not");  printf ("enter immediate symbols eg enter #   ");  gets (my_immediate);  printf ("enter indirect symbols  eg enter @   ");  gets (my_indirect);  printf ("enter displen symbols   eg enter ^   ");  gets (my_displen);  if (*(p = vip_begin (mysynth, my_immediate, my_indirect, my_displen)))    {      error ("vip_begin=%s", p);    }  printf ("An empty input line will quit you from the vax instruction parser\n");  for (;;)    {      printf ("vax instruction: ");      fflush (stdout);      gets (answer);      if (!*answer)	{	  break;		/* out of for each input text loop */	}      mybug = vip (&myvit, answer);      if (*mybug)	{	  printf ("BUG:\"%s\"\n", mybug);	}      if (*myvit.vit_error)	{	  printf ("ERR:\"%s\"\n", myvit.vit_error);	}      printf ("opcode=");      for (mycount = myvit.vit_opcode_nbytes, p = myvit.vit_opcode;	   mycount;	   mycount--, p++	)	{	  printf ("%02x ", *p & 0xFF);	}      printf ("   operand count=%d.\n", mycount = myvit.vit_operands);      for (myvop = myvit.vit_operand; mycount; mycount--, myvop++)	{	  printf ("mode=%xx reg=%xx ndx=%xx len='%c'=%c%c%d. expr=\"",		  myvop->vop_mode, myvop->vop_reg, myvop->vop_ndx,		  myvop->vop_short, myvop->vop_access, myvop->vop_width,		  myvop->vop_nbytes);	  for (p = myvop->vop_expr_begin; p <= myvop->vop_expr_end; p++)	    {	      putchar (*p);	    }	  printf ("\"\n");	  if (*myvop->vop_error)	    {	      printf ("  err:\"%s\"\n", myvop->vop_error);	    }	  if (*myvop->vop_warn)	    {	      printf ("  wrn:\"%s\"\n", myvop->vop_warn);	    }	}    }  vip_end ();  exit ();}#endif /* #ifdef test *//* end of vax_ins_parse.c */ /* JF this used to be a separate file also *//* vax_reg_parse.c - convert a VAX register name to a number *//* Copyright (C) 1987 Free Software Foundation, Inc. A part of GNU. *//* *          v a x _ r e g _ p a r s e ( ) * * Take 3 char.s, the last of which may be `\0` (non-existent) * and return the VAX register number that they represent. * * Return -1 if they don't form a register name. Good names return * a number from 0:15 inclusive. * * Case is not important in a name. * * Register names understood are: * *	R0 *	R1 *	R2 *	R3 *	R4 *	R5 *	R6 * 	R7 *	R8 *	R9 *	R10 *	R11 *	R12	AP *	R13	FP *	R14	SP *	R15	PC * */#include <ctype.h>#define AP (12)#define FP (13)#define SP (14)#define PC (15)int				/* return -1 or 0:15 */vax_reg_parse (c1, c2, c3)	/* 3 chars of register name */     char c1, c2, c3;		/* c3 == 0 if 2-character reg name */{  register int retval;		/* return -1:15 */  retval = -1;  if (isupper (c1))    c1 = tolower (c1);  if (isupper (c2))    c2 = tolower (c2);  if (isdigit (c2) && c1 == 'r')    {      retval = c2 - '0';      if (isdigit (c3))	{	  retval = retval * 10 + c3 - '0';	  retval = (retval > 15) ? -1 : retval;	  /* clamp the register value to 1 hex digit */	}      else if (c3)	retval = -1;		/* c3 must be '\0' or a digit */    }  else if (c3)			/* There are no three letter regs */    retval = -1;  else if (c2 == 'p')    {      switch (c1)	{	case 's':	  retval = SP;	  break;	case 'f':	  retval = FP;	  break;	case 'a':	  retval = AP;	  break;	default:	  retval = -1;	}    }  else if (c1 == 'p' && c2 == 'c')    retval = PC;  else    retval = -1;  return (retval);}/* end: vax_reg_parse.c */ /* JF this was another separate prog *//* vip_op.c - parse 1 VAX instr's operand.(C)1986 Free Software Foundation. *//* JF #include <ctype.h> *//* #include "vax_inst.h" *//* *               v i p _ o p ( ) * * Parse a vax operand in DEC assembler notation. * For speed, expect a string of whitespace to be reduced to a single ' '. * This is the case for GNU AS, and is easy for other DEC-compatible * assemblers. * * Knowledge about DEC VAX assembler operand notation lives here. * This doesn't even know what a register name is, except it believes * all register names are 2 or 3 characters, and lets vax_reg_parse() say * what number each name represents. * It does, however, know that PC, SP etc are special registers so it can * detect addressing modes that are silly for those registers. * * Where possible, it delivers 1 fatal or 1 warning message if the operand * is suspect. Exactly what we test for is still evolving. *//* *		   	B u g s * *	Arg block. * * There were a number of 'mismatched argument type' bugs to vip_op. * The most general solution is to typedef each (of many) arguments. * We used instead a typedef'd argument block. This is less modular * than using seperate return pointers for each result, but runs faster * on most engines, and seems to keep programmers happy. It will have * to be done properly if we ever want to use vip_op as a general-purpose * module (it was designed to be). * *	G^ * * Doesn't support DEC "G^" format operands. These always take 5 bytes * to express, and code as modes 8F or 9F. Reason: "G^" deprives you of * optimising to (say) a "B^" if you are lucky in the way you link. * When someone builds a linker smart enough to convert "G^" to "B^", "W^" * when

⌨️ 快捷键说明

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