📄 vax.c
字号:
/* 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 + -