/* * DEFM */ int op_dm(void) { register int i; register char *p; if (!gencode) return(0); i = 0; p = operand; if (pass == 1) if (*label) put_label(); if (*p != STRSEP) { asmerr(E_MISHYP); return(0); } p++; while (*p != STRSEP) { if (*p == '\n' || *p == '\0') { asmerr(E_MISHYP); break; } ops[i++] = *p++; if (i >= OPCARRAY) fatal(F_INTERN, "Op-Code buffer overflow"); } return(i); }
/* * generates branch opcodes * * opcode : opcode of the branch (for instance 0x8f for BR7) * str : operand string */ static void generate_branch(unsigned char opcode, char *str) { unsigned long target_adr; long disp; programlabel(); /* get target address */ if (parse_value(str, &target_adr)) { /* unresolved target address, reserve space */ emit_opcode2(0, 0); return; } /* calculate displacement */ if (isPCKnown()) { disp = target_adr - getPC() - 1; if (disp > 127 || disp < -128) { char buf[64]; sprintf(buf, "%d", (int)disp); asmerr(ERROR_BRANCH_OUT_OF_RANGE, false, buf); } } else { /* unknown pc, will be (hopefully) resolved in future passes */ disp = 0; } emit_opcode2(opcode, disp & 255); }
/* * Pass 1: * - process one line of source * * Output: 1 line processed * 0 EOF */ int p1_line(void) { register char *p; register int i; register struct opc *op; if ((p = fgets(line, MAXLINE, srcfp)) == NULL) return(0); c_line++; p = get_label(label, p); p = get_opcode(opcode, p); p = get_arg(operand, p); if (strcmp(opcode, ENDFILE) == 0) return(0); if (*opcode) { if ((op = search_op(opcode)) != NULL) { i = (*op->op_fun)(op->op_c1, op->op_c2); if (gencode) pc += i; } else asmerr(E_ILLOPC); } else if (*label) put_label(); return(1); }
void v_macro(char *str, MNEMONIC *dummy) { STRLIST *base; int defined = 0; STRLIST **slp, *sl; MACRO *mac; /* slp, mac: might be used uninitialised */ MNEMONIC *mne; unsigned int i; char buf[MAXLINE]; int skipit = !(Ifstack->xtrue && Ifstack->acctrue); strlower(str); if (skipit) { defined = 1; } else { defined = (findmne(str) != NULL); if (F_listfile && ListMode) outlistfile(""); } if (!defined) { base = NULL; slp = &base; mac = (MACRO *)permalloc(sizeof(MACRO)); i = hash1(str); mac->next = (MACRO *)MHash[i]; mac->vect = v_execmac; mac->name = strcpy(permalloc(strlen(str)+1), str); mac->flags = MF_MACRO; MHash[i] = (MNEMONIC *)mac; } while (fgets(buf, MAXLINE, pIncfile->fi)) { const char *comment; if (Xdebug) printf("%08lx %s\n", (unsigned long) pIncfile, buf); ++pIncfile->lineno; comment = cleanup(buf, true); mne = parse(buf); if (Av[1][0]) { if (mne && mne->flags & MF_ENDM) { if (!defined) mac->strlist = base; return; } } if (!skipit && F_listfile && ListMode) outlistfile(comment); if (!defined) { sl = (STRLIST *)permalloc(STRLISTSIZE+1+strlen(buf)); strcpy(sl->buf, buf); *slp = sl; slp = &sl->next; } } asmerr( ERROR_PREMATURE_EOF, true, NULL ); }
/* * check value for range -128 < value < 128 * Output: value if in range, otherwise 0 and error message */ int chk_v2(int i) { if (i >= -127 && i <= 127) return(i); else { asmerr(E_VALOUT); return(0); } }
/* * check value for range -256 < value < 256 * Output: value if in range, otherwise 0 and error message */ int chk_v1(int i) { if (i >= -255 && i <= 255) return(i); else { asmerr(E_VALOUT); return(0); } }
/* * add label to symbol table, error if symbol already exists */ void put_label(void) { struct sym *get_sym(char *); if (get_sym(label) == NULL) { if (put_sym(label, pc)) fatal(F_OUTMEM, "symbols"); } else asmerr(E_MULSYM); }
/* * used to print error messages. * mnename and opstring are copied into a single error message, * which is passed to asmerr. * * err : error code (ERROR_xxx constant, passed to asmerr) * mnename : name of the mnemonic * opstring : operand string * abort : false = don't abort assembly * true = abort assembly */ static void f8err(int err, const char *mnename, const char *opstring, bool bAbort) { char *buf; buf = ckmalloc(strlen(mnename) + strlen(opstring) + 64); strcpy(buf, mnename); strcat(buf, " "); strcat(buf, opstring); asmerr(err, bAbort, buf); free(buf); }
/* * Pass 1: * - process one source file * * Input: name of source file */ void p1_file(char *fn) { c_line = 0; srcfn = fn; if ((srcfp = fopen(fn, READA)) == NULL) fatal(F_FOPEN, fn); while (p1_line()) ; fclose(srcfp); if (iflevel) asmerr(E_MISEIF); }
/* * EQU */ int op_equ(void) { if (!gencode) return(0); if (pass == 1) { /* Pass 1 */ if (get_sym(label) == NULL) { sd_val = eval(operand); if (put_sym(label, sd_val)) fatal(F_OUTMEM, "symbols"); } else asmerr(E_MULSYM); } else { /* Pass 2 */ sd_flag = 1; sd_val = eval(operand); } return(0); }
/* * attempts to parse a scratchpad register name. * register numbers are parsed as expressions. * if an expression is invalid, asmerr is called * and the assembly aborted. * * accepts the following input: * * - numbers 0..14 (as expressions, numbers 12-14 map to S, I and D) * - J (alias for register 9) * - HU (alias for register 10) * - HL (alias for register 11) * - S and (IS) * - I and (IS)+ * - D and (IS)- * * str : string to parse the scratchpad register from * reg : parsed scratchpad register is stored here. * this is the value which will become the lower * nibble of the opcodes. * * result : zero = ok or syntax error * nonzero = unresolved expression */ static int parse_scratchpad_register(char *str, unsigned char *reg) { unsigned long regnum; /* parse special cases where ISAR is used as index */ if (!strcasecmp("s", str) || !strcasecmp("(is)", str)) { *reg = 0x0c; return 0; } if (!strcasecmp("i", str) || !strcasecmp("(is)+", str)) { *reg = 0x0d; return 0; } if (!strcasecmp("d", str) || !strcasecmp("(is)-", str)) { *reg = 0x0e; return 0; } /* parse aliases for scratchpad registers */ if (!strcasecmp("j", str)) { *reg = 0x09; return 0; } if (!strcasecmp("hu", str)) { *reg = 0x0a; return 0; } if (!strcasecmp("hl", str)) { *reg = 0x0b; return 0; } /* parse register number */ if (parse_value(str, ®num)) { return 1; /* unresolved expr */ } else { if (regnum > 14) { asmerr(ERROR_VALUE_MUST_BE_LT_F, true, str); } *reg = regnum; return 0; } }
/* * DEFB */ int op_db(void) { register int i; register char *p; register char *s; if (!gencode) return(0); i = 0; p = operand; if (pass == 1) if (*label) put_label(); while (*p) { if (*p == STRSEP) { p++; while (*p != STRSEP) { if (*p == '\n' || *p == '\0') { asmerr(E_MISHYP); goto hyp_error; } ops[i++] = *p++; if (i >= OPCARRAY) fatal(F_INTERN, "Op-Code buffer overflow"); } p++; } else { s = tmp; while (*p != ',' && *p != '\0') *s++ = *p++; *s = '\0'; ops[i++] = eval(tmp); if (i >= OPCARRAY) fatal(F_INTERN, "Op-Code buffer overflow"); } if (*p == ',') p++; } hyp_error: return(i); }
/* * attempts to parse a 32 bit unsigned value from a string. * * str : string to parse the value from * value : parsed value is stored here * * result : zero = ok or syntax error * nonzero = unresolved expression */ static int parse_value(char *str, unsigned long *value) { SYMBOL *sym; int result = 0; *value = 0; sym = eval(str, 0); if (NULL != sym->next || AM_BYTEADR != sym->addrmode) { asmerr(ERROR_SYNTAX_ERROR, true, str); } else if (sym->flags & SYM_UNKNOWN) { ++Redo; Redo_why |= REASON_MNEMONIC_NOT_RESOLVED; result = 1; } else { *value = sym->value; } FreeSymbolList(sym); return result; }
void v_processor(char *str, MNE *dummy) { static int called; if (called) return; called = 1; if (strcmp(str,"6502") == 0) { addhashtable(Mne6502); MsbOrder = 0; /* lsb,msb */ Processor = 6502; } if (strcmp(str,"6803") == 0) { addhashtable(Mne6803); MsbOrder = 1; /* msb,lsb */ Processor = 6803; } if (strcmp(str,"HD6303") == 0 || strcmp(str, "hd6303") == 0) { addhashtable(Mne6803); addhashtable(MneHD6303); MsbOrder = 1; /* msb,lsb */ Processor = 6303; } if (strcmp(str,"68705") == 0) { addhashtable(Mne68705); MsbOrder = 1; /* msb,lsb */ Processor = 68705; } if (strcmp(str,"68HC11") == 0 || strcmp(str, "68hc11") == 0) { addhashtable(Mne68HC11); MsbOrder = 1; /* msb,lsb */ Processor = 6811; } if (!Processor) asmerr(20,1); }
/* * ORG */ int op_org(void) { register int i; if (!gencode) return(0); i = eval(operand); if (i < pc) { asmerr(E_MEMOVR); return(0); } if (pass == 1) { /* PASS 1 */ if (!prg_flag) { prg_adr = i; prg_flag++; } } else { /* PASS 2 */ if (++prg_flag > 2) obj_fill(i - pc); sd_flag = 2; } pc = i; return(0); }
int asmerr(int err, bool bAbort, const char *sText ) { const char *str; INCFILE *pincfile; /* file pointer we print error messages to */ FILE *error_file = NULL; if ( err >= MAX_ERROR || err < 0 ) { return asmerr( ERROR_BADERROR, true, "Bad error ERROR!" ); } else { if (sErrorDef[err].bFatal) bStopAtEnd = true; for ( pincfile = pIncfile; pincfile->flags & INF_MACRO; pincfile=pincfile->next); str = sErrorDef[err].sDescription; /* New error format selection for 2.20.11 since some people *don't* use MS products. For historical reasons we currently send errors to stdout when they should really go to stderr, but we'll switch eventually I hope... [phf] */ /* determine the file pointer to use */ error_file = (F_listfile != NULL) ? FI_listfile : stdout; /* print first part of message, different formats offered */ switch (F_errorformat) { case ERRORFORMAT_WOE: /* Error format for MS VisualStudio and relatives: "file (line): error: string" */ fprintf(error_file, "%s (%lu): error: ", pincfile->name, pincfile->lineno); break; case ERRORFORMAT_DILLON: /* Matthew Dillon's original format, except that we don't distinguish writing to the terminal from writing to the list file for now. Matt's 2.16 uses these: "*line %4ld %-10s %s\n" (list file) "line %4ld %-10s %s\n" (terminal) */ fprintf(error_file, "line %7ld %-10s ", pincfile->lineno, pincfile->name); break; case ERRORFORMAT_GNU: /* GNU format error messages, from their coding standards. */ fprintf(error_file, "%s:%lu: error: ", pincfile->name, pincfile->lineno); break; default: /* TODO: really panic here? [phf] */ panic("Invalid error format, internal error!"); break; } /* print second part of message, always the same for now */ fprintf(error_file, str, sText ? sText : ""); fprintf(error_file, "\n"); if ( bAbort ) { fprintf(error_file, "Aborting assembly\n"); exit(EXIT_FAILURE); } } return err; }
static int MainShadow(int ac, char **av, bool *pbTableSort ) { int nError = ERROR_NONE; bool bDoAllPasses = false; int nMaxPasses = 10; char buf[MAXLINE]; int i; MNEMONIC *mne; int oldredo = -1; unsigned long oldwhy = 0; int oldeval = 0; addhashtable(Ops); pass = 1; if (ac < 2) { fail: puts(dasm_id); puts("Copyright (c) 1988-2008 by various authors (see file AUTHORS)."); puts("License GPLv2+: GNU GPL version 2 or later (see file COPYING)."); puts("DASM is free software: you are free to change and redistribute it."); puts("There is ABSOLUTELY NO WARRANTY, to the extent permitted by law."); puts(""); puts("Usage: dasm sourcefile [options]"); puts(""); puts("-f# output format 1-3 (default 1)"); puts("-oname output file name (else a.out)"); puts("-lname list file name (else none generated)"); puts("-Lname list file, containing all passes"); puts("-sname symbol dump file name (else none generated)"); puts("-v# verboseness 0-4 (default 0)"); puts("-d debug mode (for developers)"); puts("-Dsymbol define symbol, set to 0"); puts("-Dsymbol=expression define symbol, set to expression"); puts("-Msymbol=expression define symbol using EQM (same as -D)"); puts("-Idir search directory for INCLUDE and INCBIN"); puts("-p# maximum number of passes"); puts("-P# maximum number of passes, with fewer checks"); puts("-T# symbol table sorting (default 0 = alphabetical, 1 = address/value)"); puts("-E# error format (default 0 = MS, 1 = Dillon, 2 = GNU)"); puts(""); puts("Report bugs to [email protected] please!"); return ERROR_COMMAND_LINE; } for (i = 2; i < ac; ++i) { if ( ( av[i][0] == '-' ) || ( av[i][0] == '/' ) ) { char *str = av[i]+2; switch(av[i][1]) { /* TODO: need to improve option parsing and errors for it */ case 'E': F_errorformat = atoi(str); if (F_errorformat < ERRORFORMAT_DEFAULT || F_errorformat >= ERRORFORMAT_MAX ) { panic("Invalid error format for -E, must be 0, 1, 2"); } break; case 'T': F_sortmode = atoi(str); if (F_sortmode < SORTMODE_DEFAULT || F_sortmode >= SORTMODE_MAX ) { panic("Invalid sorting mode for -T option, must be 0 or 1"); } /* TODO: refactor into regular configuration [phf] */ *pbTableSort = (F_sortmode != SORTMODE_DEFAULT); break; case 'd': Xdebug = atoi(str) != 0; printf( "Debug trace %s\n", Xdebug ? "ON" : "OFF" ); break; case 'M': case 'D': while (*str && *str != '=') ++str; if (*str == '=') { *str = 0; ++str; } else { str = "0"; } Av[0] = av[i]+2; if (av[i][1] == 'M') v_eqm(str, NULL); else v_set(str, NULL); break; case 'f': /* F_format */ F_format = atoi(str); if (F_format < FORMAT_DEFAULT || F_format >= FORMAT_MAX ) panic("Illegal format specification"); break; case 'o': /* F_outfile */ F_outfile = str; nofile: if (*str == 0) panic("-o Switch requires file name."); break; case 'L': F_ListAllPasses = 1; /* fall through to 'l' */ case 'l': /* F_listfile */ F_listfile = str; goto nofile; case 'P': /* F_Passes */ bDoAllPasses = true; /* fall through to 'p' */ case 'p': /* F_passes */ nMaxPasses = atoi(str); break; case 's': /* F_symfile */ F_symfile = str; goto nofile; case 'v': /* F_verbose */ F_verbose = atoi(str); break; case 'I': v_incdir(str, NULL); break; default: goto fail; } continue; } goto fail; } /* INITIAL SEGMENT */ { SEGMENT *seg = (SEGMENT *)permalloc(sizeof(SEGMENT)); seg->name = strcpy(permalloc(sizeof(ISEGNAME)), ISEGNAME); seg->flags= seg->rflags = seg->initflags = seg->initrflags = SF_UNKNOWN; Csegment = Seglist = seg; } /* TOP LEVEL IF */ { IFSTACK *ifs = (IFSTACK *)zmalloc(sizeof(IFSTACK)); ifs->file = NULL; ifs->flags = IFF_BASE; ifs->acctrue = 1; ifs->xtrue = 1; Ifstack = ifs; } nextpass: if ( F_verbose ) { puts(""); printf("START OF PASS: %d\n", pass); } Localindex = Lastlocalindex = 0; Localdollarindex = Lastlocaldollarindex = 0; /*_fmode = 0x8000;*/ FI_temp = fopen(F_outfile, "wb"); /*_fmode = 0;*/ Fisclear = 1; CheckSum = 0; if (FI_temp == NULL) { printf("Warning: Unable to [re]open '%s'\n", F_outfile); return ERROR_FILE_ERROR; } if (F_listfile) { FI_listfile = fopen(F_listfile, F_ListAllPasses && (pass > 1)? "a" : "w"); if (FI_listfile == NULL) { printf("Warning: Unable to [re]open '%s'\n", F_listfile); return ERROR_FILE_ERROR; } } pushinclude(av[1]); while ( pIncfile ) { for (;;) { const char *comment; if ( pIncfile->flags & INF_MACRO) { if ( pIncfile->strlist == NULL) { Av[0] = ""; v_mexit(NULL, NULL); continue; } strcpy(buf, pIncfile->strlist->buf); pIncfile->strlist = pIncfile->strlist->next; } else { if (fgets(buf, MAXLINE, pIncfile->fi) == NULL) break; } if (Xdebug) printf("%08lx %s\n", (unsigned long) pIncfile, buf); comment = cleanup(buf, false); ++pIncfile->lineno; mne = parse(buf); if (Av[1][0]) { if (mne) { if ((mne->flags & MF_IF) || (Ifstack->xtrue && Ifstack->acctrue)) (*mne->vect)(Av[2], mne); } else { if (Ifstack->xtrue && Ifstack->acctrue) asmerr( ERROR_UNKNOWN_MNEMONIC, false, Av[1] ); } } else { if (Ifstack->xtrue && Ifstack->acctrue) programlabel(); } if (F_listfile && ListMode) outlistfile(comment); } while (Reploop && Reploop->file == pIncfile) rmnode((void **)&Reploop, sizeof(REPLOOP)); while (Ifstack->file == pIncfile) rmnode((void **)&Ifstack, sizeof(IFSTACK)); fclose( pIncfile->fi ); free( pIncfile->name ); --Inclevel; rmnode((void **)&pIncfile, sizeof(INCFILE)); if ( pIncfile ) { /* if (F_verbose > 1) printf("back to: %s\n", Incfile->name); */ if (F_listfile) fprintf(FI_listfile, "------- FILE %s\n", pIncfile->name); } } if ( F_verbose >= 1 ) ShowSegments(); if ( F_verbose >= 3 ) { if ( !Redo || ( F_verbose == 4 ) ) ShowSymbols( stdout, *pbTableSort ); ShowUnresolvedSymbols(); } closegenerate(); fclose(FI_temp); if (FI_listfile) fclose(FI_listfile); if (Redo) { if ( !bDoAllPasses ) if (Redo == oldredo && Redo_why == oldwhy && Redo_eval == oldeval) { ShowUnresolvedSymbols(); return ERROR_NOT_RESOLVABLE; } oldredo = Redo; oldwhy = Redo_why; oldeval = Redo_eval; Redo = 0; Redo_why = 0; Redo_eval = 0; Redo_if <<= 1; ++pass; if ( bStopAtEnd ) { printf("Unrecoverable error(s) in pass, aborting assembly!\n"); } else if ( pass > nMaxPasses ) { char sBuffer[64]; sprintf( sBuffer, "%d", pass ); return asmerr( ERROR_TOO_MANY_PASSES, false, sBuffer ); } else { clearrefs(); clearsegs(); goto nextpass; } } return nError; }
static const char *cleanup(char *buf, bool bDisable) { char *str; STRLIST *strlist; int arg, add; const char *comment = ""; for (str = buf; *str; ++str) { switch(*str) { case ';': comment = (char *)str + 1; /* FALL THROUGH */ case '\r': case '\n': goto br2; case TAB: *str = ' '; break; case '\'': ++str; if (*str == TAB) *str = ' '; if (*str == '\n' || *str == 0) { str[0] = ' '; str[1] = 0; } if (str[0] == ' ') str[0] = '\x80'; break; case '\"': ++str; while (*str && *str != '\"') { if (*str == ' ') *str = '\x80'; ++str; } if (*str != '\"') { asmerr( ERROR_SYNTAX_ERROR, false, buf ); --str; } break; case '{': if ( bDisable ) break; if (Xdebug) printf("macro tail: '%s'\n", str); arg = atoi(str+1); for (add = 0; *str && *str != '}'; ++str) --add; if (*str != '}') { puts("end brace required"); --str; break; } --add; ++str; if (Xdebug) printf("add/str: %d '%s'\n", add, str); for (strlist = pIncfile->args; arg && strlist;) { --arg; strlist = strlist->next; } if (strlist) { add += strlen(strlist->buf); if (Xdebug) printf("strlist: '%s' %zu\n", strlist->buf, strlen(strlist->buf)); if (str + add + strlen(str) + 1 > buf + MAXLINE) { if (Xdebug) printf("str %8ld buf %8ld (add/strlen(str)): %d %ld\n", (unsigned long)str, (unsigned long)buf, add, (long)strlen(str)); panic("failure1"); } memmove(str + add, str, strlen(str)+1); str += add; if (str - strlen(strlist->buf) < buf) panic("failure2"); memmove(str - strlen(strlist->buf), strlist->buf, strlen(strlist->buf)); str -= strlen(strlist->buf); if (str < buf || str >= buf + MAXLINE) panic("failure 3"); --str; /* for loop increments string */ } else { asmerr( ERROR_NOT_ENOUGH_ARGUMENTS_PASSED_TO_MACRO, false, NULL ); goto br2; } break; } } br2: while(str != buf && *(str-1) == ' ') --str; *str = 0; return comment; }
void v_processor(char *str, MNEMONIC *dummy) { static bool bCalled = false; unsigned long PreviousProcessor = Processor; Processor = 0; if (strcmp(str,"6502") == 0) { if ( !bCalled ) addhashtable(Mne6502); MsbOrder = 0; /* lsb,msb */ Processor = 6502; } if (strcmp(str,"6803") == 0) { if ( !bCalled ) addhashtable(Mne6803); MsbOrder = 1; /* msb,lsb */ Processor = 6803; } if (strcmp(str,"HD6303") == 0 || strcmp(str, "hd6303") == 0) { if ( !bCalled ) { addhashtable(Mne6803); addhashtable(MneHD6303); } MsbOrder = 1; /* msb,lsb */ Processor = 6303; } if (strcmp(str,"68705") == 0) { if ( !bCalled ) addhashtable(Mne68705); MsbOrder = 1; /* msb,lsb */ Processor = 68705; } if (strcmp(str,"68HC11") == 0 || strcmp(str, "68hc11") == 0) { if ( !bCalled ) addhashtable(Mne68HC11); MsbOrder = 1; /* msb,lsb */ Processor = 6811; } if (strcmp(str,"F8") == 0 || strcmp(str, "f8") == 0) { if ( !bCalled ) addhashtable(MneF8); MsbOrder = 1; Processor = 0xf8; } bCalled = true; if ( !Processor ) { asmerr( ERROR_PROCESSOR_NOT_SUPPORTED, true, str ); } if ( PreviousProcessor && Processor != PreviousProcessor ) { asmerr( ERROR_ONLY_ONE_PROCESSOR_SUPPORTED, true, str ); } }
void v_mnemonic(char *str, MNEMONIC *mne) { int addrmode; SYMBOL *sym; unsigned int opcode; short opidx; SYMBOL *symbase; int opsize; Csegment->flags |= SF_REF; programlabel(); symbase = eval(str, 1); if ( bTrace ) printf("PC: %04lx MNEMONIC: %s addrmode: %d ", Csegment->org, mne->name, symbase->addrmode); for (sym = symbase; sym; sym = sym->next) { if (sym->flags & SYM_UNKNOWN) { ++Redo; Redo_why |= REASON_MNEMONIC_NOT_RESOLVED; } } sym = symbase; if (mne->flags & MF_IMOD) { if (sym->next) { sym->addrmode = AM_BITMOD; if ((mne->flags & MF_REL) && sym->next) sym->addrmode = AM_BITBRAMOD; } } addrmode = sym->addrmode; if ((sym->flags & SYM_UNKNOWN) || sym->value >= 0x100) opsize = 2; else opsize = (sym->value) ? 1 : 0; while (badcode(mne,addrmode) && Cvt[addrmode]) addrmode = Cvt[addrmode]; if ( bTrace ) printf("mnemask: %08lx adrmode: %d Cvt[am]: %d\n", mne->okmask, addrmode, Cvt[addrmode]); if (badcode(mne,addrmode)) { char sBuffer[128]; sprintf( sBuffer, "%s %s", mne->name, str ); asmerr( ERROR_ILLEGAL_ADDRESSING_MODE, false, sBuffer ); FreeSymbolList(symbase); return; } if (Mnext >= 0 && Mnext < NUMOC) /* Force */ { addrmode = Mnext; if (badcode(mne,addrmode)) { asmerr( ERROR_ILLEGAL_FORCED_ADDRESSING_MODE, false, mne->name ); FreeSymbolList(symbase); return; } } if ( bTrace ) printf("final addrmode = %d\n", addrmode); while (opsize > Opsize[addrmode]) { if (Cvt[addrmode] == 0 || badcode(mne,Cvt[addrmode])) { char sBuffer[128]; if (sym->flags & SYM_UNKNOWN) break; sprintf( sBuffer, "%s %s", mne->name, str ); asmerr( ERROR_ADDRESS_MUST_BE_LT_100, false, sBuffer ); break; } addrmode = Cvt[addrmode]; } opcode = mne->opcode[addrmode]; opidx = 1 + (opcode > 0xFF); if (opidx == 2) { Gen[0] = opcode >> 8; Gen[1] = opcode; }
/* * recursive expression parser * * Input: pointer to argument rest string * * Output: computed value */ int eval(char *s) { register char *p; register int val; char word[MAXLINE]; struct sym *sp; val = 0; while (*s) { p = word; if (*s == '(') { s++; while (*s != ')') { if (*s == '\0') { asmerr(E_MISPAR); goto eval_break; } *p++ = *s++; } *p = '\0'; s++; val = eval(word); continue; } if (*s == STRSEP) { s++; while (*s != STRSEP) { if (*s == '\n' || *s == '\0') { asmerr(E_MISHYP); goto hyp_error; } *p++ = *s++; } s++; hyp_error: *p = '\0'; val = strval(word); continue; } if (isari(*s)) *p++ = *s++; else while (!isspace(*s) && !isari(*s) && (*s != '\0')) *p++ = *s++; *p = '\0'; switch (get_type(word)) { case OPESYM: /* symbol */ if (strcmp(word, "$") == 0) { val = pc; break; } if (strlen(word) > SYMSIZE) word[SYMSIZE] = '\0'; if ((sp = get_sym(word)) != NULL) val = sp->sym_val; else asmerr(E_UNDSYM); break; case OPEDEC: /* decimal number */ val = atoi(word); break; case OPEHEX: /* hexadecimal number */ val = axtoi(word); break; case OPEBIN: /* binary number */ val = abtoi(word); break; case OPEOCT: /* octal number */ val = aotoi(word); break; case OPESUB: /* arithmetical - */ val -= eval(s); goto eval_break; case OPEADD: /* arithmetical + */ val += eval(s); goto eval_break; case OPEMUL: /* arithmetical * */ val *= eval(s); goto eval_break; case OPEDIV: /* arithmetical / */ val /= eval(s); goto eval_break; case OPEMOD: /* arithmetical modulo */ val %= eval(s); goto eval_break; case OPESHL: /* logical shift left */ val <<= eval(s); goto eval_break; case OPESHR: /* logical shift right */ val >>= eval(s); goto eval_break; case OPELOR: /* logical OR */ val |= eval(s); goto eval_break; case OPELAN: /* logical AND */ val &= eval(s); goto eval_break; case OPEXOR: /* logical XOR */ val ^= eval(s); goto eval_break; case OPECOM: /* logical complement */ val = ~(eval(s)); goto eval_break; } } eval_break: return(val); }
void v_mnemonic(char *str, MNE *mne) { register int addrmode; register SYMBOL *sym; register uword opcode; short opidx; SYMBOL *symbase; int opsize; Csegment->flags |= SF_REF; programlabel(); symbase = eval(str, 1); if (Xtrace) printf("PC: %04lx MNE: %s addrmode: %d ", Csegment->org, mne->name, symbase->addrmode); for (sym = symbase; sym; sym = sym->next) { if (sym->flags & SYM_UNKNOWN) { ++Redo; Redo_why |= 1 << 0; } } sym = symbase; if (mne->flags & MF_IMOD) { if (sym->next) { sym->addrmode = AM_BITMOD; if ((mne->flags & MF_REL) && sym->next) sym->addrmode = AM_BITBRAMOD; } } addrmode = sym->addrmode; if ((sym->flags & SYM_UNKNOWN) || sym->value >= 0x100) opsize = 2; else opsize = (sym->value) ? 1 : 0; while (badcode(mne,addrmode) && Cvt[addrmode]) addrmode = Cvt[addrmode]; if (Xtrace) printf("mnemask: %08lx adrmode: %d Cvt[am]: %d\n", mne->okmask, addrmode, Cvt[addrmode]); if (badcode(mne,addrmode)) { asmerr(5,0); freesymbollist(symbase); return; } if (Mnext >= 0 && Mnext < NUMOC) { /* Force */ addrmode = Mnext; if (badcode(mne,addrmode)) { asmerr(19,0); freesymbollist(symbase); return; } } if (Xtrace) printf("final addrmode = %d\n", addrmode); while (opsize > Opsize[addrmode]) { if (Cvt[addrmode] == 0 || badcode(mne,Cvt[addrmode])) { if (sym->flags & SYM_UNKNOWN) break; asmerr(14,0); break; } addrmode = Cvt[addrmode]; } opcode = mne->opcode[addrmode]; opidx = 1 + (opcode > 0xFF); if (opidx == 2) { Gen[0] = opcode >> 8; Gen[1] = opcode; } else {