From: Richard Burgess <> Date: Thu, 26 Jan 1995 12:55:50 +0000 (+0000) Subject: autocommit for file dated 1995-01-26 12:55:50 X-Git-Url: https://pd.if.org/git/?p=mmurtl;a=commitdiff_plain;h=461eaabae89395cb322db79a4e9487fc2dbab075 autocommit for file dated 1995-01-26 12:55:50 --- diff --git a/dasm/source/dasmq.c b/dasm/source/dasmq.c new file mode 100644 index 0000000..64d12bf --- /dev/null +++ b/dasm/source/dasmq.c @@ -0,0 +1,1569 @@ +/* DASMQ.c contains procedures that are stable and are not + subject to change during debugging and development. They + have been moved out of the main module to reduce SCROLL Mania... + +*/ + +/****************************************** +* Determine if a character is alphabetic +* or underscore. These can be used for first +* or subsequent chars in an identifier. +*******************************************/ + +char is_ident(char chr) +{ + return (isalpha(chr)) || (chr == '_'); +} + + +/******************************************** + Determine if character is "skip" character. + All values from 0x20 down to CTRL-A are + skipped. +*********************************************/ + +char isskip(char chr) +{ + if ((chr > 0) && (chr <= ' ')) return(1); + else return(0); +} +/************************************** + Write a Hex byte to a file fout. +***************************************/ + +void put_hexb(U8 value, FILE *fout) +{ +S8 stack[10]; +U16 i, j; + + i = 0; j = 2; + do { + stack[i] = (value % 16) + '0'; + if (stack[i] > 0x39) + stack[i] += 7; + i++; + } + while(value /= 16); + while (i < j--) { /* zero pad front end to width */ + fputc('0', fout); + } + while(i) { + fputc(stack[--i], fout); + } +} + +/************************************** + Write a Hex number to a file fout. +***************************************/ + +void put_hexw(U16 value, FILE *fout) +{ +S8 stack[10]; +U16 i, j; + + i = 0; + j = 4; + do { + stack[i] = (value % 16) + '0'; + if (stack[i] > 0x39) + stack[i] += 7; + i++; + } + while(value /= 16); + while (i < j--) { /* zero pad front end to width */ + fputc('0', fout); + } + while(i) { + fputc(stack[--i], fout); + } +} + +/************************************** + Write a hex dword to a file fout. +***************************************/ + +void put_hexd(U32 value, FILE *fout) +{ +S8 stack[10]; +U16 i, j; + + i = 0; + j = 8; + do { + stack[i] = (value % 16) + '0'; + if (stack[i] > 0x39) + stack[i] += 7; + i++; + } + while(value /= 16); + while (i < j--) { /* zero pad front end to width */ + fputc('0', fout); + } + while(i) { + fputc(stack[--i], fout); + } +} + + +/************************************* + Acquires VALUE for Expression() +*************************************/ +int expr4(long *val) +{ +int k; + +if (Token == rOFFSET) { + fOffset = 1; + Parse(); + } + +if (Token == OPENRND) { /* Open paren */ + Parse(); + k=expr1(val); + if (Token == CLOSRND) { + Parse(); + } + else{ + line_error(1); + return(0); + } + } +else if (Token == NUMBER) { + *val = TNumber; + Parse(); /* set up for next token check */ + } +else if (Token == LSYMBOL) { + nExpSyms++; + *val = lst[TSymnum].Offs; + iExpSym = TSymnum; /* so we can trace symbol number came from */ + ExpType = 1; + Parse(); /* set up for next token check */ + } +else if (Token == SYMBOL) { + nExpSyms++; + *val = gst[TSymnum].Offs; + iExpSym = TSymnum; /* so we can trace symbol number came from */ + ExpType = 2; + Parse(); /* set up for next token check */ + } +else if (Token == UNKSYM) { + nExpSyms++; + *val = 0; /* No offset for UNKSYM */ + iExpSym =0; + ExpType = 0; /* 0 means forward ref. No Assumption. */ + + /* Save name for forward reference */ + strncpy(UString, TString, 30); + if (CBString > 30) + UCBString = 30; + else + UCBString = CBString; /* Size of Unknown label */ + UString[UCBString] = '\0'; /* Null terminate */ + + Parse(); /* set up for next token check */ + } +else if (Token == DOLLAR) { + if (fDataSeg) + *val = oNextData; + else + *val = oNextCode; + ExpType = 3; + Parse(); /* set up for next token check */ + } +else{ + line_error(2); + return(0); + } +return(1); +} + +/***************************************** + Evaluates a UNARY MINUS for Expression() +*****************************************/ +int expr3(long *val) +{ +int k; + +if (Token == MINUS) { /* Unary MINUS */ + Parse(); /* set up for next token check */ + k=expr4(val); + if (k) { + *val = -(*val); + return(1); + } + else { + line_error(3); + return(0); + } + } +else { + k = expr4(val); + return(k); + } +} + + +/************************************* + Evaluates a * and / Expression() +*************************************/ +int expr2(long *val) +{ +int k; +long val2; + +k=expr3(val); +if ((Token != STAR) && (Token != SLASH)) + return(k); +while(1) { + if (Token == STAR) { /* MULTIPLY */ + Parse(); /* set up for next token check */ + if(expr2(&val2)) + *val *= val2; + } + else if (Token == SLASH) { /* DIVIDE */ + Parse(); /* set up for next token check */ + if(expr2(&val2)) + *val /= val2; + } + else return(1); /* Expr doesn't continue but it's OK to here */ +} +} + +/************************************* + Evaluates a + and - for Expression() +*************************************/ +int expr1(long *val) +{ +int k; +long val2; + +k=expr2(val); +if ((Token != PLUS) && (Token != MINUS)) return(k); +while(1) { + if (Token == PLUS) { + Parse(); + if (Token==REGIST) return(1); /* allow for N+REG */ + if(expr2(&val2)) + *val += val2; + else return(0); + } + else if (Token == MINUS) { + Parse(); + if (Token==REGIST) return(1); /* allow for N+REG */ + if(expr2(&val2)) + *val -= val2; + else return(0); + } + else return(1); /* Expr doesn't continue but it's OK to here */ +} +} + +/******************************************* + Expression is called to evaluate a math + expression made of constants, and/or + address labels (offsets). + Uses functions expr1 - expr4 recursively + to handle parenthetical expressions + while keeping standard math operator + precedence correct. Exits with (0) if error + in expression is encountered. Exits with + 1 if value is left in TNumber. If a NON + math Token is encountered but expression + was OK to that point, it calls ReturnToken + and leaves the currenly evaluated number + as the current token. + + If a single symbol or a single "current address" + opeator ($) is used in the expression, it will + return with SYMOFF as the Token type with the + offset value in TNumber, and the symbol + in TSymnum. If the OFFSET operator is used, + it will return with the offset in TNumber + and it will be a NUMOFF. + If more than 1 symbol or the + current address operator ($) and a symbol + is used it will assume a simple numeric + value from the computation and return + NUMBER as it's token. +********************************************/ + +int Expression(void) +{ +long val; + +/* iExpSym = 0; */ +nExpSyms = 0; +fOffset = 0; + +if (expr1(&val)) { + + if (Token) /* if not EOL (EOL returns 0) */ + ReturnToken(); /* give back non-expression token */ + if (nExpSyms == 1) { + if (fOffset) + Token = NUMOFF; /* Derived from OFFSET cmd */ + else + Token = SYMOFF; /* single address operator used (Mem Type) */ + } + else + Token = NUMBER; /* Make current token a NUMBER */ + + TSymnum = iExpSym; /* We can tell where number came from */ + TNumber = val; /* Tell em what it is */ + return(1); /* Tell em they got one */ +} +else return(0); /* Tell em they got an error */ +} + +/***************************************************** + Determines if token is 32 bit general register. +*****************************************************/ +int is_r32(int id) +{ +switch (id) { + case rEAX: + case rEBX: + case rECX: + case rEDX: + case rESI: + case rEDI: + case rEBP: + case rESP: return(1); + default: return(0); + } +} + +/***************************************************** + Determines if token is 16 bit general. +*****************************************************/ +int is_r16(int id) +{ +switch (id) { + case rAX: + case rBX: + case rCX: + case rDX: + case rSI: + case rDI: + case rBP: + case rSP: return(1); + default: return(0); + } +} + +/***************************************************** + Determines if token is 8 bit general register. +*****************************************************/ +int is_r8(int id) +{ +switch (id) { + case rAL: + case rBL: + case rCL: + case rDL: + case rAH: + case rBH: + case rCH: + case rDH: return(1); + default: return(0); + } +} + +/***************************************************** + Determines if token is Segment Register. +*****************************************************/ +int is_rSEG(int id) +{ +switch (id) { + case rDS: + case rES: + case rCS: + case rFS: + case rGS: + case rSS: return(1); + default: return(0); + } +} + +/***************************************************** + Determines if token is Debug register. +*****************************************************/ +int is_rDRG(int id) +{ +switch (id) { + case rDR0: + case rDR1: + case rDR2: + case rDR3: + case rDR6: + case rDR7: return(1); + default: return(0); + } +} + +/***************************************************** + Determines if token is Control register. +*****************************************************/ +int is_rCRG(int id) +{ +return ((id == rCR0) || (id == rCR2) || (id == rCR3)); +} + +/***************************************************** + Determines if token is Test register. +*****************************************************/ +int is_rTRG(int id) +{ +return ((id == rTR6) || (id == rTR7)); +} + +/***************************************************** + Determines if operand entry in instruction (ins) is + compatible with the operand type the user gave (op). + An entry of 0 may match which means there is no + operand. +*****************************************************/ + + +int is_Comp(int ins, int op) +{ +switch (rgINS[ins][op+1]) { /* check against op type in instruction */ + case 0: + if (!rgOpType[op]) return(1); /* no operand in either matches */ + break; + case rel8: + if (rgOpType[op] == rel8) return(1); + break; + case relW: + if (rgOpType[op] == relW) return(1); + break; + case iSAD: + if (rgOpType[op] == r8) return(1); + break; + case r8: + if (rgOpType[op] == r8) return(1); + break; + case r16: + if (rgOpType[op] == r16) return(1); + break; + case r32: + if (rgOpType[op] == r32) return(1); + break; + case rREG: + if ((rgOpType[op] == r8) || + (rgOpType[op] == r16) || + (rgOpType[op] == r32)) return(1); + break; + case rRGW: + if ((rgOpType[op] == r16) || + (rgOpType[op] == r32)) return(1); + break; + case rACC: + if (((rgOpType[op] == r8) && (rgOpReg[op] == rAL)) || + ((rgOpType[op] == r16) && (rgOpReg[op] == rAX)) || + ((rgOpType[op] == r32) && (rgOpReg[op] == rEAX))) + return(1); + break; + case rSEG: + if (rgOpType[op] == rSEG) return(1); + break; + case rCRG: + if (rgOpType[op] == rCRG) return(1); + break; + case rDRG: + if (rgOpType[op] == rDRG) return(1); + break; + case rTRG: + if (rgOpType[op] == rTRG) return(1); + break; + case imm8: + if (rgOpType[op] == val8) + return(1); + + if ((rgOpType[op] == val16) && + (OpImm < 256) && + (OpImm >= 0)) + return(1); + + break; + case ims8: /* This is where a byte in an instruction + will be sign extended. We will only allow byte values + between -128 and 127 to be compatible here. This is because + they can put AND EAX, A0h and we have to assume they DON'T + want it extended into a negative 32 bit integer such as 0FFFFFFA0h. + */ + if (rgOpType[op] == val8) + return(1); + + if ((rgOpType[op] == val16) && + (OpImm < 128) && + (OpImm >= 0)) + return(1); + + break; + case imm16: + if ((rgOpType[op] == val8) || + (rgOpType[op] == val16)) return(1); + break; + case immX: + if ((rgOpType[op] == val8) || + (rgOpType[op] == val16) || + (rgOpType[op] == val32)) return(1); + break; + case rm8: + if ((rgOpType[op] == r8) || + ((rgOpType[op] == mem) && (OpSize[op] & fByte))) return(1); + break; + case rm16: + if ((rgOpType[op] == r16) || + ((rgOpType[op] == mem) && (OpSize[op] & fWord)) ) return(1); + break; + case rRM: + if ((rgOpType[op] == r8) || + (rgOpType[op] == r16) || + (rgOpType[op] == r32) || + (rgOpType[op] == mem)) return(1); + break; + case rRMW: + if (rgOpType[op] == mem) + { + if (OpSize[op] & fFWord) + return(0); + if (OpSize[op] & fByte) + return(0); + return(1); + } + if ((rgOpType[op] == r16) || + (rgOpType[op] == r32)) + return(1); + break; + case mem: + if ((rgOpType[op] == mem) && (!(OpSize[op] & fFWord))) return(1); + break; + case memF: + if ((rgOpType[op] == memF) && (OpSize[op] & fFWord)) return(1); + break; + case moff: + if ((rgOpType[op] == mem) && + (OpMType & fDisp32) && + ((OpMType & fIndx)==0) && + ((OpMType & fBase)==0)) + return(1); + break; + case immv3: + if ((rgOpType[op] == val8) && + (OpImm == 3)) return(1); + break; + case immv1: + if ((rgOpType[op] == val8) && + (OpImm == 1)) return(1); + break; + case rDX: + if ((rgOpType[op] == r16) && + (rgOpReg[op] == rDX)) return(1); + break; + case rCL: + if ((rgOpType[op] == r8) && + (rgOpReg[op] == rCL)) return(1); + break; + case rAL: + if ((rgOpType[op] == r8) && + (rgOpReg[op] == rAL)) return(1); + break; + case rAX: + if ((rgOpType[op] == r16) && + (rgOpReg[op] == rAX)) return(1); + break; + case rEAX: + if ((rgOpType[op] == r32) && + (rgOpReg[op] == rEAX)) return(1); + break; + case rCS: + case rSS: + case rDS: + case rES: + case rFS: + case rGS: + if ((rgOpType[op] == rSEG) && + (rgOpReg[op] == rgINS[ins][op+1])) return(1); + break; + default:; + } +return(0); +} + +/***************************************************** + Determines if entry in rgOpType is a register. +*****************************************************/ + +int is_Reg(int op) +{ + switch (op) { /* This should be the value from rgOpType[x] */ + case r8: + case r16: + case r32: + case rCRG: + case rDRG: + case rTRG: + return(1); + default:; + } + return(0); +} + + +/********************************************* +This displays the string and exits for a FATAL +assembler error. +**********************************************/ + +void fatal_error(S8 *pst) +{ + +++error_count; + +if (fListA | fListE) { + fprintf(lst_fh, "\r\nFATAL ERROR, line %ld - %s\r\n", lineno[level], pst); + +/* + DumpGSymbols(); + DumpLSymbols(); +*/ + fclose(lst_fh); + } + +printf("\r\nFATAL ERROR, line %ld - %s\r\n", lineno[level], pst); +printf("%d Errors\r\n%d Warnings\r\n", error_count, warn_count); + +/* close all files here and delete temps */ + fclose(cs_fh); + fclose(ds_fh); + +exit(1); +} + +/********************************************* +This displays the string and line number for +non-fatal errors. +**********************************************/ + +void line_error(int num) +{ +S8 *p; + + switch (num) { + case 1: p="Invalid expression, ')' expected"; break; + case 2: p="Invalid expression, value expected"; break; + case 3: p="Value expected after unary '-'"; break; + case 4: p="Too many digits for numeric radix"; break; + case 5: p="Invalid character in a number"; break; + case 6: p="Unterminated string"; break; + case 7: p="Unrecognized character"; break; + case 8: p="Invalid Alignment specified"; break; + case 9: p="Start command only allowed in CSEG"; break; + case 10: p="Virtual command must be first in segment"; break; + case 11: p="Invalid Virtual value"; break; + case 12: p="Starting address not found"; break; + case 13: p="Stack command not allowed in DSEG"; break; + case 14: p="Invalid command"; break; + case 15: p="Invalid Operand"; break; + case 16: p="Invalid segment register use"; break; + case 17: p="Invalid scale value 'Reg*?'"; break; + case 18: p="Scale value expected (*2,*4,*8)"; break; + case 19: p="Too many address scale values"; break; + case 20: p="Invalid register for memory operand"; break; + case 21: p="Invalid memory operand"; break; + case 22: p="Offset must be from data segment"; break; + case 23: p="Nested brackets"; break; + case 24: p="Unbalanced brackets"; break; + case 25: p="Invalid operand size attribute"; break; + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: p=""; break; + case 32: p="Unknown token in operand array"; break; + case 33: p="Too many operands or extra character"; break; + case 34: p=""; break; + case 35: p="Invalid expression or numeric value"; break; + case 36: p="Operand expected before comma"; break; + case 37: p=""; break; + case 38: p="Invalid character or reserved word in operand"; break; + case 39: p="Relative jump out of range"; break; + case 40: p="Operand size NOT specified or implied"; break; + case 41: p="Instructions not allowed in data segment"; break; + case 42: p="Instruction expected after prefix"; break; + case 43: p="Operand sizes don't match"; break; + case 44: p="Wrong operand type for instruction"; break; + case 45: p="Incorrect format for memory operand"; break; + case 46: p="Strings only valid for DB storage"; break; + case 47: p="Expected '(' after 'DUP'"; break; + case 48: p="Storage expected between commas"; break; + case 49: p="':' not expected"; break; + case 50: p="DWord storage required for OFFSET"; break; + case 51: p="Invalid storage value"; break; + case 52: + case 53: p=""; break; + case 54: p="':' expected after last label"; break; + case 55: p="Macro not allowed in lexical level 0"; break; + case 56: p="EQU or Storage expected"; break; + case 57: + case 58: + case 59: + case 60: + case 61: + case 62: p=""; break; + case 63: p="Instruction expected before register name"; break; + case 64: p="Public Symbol already defined"; break; + case 65: p="Local symbol already defined"; break; + case 66: p="Number not expected"; break; + case 67: p="New symbol must follow PUBLIC keyword"; break; + case 68: p="Label, Command, Instruction, or Storage expected"; break; + case 69: p="Inconsistant redeclaration"; break; + case 70: p=""; break; + default: + break; + } + + fprintf(lst_fh, "\r\nERROR: %d, line: %ld, %s\r\n", num, lineno[level], p); + *line_ptr = 0; /* this KILLS the rest of the line */ + Column = 0; + ++error_count; +} + +/********************************************* +This displays the string and line number for +errors dicovered AFTER we past the line. +This is for non-fatal errors. +**********************************************/ + +void prev_error(S8 *pst, S16 line) +{ + fprintf(lst_fh, "\r\nERROR, line %d - %s\r\n", line, pst); + Column = 0; + ++error_count; +} + +/********************************************************** + The parser calls this when it detects a digit leaving + the line_ptr* pointing to digit. It accepts base 2, 10 + & 16. Base 2 numbers are suffixed with a B or b, base 16 + with an h or H and base 10 with no suffix. +***********************************************************/ + +U32 get_number(void) +{ +U32 value, base; +S8 c, i; +S16 len; +S8 st[33]; + value = 0; + len = 0; + base = 10; /* default base is 10 */ + + while(isxdigit(c = *line_ptr)) { /* get all the digits */ + st[len++] = c; + line_ptr++; + } + + if ((*line_ptr== 'h') || (*line_ptr== 'H')) { /* looks like hex */ + line_ptr++; + base = 16; + } + else if ((st[len-1] == 'b') || (st[len-1] == 'B')) { + base = 2; + len--; + } + if (((base == 2) && (len > 33)) || + ((base == 10) && (len > 10)) || + ((base == 16) && (len > 9))) { + line_error(4); + return(0); + } + i = 0; + do { + c = st[i]; + if(isdigit(c)) /* convert numeric digits */ + c -= '0'; + else if(c >= 'a') /* convert lower case alphas */ + c -= ('a' - 10); + else if(c >= 'A') /* convert upper case alphas */ + c -= ('A' - 10); + else + break; + if(c >= base) { /* outside of base */ + line_error(5); + return(0); + } + value = (value * base) + c; /* include in total */ + i++; } + while(i < len); /* to length of string */ + return value; +} + +/********************************************* +This is a fast binary search for a reserved +word that is not an instructions or a register. +**********************************************/ + +S16 findrsvd(S8 *pb, S16 cb) /* pointer to and size of string */ +{ +S16 f, m, n, k; +S8 id[8]; + + if (cb>srsvd) return(0); /* can't be a reserved word */ + strncpy(id, pb, cb); /* move string local */ + id[cb] = 0; /* null terminate */ + + m = 0; + n = nreserved-1; + while (m<=n) { + k = m + (n-m) / 2; + f = strncmp(id, rgReserved[k], srsvd-1); + if (!f) return(k + nrsvd1); /* found it! */ + else if (f > 0) /* it was less */ + m = k+1; + else /* it was more */ + n = k-1; + } + return(0); +} + +/********************************************* +This is a fast binary search for an instuction. +It returns the number or 0 if not found. +**********************************************/ + +S16 findinst(S8 *pb, S16 cb) /* pointer to and size of parsed string */ +{ +S16 f, m, n, k; +S8 id[6]; + + if (cb>sinst) return(0); /* can't be an instruction */ + strncpy(id, pb, cb); /* move string local */ + id[cb] = 0; /* null terminate */ + + m = 0; + n = ninst-1; + while (m<=n) { + k = m + (n-m) / 2; + f = strncmp(id, rginst[k], sinst-1); + if (!f) return(k+1); /* found it! */ + else if (f > 0) /* id was less */ + m = k+1; + else /* idwas more */ + n = k-1; + } + return(0); +} + +/********************************************* +This is a fast binary search for a register. +It returns the number or 0 if not found. +**********************************************/ + +S16 findreg(S8 *pb, S16 cb) /* pointer to, and size of parsed string */ +{ +S16 f, m, n, k; +S8 id[3]; + + if ((cb>sregs-1) || (cb<2)) return(0); /* can't be a register */ + strncpy(id, pb, cb); /* move string local */ + id[cb] = 0; /* null pad */ + + m = 0; + n = nregs-1; + while (m<=n) { + k = m + (n-m) / 2; + f = strncmp(id, rgreg[k], sregs-1); + if (!f) return(k+nreg1); /* found it! */ + else if (f > 0) /* it was less */ + m = k+1; + else /* it was more */ + n = k-1; + } + return(0); +} + +/********************************************* +This searches the LOCAL symbol table for the name +described by pb, cb. It only compares items that +are the same length (cb == TSymsize[x]). +It returns the number or 0 if not found. +**********************************************/ + +S16 findLsymbol(S8 *pb, S16 cb) /* pointer to, and size of string */ +{ +S16 i; +S8 name[132]; + +strncpy(name, pb, cb); /* move name local */ +name[cb] = 0; /* null terminate */ + +i = iLSymNext; +while (i>1) { /* backwards through symbol table */ + i--; + /* Only compare if same size */ + if (lst[i].Size == cb) { + if (strncmp(name, lst[i].Ptr, cb) == 0) return(i); + } + } +return(0); /* not found... */ +} + + +/********************************************* +This searches the symbol table for the name +described by pb, cb. It only compares items that +are the same length (cb == TSymsize[x]). +If the include level is greater than 0 it +searches the local first, then the global. +If at level 0, it only searches the global. +It returns the number or 0 if not found. +**********************************************/ + +S16 findGsymbol(S8 *pb, S16 cb) /* pointer to, and size of string */ +{ +S16 i; +S8 name[132]; + +strncpy(name, pb, cb); /* move name local */ +name[cb] = 0; /* null terminate */ + +i = iSymNext; +while (i>1) { /* backwards through symbol table */ + i--; + /* Only compare if same size */ + if (gst[i].Size == cb) { + if (strncmp(name, gst[i].Ptr, cb) == 0) return(i); + } + } +return(0); /* not found... */ +} + +/********************************************* + DUMP SYMBOL TABLE FOR TESTING +**********************************************/ + +void DumpGSymbols(void) +{ +S16 i; +S8 name[132]; + +fprintf(lst_fh, "PUBLIC SYMBOLS: \r\n"); + +i = 1; +while (i 0) + line_error(10); + else { + if (fListA) + Column += fprintf(lst_fh, "%08lX", TNumber); + oNextData = TNumber; + DataOffset = TNumber; + } + } + else + line_error(11); + } + else { + if (fListA) + Column += fprintf(lst_fh, "VIRTUAL Segment address: "); + if (Parse() == NUMBER) { + if (oNextCode > 0) + line_error(10); + else { + if (fListA) + Column += fprintf(lst_fh, "%08lX", TNumber); + oNextCode = TNumber; + CodeOffset = TNumber; + } + } + else + line_error(11); + } + break; + case rINCLUDE: + tmpname[0] = 0; /* default to null name */ + while (isskip(*line_ptr)) line_ptr++; + i=0; + while ((*line_ptr) && (*line_ptr != ';') && (!isskip(*line_ptr))) + tmpname[i++] = *line_ptr++; + tmpname[i] = 0; /* null terminate */ + + DoInclude(tmpname); + break; + case rSEARCH: + tmpname[0] = 0; /* default to null name */ + while (isskip(*line_ptr)) line_ptr++; + i=0; + while ((*line_ptr) && (*line_ptr != ';') && (!isskip(*line_ptr))) + tmpname[i++] = *line_ptr++; + tmpname[i] = 0; /* null terminate */ + + DoSearch(tmpname); + break; + case rSTACK: + if (!fDataSeg) { + if (fListA) + Column += fprintf(lst_fh, "Stack Total: "); + if (Parse() == NUMBER) { + StackTotal += TNumber; + if (fListA) + Column += fprintf(lst_fh, "%08lX", StackTotal); + } + else + line_error(35); /* Invalid number or expression */ + } + else + line_error(13); + break; + default: line_error(14); + return; + } + } + +/******************************************** + This adds the 3 bit code for the specified + register to the ModRM or SIB bytes which + is pointed to by *modbyte. nshift is the + number of bits to shift the register code + before ORing it with *modbyte (ModRM or SIB). +*********************************************/ + +void EncodeRegBits(S16 regnum, S8 *modbyte, S16 nshift) +{ + +switch (regnum) { + case rAL: + case rAX: /* value is 1 don't do anything */ + case rEAX: + case rES: + case rCR0: + case rDR0: + break; + case rCL: + case rCX: + case rECX: + case rCS: + case rCR1: + case rDR1: + *modbyte |= (1 << nshift); + break; + case rDL: + case rDX: + case rEDX: + case rSS: + case rCR2: + case rDR2: + *modbyte |= (2 << nshift); + break; + case rBL: + case rBX: + case rEBX: + case rDS: + case rCR3: + case rDR3: + *modbyte |= (3 << nshift); + break; + case rAH: + case rSP: + case rESP: + *modbyte |= (4 << nshift); + break; + case rCH: + case rBP: + case rEBP: + case rFS: + *modbyte |= (5 << nshift); + break; + case rDH: + case rSI: + case rESI: + case rGS: + case rTR6: + case rDR6: + *modbyte |= (6 << nshift); + break; + case rBH: + case rDI: + case rEDI: + case rTR7: + case rDR7: + *modbyte |= (7 << nshift); + break; + default:; /* if it's not one of these we do nothing */ +} +} + +/******************************************** + Add Macro to LOCAL symbol table. + The last symbol added to the symbol + table is the label for this macro. + +*********************************************/ +void AddMacro(void) +{ +S16 i, j; +S8 mac[100]; + +mac[0] = 0; + +if (iMacNext >= MACBUFMAX-50) + fatal_error("Macro buffer overflow..."); +if (iMacNext >= MACSMAX) + fatal_error("Macro table overflow..."); + +i = 0; j = 0; +while(isskip(*line_ptr)) line_ptr++; /* skip while space */ + +/* Read the macro including white space upto EOL or comment. + j keeps track of the last NON-space character so we don't + store unneeded spaces at the end of the macro. +*/ + +while ((*line_ptr) && (*line_ptr != SEMI)) { + mac[i++] = *line_ptr++; + if (mac[i-1] > 0x20) j = i; /* j will be length */ +} + +strncpy(pMacNext, mac, j); + +/* These are all "iLSymNext-1" because the Macro label has + already been added to the symbol table when AddMacro + is called. +*/ + +lst[iLSymNext-1].Type = 0; /* cancel previous type */ +lst[iLSymNext-1].Type |= MACRO; /* initialize type */ + +rgMacPtr[iMacNext] = pMacNext; /* store mac ptr in pmac array */ +lst[iLSymNext-1].Offs = iMacNext; /* store mac # in offset */ +iMacNext++; +pMacNext += j; +*pMacNext = 0; /* null terminate the macro */ +pMacNext++; + +}