/***************************************************************************** * Change Log * Date | Change *-----------+----------------------------------------------------------------- * 26-Nov-85 | [1.151] Created * 4-Dec-85 | [1.105] Recognize compare instr as having valid literal * | second operand * 6-Dec-85 | [1.148] Allow extra space for NUL in label * 28-Dec-85 | [1.174] Allow implicit d-char on no-operand instructions (WM) * 24-Nov-91 | [1.177] memory.h => automem.h * 24-Nov-91 | [1.177] converted to C6.0 * 24-Nov-91 | [1.177] mach.h => machmem.h * 25-Nov-91 | [1.185] literal now accepts ', +, -, @ as leading lit * | indicators * 26-Nov-91 | [1.198] all calls on expr to evaluate literals specifies * | 'false' for the report_undefined * 26-Nov-91 | [1.204] better checking for multiply-defined labels * | use startloc.h * 26-Nov-91 | [1.212] added blankop predicate, allow propagation of * | DC/DCW opcodes * 27-Nov-91 | [1.213] allow for indented labels *****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static boolean compare; /* Assembler state */ extern int dot; /* current location counter */ extern int star; /* Value of '*' */ extern int sdot; extern unsigned maxdot; extern unsigned litoffset; extern FILE * reader; extern char line[81]; extern boolean debug; extern boolean debug_sym; extern boolean saw_end; static int lastop = 0; /**************************************************************************** * isliteral * Inputs: * char * str: String which might be literal operand * Result: boolean * true if literal operand, false if not ****************************************************************************/ boolean isliteral(char * str) { switch(str[0]) { /* try leading char */ case '@': case '\'': case '+': case '-': case '&': return true; default: if(strrchr(str,'#') || strrchr(str,'=')) return true; /* literaloid */ } /* try leading char */ return false; } /**************************************************************************** * pass1 * Effect: * Runs pass 1 of the assembler ****************************************************************************/ void pass1() { star = sdot = dot = STARTLOC; maxdot = 0; litoffset = 0; lastop = 0; while(true) { /* pass1 loop */ int opindex; if(saw_end) break; readline(); if(feof(reader)) break; if(line[0]=='*') continue; /* comment card */ sdot = dot; if(blankop() && lastop != 0) { /* propagate it */ opindex = lastop + 1; } /* propagate it */ else { /* new op */ opindex = opcode_1(); lastop = (optable[opindex].propagate ? opindex : 0); } /* new op */ (*optable[opindex].processor)(opindex,1); check_sym("end of processing line in pass 1"); maxdot = max(dot,maxdot); fix_da(); } /* pass1 loop */ fprintf(stderr,"End of Pass 1\n"); } /**************************************************************************** * getlabel * Result: getlabelval * * Pointer to label structure (name is NUL terminated) * NULL if label string is empty * Effects: * Allocates a heap string for the label, in result->name. * If label is indented result->left is true ****************************************************************************/ getlabelval * getlabel() { static getlabelval v; char * p; char * symname; char * sym = &line[LABEL_START]; int len; char * t = sym; boolean left = false; if(*sym == ' ' && *(sym+1) != ' ') { /* indented label */ t = sym+1; left = true; } /* indented label */ p = strchr(t,' '); /* get end of symbol */ if(p==NULL) return NULL; /* unexplained failure */ len = p - t; if(len == 0) return NULL; /* No label */ if(len > 6) { /* indented label */ /* We get here if we had an indented label that ran into the opcode field. The label is 6 chars long or we would not have had a len > 6: _FOOBARMLCWA FOO ^ ^ */ len = 6; } /* indented label */ symname = malloc(len+1); /* +1 plus one for NUL */ strncpy(symname,t,len); /* count includes terminal NUL */ symname[len] = '\0'; if(debug_sym) printf("Symbol @0x%x length %d = \"%-*.*s\"\n", symname, len, len, len, symname); v.name = symname; v.left = left; return &v; } /**************************************************************************** * label_1 * Result: ste * * Symbol table entry of label * NULL if no label, or error occurred * Effect: * Enters the label in the symbol table ****************************************************************************/ ste * label_1() { getlabelval * v; ste * sy = NULL; v = getlabel(); if(v != NULL) { /* enter label */ if(v->left == ' ') { /* right-indented */ error(err_label,"Indented label not permitted here"); return NULL; } /* right-indented */ #if 1 sy = lookup(v->name); if(sy != NULL) { /* multiply defined */ sy->muldef = true; free(v->name); /* free string from getlabel */ } /* multiply defined */ else { /* unique */ sy = enter(v->name,dot); } /* unique */ #else sy = enter(v->name,dot); #endif } /* enter label */ return sy; } /**************************************************************************** * legal_op * Inputs: * int i: Table index * Result: boolean * true if legal, false if not ****************************************************************************/ boolean legal_op(int i) { int opp; for(opp=0;opp0;i++) { /* check op */ found = legal_op(i); if(found) break; } /* check op */ if(!found) { /* error */ char msg[80]; sprintf(msg,"Illegal operation '%.5s'",&line[OP_START]); error(err_opcode,msg); i = 0; } /* error */ if(strcmp(optable[i].mnemonic,"C ") == 0) compare = true; return i; } /**************************************************************************** * operands_1 * Inputs: * int opindex: Index into operator table * Effect: * Processes the operands field ****************************************************************************/ void operands_1(int opindex) { int i; int noperands; unsigned val; noperands = scan_operands(); if(debug) { /* print debug stuff */ printf("%d operands:\n",noperands); for(i=0;i