From: Peter Johnson Date: Thu, 11 Oct 2001 05:34:50 +0000 (-0000) Subject: Fix LOTS of little nits. Primary changes: X-Git-Tag: v0.1.0~260 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=193392dcb60eff248108dbd56a4d361dbe58ee47;p=yasm Fix LOTS of little nits. Primary changes: - New intnum module to replace using just unsigned long (for >32 bit values). Read values using BitVector instead of strtoul(). - Brought both floatnum and intnum into expr (still need to integrate calc for floatnum). - Add traversal function to ternary tree (for use by symrec_foreach). - Change floatnum output interface from single/double/extended to byte size. - Try to make floatnum/intnum interfaces very similar. Still needs work. - Add/fix *_print functions, including interating ones for sections/bytecodes. - Fix handling of $ and $$. Both now are properly parsed and bytecode'd. - Print out all sections and symbol table in main() in preparation for work on "cleanup" functionality between parser and optimizer stages (really part of the parser stage). svn path=/trunk/yasm/; revision=270 --- diff --git a/configure.ac b/configure.ac index 20c6bd52..f8a1803b 100644 --- a/configure.ac +++ b/configure.ac @@ -117,7 +117,7 @@ AC_TYPE_SIZE_T AC_FUNC_VPRINTF AC_CHECK_FUNCS(memcpy toascii abort) AC_CHECK_FUNCS(strcasecmp stricmp strcmpi, break) -AC_REPLACE_FUNCS(strsep strtoul) +AC_REPLACE_FUNCS(strsep) AC_CHECK_HEADERS(limits.h sys/queue.h sys/cdefs.h) diff --git a/configure.in b/configure.in index 20c6bd52..f8a1803b 100644 --- a/configure.in +++ b/configure.in @@ -117,7 +117,7 @@ AC_TYPE_SIZE_T AC_FUNC_VPRINTF AC_CHECK_FUNCS(memcpy toascii abort) AC_CHECK_FUNCS(strcasecmp stricmp strcmpi, break) -AC_REPLACE_FUNCS(strsep strtoul) +AC_REPLACE_FUNCS(strsep) AC_CHECK_HEADERS(limits.h sys/queue.h sys/cdefs.h) diff --git a/frontends/yasm/yasm.c b/frontends/yasm/yasm.c index 8e1e6b1f..6cad2ab2 100644 --- a/frontends/yasm/yasm.c +++ b/frontends/yasm/yasm.c @@ -45,6 +45,7 @@ #include "globals.h" #include "options.h" #include "errwarn.h" +#include "symrec.h" #include "bytecode.h" #include "section.h" @@ -99,6 +100,8 @@ char help_tail[] = "\n" int main(int argc, char *argv[]) { + sectionhead *sections; + if (parse_cmdline(argc, argv, options, countof(options, opt_option))) return EXIT_FAILURE; @@ -123,11 +126,15 @@ main(int argc, char *argv[]) /* Get initial BITS setting from object format */ mode_bits = dbg_objfmt.default_mode_bits; - nasm_parser.do_parse(&nasm_parser, &dbg_objfmt, in); + sections = nasm_parser.do_parse(&nasm_parser, &dbg_objfmt, in); if (OutputAllErrorWarning() > 0) return EXIT_FAILURE; + sections_print(sections); + printf("\n***Symbol Table***\n"); + symrec_foreach((int (*) (symrec *))symrec_print); + if (in_filename) free(in_filename); return EXIT_SUCCESS; diff --git a/libyasm/bytecode.c b/libyasm/bytecode.c index 96620a1d..24bf0b20 100644 --- a/libyasm/bytecode.c +++ b/libyasm/bytecode.c @@ -37,6 +37,7 @@ #include "globals.h" #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" @@ -73,11 +74,10 @@ struct immval { struct dataval { STAILQ_ENTRY(dataval) link; - enum { DV_EMPTY, DV_EXPR, DV_FLOAT, DV_STRING } type; + enum { DV_EMPTY, DV_EXPR, DV_STRING } type; union { expr *expn; - floatnum *flt; char *str_val; } data; }; @@ -229,7 +229,7 @@ immval_new_int(unsigned long int_val) { immval *im = xmalloc(sizeof(immval)); - im->val = expr_new_ident(ExprInt(int_val)); + im->val = expr_new_ident(ExprInt(intnum_new_int(int_val))); if ((int_val & 0xFF) == int_val) im->len = 1; @@ -249,7 +249,7 @@ immval_new_expr(expr *expr_ptr) immval *im = xmalloc(sizeof(immval)); im->val = expr_ptr; - + im->len = 0; im->isneg = 0; return im; @@ -486,46 +486,7 @@ bytecode_new_jmprel(targetval *target, bytecode * bytecode_new_data(datavalhead *datahead, unsigned long size) { - bytecode *bc; - dataval *cur; - - /* First check to see if all the data elements are valid for the size - * being set. - * Validity table: - * db (1) -> expr, string - * dw (2) -> expr, string - * dd (4) -> expr, float, string - * dq (8) -> expr, float, string - * dt (10) -> float, string - * - * Once we calculate expr we'll have to validate it against the size - * and warn/error appropriately (symbol constants versus labels: - * constants (equ's) should always be legal, but labels should raise - * warnings when used in db or dq context at the minimum). - */ - STAILQ_FOREACH(cur, datahead, link) { - switch (cur->type) { - case DV_EMPTY: - case DV_STRING: - /* string is valid in every size */ - break; - case DV_FLOAT: - if (size == 1) - Error(_("floating-point constant encountered in `%s'"), - "DB"); - else if (size == 2) - Error(_("floating-point constant encountered in `%s'"), - "DW"); - break; - case DV_EXPR: - if (size == 10) - Error(_("non-floating-point value encountered in `%s'"), - "DT"); - break; - } - } - - bc = bytecode_new_common(); + bytecode *bc = bytecode_new_common(); bc->type = BC_DATA; @@ -570,14 +531,14 @@ bytecode_print(bytecode *bc) printf("\n Disp="); expr_print(bc->data.insn.ea->disp); printf("\n"); - printf(" Len=%u SegmentOv=%2x\n", + printf(" Len=%u SegmentOv=%02x\n", (unsigned int)bc->data.insn.ea->len, (unsigned int)bc->data.insn.ea->segment); - printf(" ModRM=%2x ValidRM=%u NeedRM=%u\n", + printf(" ModRM=%02x ValidRM=%u NeedRM=%u\n", (unsigned int)bc->data.insn.ea->modrm, (unsigned int)bc->data.insn.ea->valid_modrm, (unsigned int)bc->data.insn.ea->need_modrm); - printf(" SIB=%2x ValidSIB=%u NeedSIB=%u\n", + printf(" SIB=%02x ValidSIB=%u NeedSIB=%u\n", (unsigned int)bc->data.insn.ea->sib, (unsigned int)bc->data.insn.ea->valid_sib, (unsigned int)bc->data.insn.ea->need_sib); @@ -595,16 +556,17 @@ bytecode_print(bytecode *bc) printf(" FLen=%u, FSign=%u\n", (unsigned int)bc->data.insn.imm->f_len, (unsigned int)bc->data.insn.imm->f_sign); - printf("Opcode: %2x %2x %2x OpLen=%u\n", - (unsigned int)bc->data.insn.opcode[0], - (unsigned int)bc->data.insn.opcode[1], - (unsigned int)bc->data.insn.opcode[2], - (unsigned int)bc->data.insn.opcode_len); - printf("AddrSize=%u OperSize=%u LockRepPre=%2x\n", - (unsigned int)bc->data.insn.addrsize, - (unsigned int)bc->data.insn.opersize, - (unsigned int)bc->data.insn.lockrep_pre); } + printf("Opcode: %02x %02x %02x OpLen=%u\n", + (unsigned int)bc->data.insn.opcode[0], + (unsigned int)bc->data.insn.opcode[1], + (unsigned int)bc->data.insn.opcode[2], + (unsigned int)bc->data.insn.opcode_len); + printf("AddrSize=%u OperSize=%u LockRepPre=%02x ShiftOp=%u\n", + (unsigned int)bc->data.insn.addrsize, + (unsigned int)bc->data.insn.opersize, + (unsigned int)bc->data.insn.lockrep_pre, + (unsigned int)bc->data.insn.shift_op); break; case BC_JMPREL: printf("_Relative Jump_\n"); @@ -614,7 +576,7 @@ bytecode_print(bytecode *bc) if (!bc->data.jmprel.shortop.opcode_len == 0) printf(" None\n"); else - printf(" Opcode: %2x %2x %2x OpLen=%u\n", + printf(" Opcode: %02x %02x %02x OpLen=%u\n", (unsigned int)bc->data.jmprel.shortop.opcode[0], (unsigned int)bc->data.jmprel.shortop.opcode[1], (unsigned int)bc->data.jmprel.shortop.opcode[2], @@ -622,7 +584,7 @@ bytecode_print(bytecode *bc) if (!bc->data.jmprel.nearop.opcode_len == 0) printf(" None\n"); else - printf(" Opcode: %2x %2x %2x OpLen=%u\n", + printf(" Opcode: %02x %02x %02x OpLen=%u\n", (unsigned int)bc->data.jmprel.nearop.opcode[0], (unsigned int)bc->data.jmprel.nearop.opcode[1], (unsigned int)bc->data.jmprel.nearop.opcode[2], @@ -648,7 +610,7 @@ bytecode_print(bytecode *bc) printf("UNKNOWN!!"); break; } - printf("\nAddrSize=%u OperSize=%u LockRepPre=%2x\n", + printf("\nAddrSize=%u OperSize=%u LockRepPre=%02x\n", (unsigned int)bc->data.jmprel.addrsize, (unsigned int)bc->data.jmprel.opersize, (unsigned int)bc->data.jmprel.lockrep_pre); @@ -690,24 +652,24 @@ bytecodes_append(bytecodehead *headp, bytecode *bc) return (bytecode *)NULL; } -dataval * -dataval_new_expr(expr *expn) +void +bytecodes_print(const bytecodehead *headp) { - dataval *retval = xmalloc(sizeof(dataval)); - - retval->type = DV_EXPR; - retval->data.expn = expn; + bytecode *cur; - return retval; + STAILQ_FOREACH(cur, headp, link) { + printf("---Next Bytecode---\n"); + bytecode_print(cur); + } } dataval * -dataval_new_float(floatnum *flt) +dataval_new_expr(expr *expn) { dataval *retval = xmalloc(sizeof(dataval)); - retval->type = DV_FLOAT; - retval->data.flt = flt; + retval->type = DV_EXPR; + retval->data.expn = expn; return retval; } @@ -748,11 +710,6 @@ dataval_print(datavalhead *head) expr_print(cur->data.expn); printf("\n"); break; - case DV_FLOAT: - printf(" Float="); - floatnum_print(cur->data.flt); - printf("\n"); - break; case DV_STRING: printf(" String=%s\n", cur->data.str_val); break; diff --git a/libyasm/bytecode.h b/libyasm/bytecode.h index 32ffa963..be485e4f 100644 --- a/libyasm/bytecode.h +++ b/libyasm/bytecode.h @@ -129,6 +129,8 @@ void bytecode_print(bytecode *bc); */ bytecode *bytecodes_append(bytecodehead *headp, bytecode *bc); +void bytecodes_print(const bytecodehead *headp); + dataval *dataval_new_expr(expr *expn); dataval *dataval_new_float(floatnum *flt); dataval *dataval_new_string(char *str_val); diff --git a/libyasm/expr.c b/libyasm/expr.c index 911fe47d..252065f7 100644 --- a/libyasm/expr.c +++ b/libyasm/expr.c @@ -40,8 +40,11 @@ #define N_(String) (String) #endif +#include "bitvect.h" + #include "globals.h" #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -61,7 +64,7 @@ struct ExprItem { union { symrec *sym; expr *expn; - unsigned long int_val; + intnum *intn; floatnum *flt; } data; }; @@ -69,6 +72,8 @@ struct ExprItem { struct expr { ExprItem left, right; ExprOp op; + char *filename; + unsigned long line; }; /* allocate a new expression node, with children as defined. @@ -93,6 +98,10 @@ expr_new(ExprItem *left, ExprOp op, ExprItem *right) InternalError(__LINE__, __FILE__, _("Right side of expression must exist")); } + + ptr->filename = xstrdup(in_filename); + ptr->line = line_number; + return ptr; } @@ -116,11 +125,11 @@ ExprExpr(expr *x) } ExprItem * -ExprInt(unsigned long i) +ExprInt(intnum *i) { ExprItem *e = xmalloc(sizeof(ExprItem)); e->type = EXPR_INT; - e->data.int_val = i; + e->data.intn = i; return e; } @@ -138,7 +147,7 @@ int expr_simplify(expr *e) { int simplified = 0; - unsigned long int_val; + ExprItem tmp; /* try to simplify the left side */ if (e->left.type == EXPR_EXPR) { @@ -150,14 +159,14 @@ expr_simplify(expr *e) * pull it up into the current node */ while (e->left.type == EXPR_EXPR && e->left.data.expn->op == EXPR_IDENT) { - ExprItem tmp; - e->left.type = e->left.data.expn->right.type; memcpy(&tmp, &(e->left.data.expn->right), sizeof(ExprItem)); free(e->left.data.expn); - memcpy(&(e->left.data.int_val), &tmp, sizeof(ExprItem)); + memcpy(&e->left, &tmp, sizeof(ExprItem)); simplified = 1; } - } else if (e->left.type == EXPR_SYM) { + } +#if 0 + else if (e->left.type == EXPR_SYM) { /* try to get value of symbol */ if (symrec_get_int_value(e->left.data.sym, &int_val, 0)) { e->left.type = EXPR_INT; @@ -166,6 +175,7 @@ expr_simplify(expr *e) simplified = 1; } } +#endif /* ditto on the right */ if (e->right.type == EXPR_EXPR) { @@ -174,14 +184,14 @@ expr_simplify(expr *e) while (e->right.type == EXPR_EXPR && e->right.data.expn->op == EXPR_IDENT) { - ExprItem tmp; - e->right.type = e->right.data.expn->right.type; memcpy(&tmp, &(e->right.data.expn->right), sizeof(ExprItem)); free(e->right.data.expn); - memcpy(&(e->right.data.int_val), &tmp, sizeof(ExprItem)); + memcpy(&e->right, &tmp, sizeof(ExprItem)); simplified = 1; } - } else if (e->right.type == EXPR_SYM) { + } +#if 0 + else if (e->right.type == EXPR_SYM) { if (symrec_get_int_value(e->right.data.sym, &int_val, 0)) { e->right.type = EXPR_INT; /* don't try to free the symrec here. */ @@ -189,139 +199,45 @@ expr_simplify(expr *e) simplified = 1; } } - - if ((e->left.type == EXPR_INT || e->left.type == EXPR_NONE) && - e->right.type == EXPR_INT && e->op != EXPR_IDENT) { - switch (e->op) { - case EXPR_ADD: - e->right.data.int_val = e->left.data.int_val + - e->right.data.int_val; - break; - case EXPR_SUB: - e->right.data.int_val = e->left.data.int_val - - e->right.data.int_val; - break; - case EXPR_MUL: - e->right.data.int_val = e->left.data.int_val * - e->right.data.int_val; - break; - case EXPR_DIV: - e->right.data.int_val = e->left.data.int_val / - e->right.data.int_val; - break; - case EXPR_MOD: - e->right.data.int_val = e->left.data.int_val % - e->right.data.int_val; - break; - case EXPR_NEG: - e->right.data.int_val = -(e->right.data.int_val); - break; - case EXPR_NOT: - e->right.data.int_val = ~(e->right.data.int_val); - break; - case EXPR_OR: - e->right.data.int_val = e->left.data.int_val | - e->right.data.int_val; - break; - case EXPR_AND: - e->right.data.int_val = e->left.data.int_val & - e->right.data.int_val; - break; - case EXPR_XOR: - e->right.data.int_val = e->left.data.int_val ^ - e->right.data.int_val; - break; - case EXPR_SHL: - e->right.data.int_val = e->right.data.int_val << - e->left.data.int_val; - break; - case EXPR_SHR: - e->right.data.int_val = e->right.data.int_val >> - e->left.data.int_val; - break; - case EXPR_LOR: - e->right.data.int_val = e->left.data.int_val || - e->right.data.int_val; - break; - case EXPR_LAND: - e->right.data.int_val = e->left.data.int_val && - e->right.data.int_val; - break; - case EXPR_LNOT: - e->right.data.int_val = !e->right.data.int_val; - break; - case EXPR_EQ: - e->right.data.int_val = e->right.data.int_val == - e->left.data.int_val; - break; - case EXPR_LT: - e->right.data.int_val = e->right.data.int_val < - e->left.data.int_val; - break; - case EXPR_GT: - e->right.data.int_val = e->right.data.int_val > - e->left.data.int_val; - break; - case EXPR_LE: - e->right.data.int_val = e->right.data.int_val <= - e->left.data.int_val; - break; - case EXPR_GE: - e->right.data.int_val = e->right.data.int_val >= - e->left.data.int_val; - break; - case EXPR_NE: - e->right.data.int_val = e->right.data.int_val != - e->left.data.int_val; - break; - case EXPR_IDENT: - break; - } - e->op = EXPR_IDENT; - simplified = 1; - } +#endif /* catch simple identities like 0+x, 1*x, etc., for x not a num */ - else if (e->left.type == EXPR_INT && - ((e->left.data.int_val == 1 && e->op == EXPR_MUL) || - (e->left.data.int_val == 0 && e->op == EXPR_ADD) || - (e->left.data.int_val == -1 && e->op == EXPR_AND) || - (e->left.data.int_val == 0 && e->op == EXPR_OR))) { + if (e->left.type == EXPR_INT && + ((intnum_is_pos1(e->left.data.intn) && e->op == EXPR_MUL) || + (intnum_is_zero(e->left.data.intn) && e->op == EXPR_ADD) || + (intnum_is_neg1(e->left.data.intn) && e->op == EXPR_AND) || + (intnum_is_zero(e->left.data.intn) && e->op == EXPR_OR))) { + intnum_delete(e->left.data.intn); e->op = EXPR_IDENT; simplified = 1; } /* and the corresponding x+|-0, x*&/1 */ else if (e->right.type == EXPR_INT && - ((e->right.data.int_val == 1 && e->op == EXPR_MUL) || - (e->right.data.int_val == 1 && e->op == EXPR_DIV) || - (e->right.data.int_val == 0 && e->op == EXPR_ADD) || - (e->right.data.int_val == 0 && e->op == EXPR_SUB) || - (e->right.data.int_val == -1 && e->op == EXPR_AND) || - (e->right.data.int_val == 0 && e->op == EXPR_OR) || - (e->right.data.int_val == 0 && e->op == EXPR_SHL) || - (e->right.data.int_val == 0 && e->op == EXPR_SHR))) { + ((intnum_is_pos1(e->right.data.intn) && e->op == EXPR_MUL) || + (intnum_is_pos1(e->right.data.intn) && e->op == EXPR_DIV) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_ADD) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SUB) || + (intnum_is_neg1(e->right.data.intn) && e->op == EXPR_AND) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_OR) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SHL) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SHR))) { + intnum_delete(e->right.data.intn); e->op = EXPR_IDENT; e->right.type = e->left.type; memcpy(&e->right, &e->left, sizeof(ExprItem)); simplified = 1; + } else if ((e->left.type == EXPR_INT || e->left.type == EXPR_NONE) && + e->right.type == EXPR_INT && e->op != EXPR_IDENT) { + intnum_calc(e->left.data.intn, e->op, e->right.data.intn); + intnum_delete(e->right.data.intn); + e->right.data.intn = e->left.data.intn; + e->op = EXPR_IDENT; + simplified = 1; } return simplified; } -int -expr_get_value(expr *e, unsigned long *retval) -{ - while (!(e->op == EXPR_IDENT && e->right.type == EXPR_INT) - && expr_simplify(e)) ; - - if (e->op == EXPR_IDENT && e->right.type == EXPR_INT) { - *retval = e->right.data.int_val; - return 1; - } else - return 0; -} - void expr_print(expr *e) { @@ -336,7 +252,7 @@ expr_print(expr *e) printf(")"); break; case EXPR_INT: - printf("%lu", e->left.data.int_val); + intnum_print(e->left.data.intn); break; case EXPR_FLOAT: floatnum_print(e->left.data.flt); @@ -358,9 +274,15 @@ expr_print(expr *e) case EXPR_DIV: printf("/"); break; + case EXPR_SIGNDIV: + printf("//"); + break; case EXPR_MOD: printf("%%"); break; + case EXPR_SIGNMOD: + printf("%%%%"); + break; case EXPR_NEG: printf("-"); break; @@ -422,7 +344,7 @@ expr_print(expr *e) printf(")"); break; case EXPR_INT: - printf("%lu", e->right.data.int_val); + intnum_print(e->right.data.intn); break; case EXPR_FLOAT: floatnum_print(e->right.data.flt); diff --git a/libyasm/expr.h b/libyasm/expr.h index 25a0bb48..8adad2db 100644 --- a/libyasm/expr.h +++ b/libyasm/expr.h @@ -32,12 +32,21 @@ typedef struct symrec symrec; typedef struct floatnum floatnum; #endif +#ifndef YASM_INTNUM +#define YASM_INTNUM +typedef struct intnum intnum; +#endif + +#ifndef YASM_EXPROP +#define YASM_EXPROP typedef enum { EXPR_ADD, EXPR_SUB, EXPR_MUL, EXPR_DIV, + EXPR_SIGNDIV, EXPR_MOD, + EXPR_SIGNMOD, EXPR_NEG, EXPR_NOT, EXPR_OR, @@ -56,6 +65,7 @@ typedef enum { EXPR_NE, EXPR_IDENT /* if right is IDENT, then the entire expr is just a num */ } ExprOp; +#endif typedef struct ExprItem ExprItem; @@ -68,7 +78,7 @@ expr *expr_new(ExprItem *, ExprOp, ExprItem *); ExprItem *ExprSym(symrec *); ExprItem *ExprExpr(expr *); -ExprItem *ExprInt(unsigned long); +ExprItem *ExprInt(intnum *); ExprItem *ExprFloat(floatnum *); #define expr_new_tree(l,o,r) \ @@ -81,7 +91,4 @@ ExprItem *ExprFloat(floatnum *); int expr_simplify(expr *); void expr_print(expr *); -/* get the value if possible. return value is IF POSSIBLE, not the val */ -int expr_get_value(expr *, unsigned long *); - #endif diff --git a/libyasm/floatnum.c b/libyasm/floatnum.c index d2e143ff..30ae7414 100644 --- a/libyasm/floatnum.c +++ b/libyasm/floatnum.c @@ -498,20 +498,28 @@ floatnum_delete(floatnum *flt) free(flt); } +void +floatnum_calc(floatnum *acc, ExprOp op, floatnum *operand) +{ + if (op != EXPR_NEG) + Error(_("Unsupported floating-point arithmetic operation")); + else + acc->sign ^= 1; +} + int floatnum_get_int(unsigned long *ret_val, const floatnum *flt) { unsigned char t[4]; - if (floatnum_get_single(t, flt)) + if (floatnum_get_sized(t, flt, 4)) return 1; LOAD_LONG(*ret_val, &t[0]); return 0; } -/* Function used by single, double, and extended conversion routines to actually - * perform the conversion. +/* Function used by conversion routines to actually perform the conversion. * * ptr -> the array to return the little-endian floating point value into. * flt -> the floating point value to convert. @@ -614,14 +622,8 @@ floatnum_get_common(unsigned char *ptr, const floatnum *flt, int byte_size, * e = bias 127 exponent * s = sign bit * m = mantissa bits, bit 23 is an implied one bit. - */ -int -floatnum_get_single(unsigned char *ptr, const floatnum *flt) -{ - return floatnum_get_common(ptr, flt, 4, 23, 1, 8); -} - -/* IEEE-754 (Intel) "double precision" format: + * + * IEEE-754 (Intel) "double precision" format: * 64 bits: * bit 63 bit 51 bit 0 * | | | @@ -630,14 +632,8 @@ floatnum_get_single(unsigned char *ptr, const floatnum *flt) * e = bias 1023 exponent. * s = sign bit. * m = mantissa bits. Bit 52 is an implied one bit. - */ -int -floatnum_get_double(unsigned char *ptr, const floatnum *flt) -{ - return floatnum_get_common(ptr, flt, 8, 52, 1, 11); -} - -/* IEEE-754 (Intel) "extended precision" format: + * + * IEEE-754 (Intel) "extended precision" format: * 80 bits: * bit 79 bit 63 bit 0 * | | | @@ -648,9 +644,34 @@ floatnum_get_double(unsigned char *ptr, const floatnum *flt) * s = sign (for mantissa) */ int -floatnum_get_extended(unsigned char *ptr, const floatnum *flt) +floatnum_get_sized(unsigned char *ptr, const floatnum *flt, size_t size) { - return floatnum_get_common(ptr, flt, 10, 64, 0, 15); + switch (size) { + case 4: + return floatnum_get_common(ptr, flt, 4, 23, 1, 8); + case 8: + return floatnum_get_common(ptr, flt, 8, 52, 1, 11); + case 10: + return floatnum_get_common(ptr, flt, 10, 64, 0, 15); + default: + InternalError(__LINE__, __FILE__, + _("Invalid float conversion size")); + return 1; /* never reached, but silence GCC warning */ + } +} + +/* 1 if the size is valid, 0 if it isn't */ +int +floatnum_check_size(const floatnum *flt, size_t size) +{ + switch (size) { + case 4: + case 8: + case 10: + return 1; + default: + return 0; + } } void @@ -666,19 +687,19 @@ floatnum_print(const floatnum *flt) free(str); /* 32-bit (single precision) format */ - printf("32-bit: %d: ", floatnum_get_single(out, flt)); + printf("32-bit: %d: ", floatnum_get_sized(out, flt, 4)); for (i=0; i<4; i++) printf("%02x ", out[i]); printf("\n"); /* 64-bit (double precision) format */ - printf("64-bit: %d: ", floatnum_get_double(out, flt)); + printf("64-bit: %d: ", floatnum_get_sized(out, flt, 8)); for (i=0; i<8; i++) printf("%02x ", out[i]); printf("\n"); /* 80-bit (extended precision) format */ - printf("80-bit: %d: ", floatnum_get_extended(out, flt)); + printf("80-bit: %d: ", floatnum_get_sized(out, flt, 10)); for (i=0; i<10; i++) printf("%02x ", out[i]); printf("\n"); diff --git a/libyasm/floatnum.h b/libyasm/floatnum.h index 61292249..4963e79a 100644 --- a/libyasm/floatnum.h +++ b/libyasm/floatnum.h @@ -24,6 +24,36 @@ #ifndef YASM_FLOATNUM_H #define YASM_FLOATNUM_H +#ifndef YASM_EXPROP +#define YASM_EXPROP +typedef enum { + EXPR_ADD, + EXPR_SUB, + EXPR_MUL, + EXPR_DIV, + EXPR_SIGNDIV, + EXPR_MOD, + EXPR_SIGNMOD, + EXPR_NEG, + EXPR_NOT, + EXPR_OR, + EXPR_AND, + EXPR_XOR, + EXPR_SHL, + EXPR_SHR, + EXPR_LOR, + EXPR_LAND, + EXPR_LNOT, + EXPR_LT, + EXPR_GT, + EXPR_EQ, + EXPR_LE, + EXPR_GE, + EXPR_NE, + EXPR_IDENT /* if right is IDENT, then the entire expr is just a num */ +} ExprOp; +#endif + #ifndef YASM_FLOATNUM #define YASM_FLOATNUM typedef struct floatnum floatnum; @@ -32,7 +62,12 @@ typedef struct floatnum floatnum; floatnum *floatnum_new(const char *str); void floatnum_delete(floatnum *flt); -/* The get functions return nonzero if flt can't fit into that size format. */ +/* calculation function: acc = acc op operand */ +void floatnum_calc(floatnum *acc, ExprOp op, floatnum *operand); + +/* The get functions return nonzero if flt can't fit into that size format: + * -1 if underflow occurred, 1 if overflow occurred. + */ /* Essentially a convert to single-precision and return as 32-bit value. * The 32-bit value is a "standard" C value (eg, of unknown endian). @@ -42,9 +77,13 @@ int floatnum_get_int(unsigned long *ret_val, const floatnum *flt); /* ptr will point to the Intel-format little-endian byte string after a * successful call (eg, [0] should be the first byte output to the file). */ -int floatnum_get_single(unsigned char *ptr, const floatnum *flt); -int floatnum_get_double(unsigned char *ptr, const floatnum *flt); -int floatnum_get_extended(unsigned char *ptr, const floatnum *flt); +int floatnum_get_sized(unsigned char *ptr, const floatnum *flt, size_t size); + +/* Basic check to see if size is even valid for flt conversion (doesn't + * actually check for underflow/overflow but rather checks for size=4,8,10). + * Returns 1 if valid, 0 if not. + */ +int floatnum_check_size(const floatnum *flt, size_t size); void floatnum_print(const floatnum *flt); diff --git a/libyasm/intnum.c b/libyasm/intnum.c new file mode 100644 index 00000000..05f5303e --- /dev/null +++ b/libyasm/intnum.c @@ -0,0 +1,542 @@ +/* $IdPath$ + * Integer number functions. + * + * Copyright (C) 2001 Peter Johnson + * + * This file is part of YASM. + * + * YASM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * YASM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "util.h" + +#include +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#include +#define _(String) gettext(String) + +#include "bitvect.h" +#include "file.h" + +#include "errwarn.h" +#include "intnum.h" + +RCSID("$IdPath$"); + +#define BITVECT_ALLOC_SIZE 80 + +struct intnum { + union val { + unsigned long ul; /* integer value (for integers <=32 bits) */ + intptr bv; /* bit vector (for integers >32 bits) */ + } val; + enum { INTNUM_UL, INTNUM_BV } type; + unsigned char origsize; /* original (parsed) size, in bits */ +}; + +intnum * +intnum_new_dec(char *str) +{ + intnum *intn = xmalloc(sizeof(intnum)); + wordptr bv; + + intn->origsize = 0; /* no reliable way to figure this out */ + + bv = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + if (BitVector_from_Dec(bv, (unsigned char *)str) == ErrCode_Ovfl) + Warning(_("Numeric constant too large for internal format")); + if (Set_Max(bv) < 32) { + intn->type = INTNUM_UL; + intn->val.ul = BitVector_Chunk_Read(bv, 32, 0); + BitVector_Destroy(bv); + } else { + intn->type = INTNUM_BV; + intn->val.bv = bv; + } + + return intn; +} + +intnum * +intnum_new_bin(char *str) +{ + intnum *intn = xmalloc(sizeof(intnum)); + wordptr bv; + + intn->origsize = strlen(str); + + if(intn->origsize > BITVECT_ALLOC_SIZE) + Warning(_("Numeric constant too large for internal format")); + + bv = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + BitVector_from_Bin(bv, (unsigned char *)str); + if (Set_Max(bv) < 32) { + intn->type = INTNUM_UL; + intn->val.ul = BitVector_Chunk_Read(bv, 32, 0); + BitVector_Destroy(bv); + } else { + intn->type = INTNUM_BV; + intn->val.bv = bv; + } + + return intn; +} + +intnum * +intnum_new_oct(char *str) +{ + intnum *intn = xmalloc(sizeof(intnum)); + wordptr bv; + + intn->origsize = strlen(str)*3; + + if(intn->origsize > BITVECT_ALLOC_SIZE) + Warning(_("Numeric constant too large for internal format")); + + bv = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + BitVector_from_Oct(bv, (unsigned char *)str); + if (Set_Max(bv) < 32) { + intn->type = INTNUM_UL; + intn->val.ul = BitVector_Chunk_Read(bv, 32, 0); + BitVector_Destroy(bv); + } else { + intn->type = INTNUM_BV; + intn->val.bv = bv; + } + + return intn; +} + +intnum * +intnum_new_hex(char *str) +{ + intnum *intn = xmalloc(sizeof(intnum)); + wordptr bv; + + intn->origsize = strlen(str)*4; + + if(intn->origsize > BITVECT_ALLOC_SIZE) + Warning(_("Numeric constant too large for internal format")); + + bv = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + BitVector_from_Hex(bv, (unsigned char *)str); + if (Set_Max(bv) < 32) { + intn->type = INTNUM_UL; + intn->val.ul = BitVector_Chunk_Read(bv, 32, 0); + BitVector_Destroy(bv); + } else { + intn->type = INTNUM_BV; + intn->val.bv = bv; + } + + return intn; +} + +intnum * +intnum_new_charconst_nasm(const char *str) +{ + intnum *intn = xmalloc(sizeof(intnum)); + size_t len = strlen(str); + + if (len > 4) + Warning(_("character constant too large, ignoring trailing characters")); + + intn->val.ul = 0; + intn->type = INTNUM_UL; + intn->origsize = len*8; + + switch (len) { + case 4: + intn->val.ul |= (unsigned long)str[3]; + intn->val.ul <<= 8; + case 3: + intn->val.ul |= (unsigned long)str[2]; + intn->val.ul <<= 8; + case 2: + intn->val.ul |= (unsigned long)str[1]; + intn->val.ul <<= 8; + case 1: + intn->val.ul |= (unsigned long)str[0]; + } + + return intn; +} + +intnum * +intnum_new_int(unsigned long i) +{ + intnum *intn = xmalloc(sizeof(intnum)); + + intn->val.ul = i; + intn->type = INTNUM_UL; + intn->origsize = 0; + + return intn; +} + +void +intnum_delete(intnum *intn) +{ + if (intn->type == INTNUM_BV) + BitVector_Destroy(intn->val.bv); + free(intn); +} + +void +intnum_calc(intnum *acc, ExprOp op, intnum *operand) +{ + wordptr result = (wordptr)NULL, op1 = (wordptr)NULL, op2 = (wordptr)NULL; + wordptr spare; + boolean carry; + + /* upsize to bitvector op if one of two parameters is bitvector already. + * BitVector results must be calculated through intermediate storage. + */ + if (acc->type == INTNUM_BV || (operand && operand->type == INTNUM_BV)) { + result = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + spare = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + + if (acc->type == INTNUM_BV) + op1 = acc->val.bv; + else { + op1 = BitVector_Create(BITVECT_ALLOC_SIZE, TRUE); + BitVector_Chunk_Store(op1, 32, 0, acc->val.ul); + } + + if (operand) { + if (operand->type == INTNUM_BV) + op2 = acc->val.bv; + else { + op2 = BitVector_Create(BITVECT_ALLOC_SIZE, TRUE); + BitVector_Chunk_Store(op2, 32, 0, operand->val.ul); + } + } + } + + if (!operand && op != EXPR_NEG && op != EXPR_NOT && op != EXPR_LNOT) + InternalError(__LINE__, __FILE__, _("Operation needs an operand")); + + /* A operation does a bitvector computation if result is allocated. */ + switch (op) { + case EXPR_ADD: + if (result) + BitVector_add(result, op1, op2, &carry); + else + acc->val.ul = acc->val.ul + operand->val.ul; + break; + case EXPR_SUB: + if (result) + BitVector_sub(result, op1, op2, &carry); + else + acc->val.ul = acc->val.ul - operand->val.ul; + break; + case EXPR_MUL: + if (result) + /* TODO: Make sure result size = op1+op2 */ + BitVector_Multiply(result, op1, op2); + else + acc->val.ul = acc->val.ul * operand->val.ul; + break; + case EXPR_DIV: + if (result) { + /* TODO: make sure op1 and op2 are unsigned */ + BitVector_Divide(result, op1, op2, spare); + } else + acc->val.ul = acc->val.ul / operand->val.ul; + break; + case EXPR_SIGNDIV: + if (result) + BitVector_Divide(result, op1, op2, spare); + else + acc->val.ul = (unsigned long)((signed long)acc->val.ul / + (signed long)operand->val.ul); + break; + case EXPR_MOD: + if (result) { + /* TODO: make sure op1 and op2 are unsigned */ + BitVector_Divide(spare, op1, op2, result); + } else + acc->val.ul = acc->val.ul % operand->val.ul; + break; + case EXPR_SIGNMOD: + if (result) + BitVector_Divide(spare, op1, op2, result); + else + acc->val.ul = (unsigned long)((signed long)acc->val.ul % + (signed long)operand->val.ul); + break; + case EXPR_NEG: + if (result) + BitVector_Negate(result, op1); + else + acc->val.ul = -(acc->val.ul); + break; + case EXPR_NOT: + if (result) + Set_Complement(result, op1); + else + acc->val.ul = ~(acc->val.ul); + break; + case EXPR_OR: + if (result) + Set_Union(result, op1, op2); + else + acc->val.ul = acc->val.ul | operand->val.ul; + break; + case EXPR_AND: + if (result) + Set_Intersection(result, op1, op2); + else + acc->val.ul = acc->val.ul & operand->val.ul; + break; + case EXPR_XOR: + if (result) + Set_ExclusiveOr(result, op1, op2); + else + acc->val.ul = acc->val.ul ^ operand->val.ul; + break; + case EXPR_SHL: + if (result) { + if (operand->type == INTNUM_UL) { + BitVector_Copy(result, op1); + BitVector_Move_Left(result, operand->val.ul); + } else /* don't even bother, just zero result */ + BitVector_Empty(result); + } else + acc->val.ul = acc->val.ul << operand->val.ul; + break; + case EXPR_SHR: + if (result) { + if (operand->type == INTNUM_UL) { + BitVector_Copy(result, op1); + BitVector_Move_Right(result, operand->val.ul); + } else /* don't even bother, just zero result */ + BitVector_Empty(result); + } else + acc->val.ul = acc->val.ul >> operand->val.ul; + break; + case EXPR_LOR: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, !BitVector_is_empty(op1) || + !BitVector_is_empty(op2)); + } else + acc->val.ul = acc->val.ul || operand->val.ul; + break; + case EXPR_LAND: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, !BitVector_is_empty(op1) && + !BitVector_is_empty(op2)); + } else + acc->val.ul = acc->val.ul && operand->val.ul; + break; + case EXPR_LNOT: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, BitVector_is_empty(op1)); + } else + acc->val.ul = !acc->val.ul; + break; + case EXPR_EQ: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, BitVector_equal(op1, op2)); + } else + acc->val.ul = acc->val.ul == operand->val.ul; + break; + case EXPR_LT: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, BitVector_Lexicompare(op1, op2) < 0); + } else + acc->val.ul = acc->val.ul < operand->val.ul; + break; + case EXPR_GT: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, BitVector_Lexicompare(op1, op2) > 0); + } else + acc->val.ul = acc->val.ul > operand->val.ul; + break; + case EXPR_LE: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, BitVector_Lexicompare(op1, op2) <= 0); + } else + acc->val.ul = acc->val.ul <= operand->val.ul; + break; + case EXPR_GE: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, BitVector_Lexicompare(op1, op2) >= 0); + } else + acc->val.ul = acc->val.ul >= operand->val.ul; + break; + case EXPR_NE: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, !BitVector_equal(op1, op2)); + } else + acc->val.ul = acc->val.ul != operand->val.ul; + break; + case EXPR_IDENT: + if (result) + BitVector_Copy(result, op1); + break; + } + + /* If we were doing a bitvector computation... */ + if (result) { + BitVector_Destroy(spare); + + if (op1 && acc->type != INTNUM_BV) + BitVector_Destroy(op1); + if (op2 && operand && operand->type != INTNUM_BV) + BitVector_Destroy(op2); + + /* Try to fit the result into 32 bits if possible */ + if (Set_Max(result) < 32) { + if (acc->type == INTNUM_BV) { + BitVector_Destroy(acc->val.bv); + acc->type = INTNUM_UL; + } + acc->val.ul = BitVector_Chunk_Read(result, 32, 0); + BitVector_Destroy(result); + } else { + if (acc->type == INTNUM_BV) { + BitVector_Copy(acc->val.bv, result); + BitVector_Destroy(result); + } else { + acc->type = INTNUM_BV; + acc->val.bv = result; + } + } + } +} + +int +intnum_is_zero(intnum *intn) +{ + return ((intn->type == INTNUM_UL && intn->val.ul == 0) || + (intn->type == INTNUM_BV && BitVector_is_empty(intn->val.bv))); +} + +int +intnum_is_pos1(intnum *intn) +{ + return ((intn->type == INTNUM_UL && intn->val.ul == 1) || + (intn->type == INTNUM_BV && Set_Max(intn->val.bv) == 0)); +} + +int +intnum_is_neg1(intnum *intn) +{ + return ((intn->type == INTNUM_UL && intn->val.ul == -1) || + (intn->type == INTNUM_BV && BitVector_is_full(intn->val.bv))); +} + +void +intnum_get_int(unsigned long *ret_val, const intnum *intn) +{ + switch (intn->type) { + case INTNUM_UL: + *ret_val = intn->val.ul; + break; + case INTNUM_BV: + *ret_val = BitVector_Chunk_Read(intn->val.bv, 32, 0); + break; + } +} + +void +intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size) +{ + unsigned long ul; + unsigned char *buf; + unsigned int len; + + switch (intn->type) { + case INTNUM_UL: + ul = intn->val.ul; + while (size-- > 0) { + WRITE_BYTE(ptr, ul); + if (ul != 0) + ul >>= 8; + } + break; + case INTNUM_BV: + buf = BitVector_Block_Read(intn->val.bv, &len); + if (len < size) + InternalError(__LINE__, __FILE__, + _("Invalid size specified (too large)")); + memcpy(ptr, buf, size); + free(buf); + break; + } +} + +/* Return 1 if okay size, 0 if not */ +int +intnum_check_size(const intnum *intn, size_t size) +{ + switch (intn->type) { + case INTNUM_UL: + if (size >= 4) + return 1; + switch (size) { + case 3: + return ((intn->val.ul & 0x00FFFFFF) == intn->val.ul); + case 2: + return ((intn->val.ul & 0x0000FFFF) == intn->val.ul); + case 1: + return ((intn->val.ul & 0x000000FF) == intn->val.ul); + } + break; + case INTNUM_BV: + if (size >= 10) + return 1; + else + return (Set_Max(intn->val.bv) < size*8); + break; + } + return 0; +} + +void +intnum_print(const intnum *intn) +{ + unsigned char *s; + + switch (intn->type) { + case INTNUM_UL: + printf("0x%lx/%u", intn->val.ul, (unsigned int)intn->origsize); + break; + case INTNUM_BV: + s = BitVector_to_Hex(intn->val.bv); + printf("0x%s/%u", s, (unsigned int)intn->origsize); + free(s); + break; + } +} diff --git a/libyasm/intnum.h b/libyasm/intnum.h new file mode 100644 index 00000000..62fe9e27 --- /dev/null +++ b/libyasm/intnum.h @@ -0,0 +1,96 @@ +/* $IdPath$ + * Integer number functions header file. + * + * Copyright (C) 2001 Peter Johnson + * + * This file is part of YASM. + * + * YASM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * YASM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef YASM_INTNUM_H +#define YASM_INTNUM_H + +#ifndef YASM_EXPROP +#define YASM_EXPROP +typedef enum { + EXPR_ADD, + EXPR_SUB, + EXPR_MUL, + EXPR_DIV, + EXPR_SIGNDIV, + EXPR_MOD, + EXPR_SIGNMOD, + EXPR_NEG, + EXPR_NOT, + EXPR_OR, + EXPR_AND, + EXPR_XOR, + EXPR_SHL, + EXPR_SHR, + EXPR_LOR, + EXPR_LAND, + EXPR_LNOT, + EXPR_LT, + EXPR_GT, + EXPR_EQ, + EXPR_LE, + EXPR_GE, + EXPR_NE, + EXPR_IDENT /* if right is IDENT, then the entire expr is just a num */ +} ExprOp; +#endif + +#ifndef YASM_INTNUM +#define YASM_INTNUM +typedef struct intnum intnum; +#endif + +intnum *intnum_new_dec(char *str); +intnum *intnum_new_bin(char *str); +intnum *intnum_new_oct(char *str); +intnum *intnum_new_hex(char *str); +/* convert character constant to integer value, using NASM rules */ +intnum *intnum_new_charconst_nasm(const char *str); +intnum *intnum_new_int(unsigned long i); +void intnum_delete(intnum *intn); + +/* calculation function: acc = acc op operand */ +void intnum_calc(intnum *acc, ExprOp op, intnum *operand); + +/* simple value checks (for catching identities and the like) */ +int intnum_is_zero(intnum *acc); +int intnum_is_pos1(intnum *acc); +int intnum_is_neg1(intnum *acc); + +/* The get functions truncate intn to the size specified; they don't check + * for overflow. Use intnum_check_size() to check for overflow. + */ + +/* Return a 32-bit value in "standard" C format (eg, of unknown endian). */ +void intnum_get_int(unsigned long *ret_val, const intnum *intn); + +/* ptr will point to the Intel-format little-endian byte string after + * call (eg, [0] should be the first byte output to the file). + */ +void intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size); + +/* Check to see if intn will fit without overflow in size bytes. + * Returns 1 if it will, 0 if not. + */ +int intnum_check_size(const intnum *intn, size_t size); + +void intnum_print(const intnum *intn); + +#endif diff --git a/libyasm/section.c b/libyasm/section.c index e655a5c2..d9db4be3 100644 --- a/libyasm/section.c +++ b/libyasm/section.c @@ -124,8 +124,42 @@ sections_switch(sectionhead *headp, objfmt *of, const char *name) return s; } +void +sections_print(sectionhead *headp) +{ + section *cur; + + STAILQ_FOREACH(cur, headp, link) + section_print(cur); +} + bytecodehead * section_get_bytecodes(section *sect) { return §->bc; } + +const char * +section_get_name(const section *sect) +{ + return sect->name; +} + +void +section_print(const section *sect) +{ + printf("***SECTION %s***\n", sect->name); + printf(" type="); + switch (sect->type) { + case SECTION_GENERAL: + printf("general\n"); + break; + case SECTION_ABSOLUTE: + printf("absolute\n"); + printf("start=%lu\n", sect->data.start); + break; + } + + printf(" Bytecodes:\n"); + bytecodes_print(§->bc); +} diff --git a/libyasm/section.h b/libyasm/section.h index ff881721..93aa3de4 100644 --- a/libyasm/section.h +++ b/libyasm/section.h @@ -36,5 +36,11 @@ section *sections_initialize(sectionhead *headp, struct objfmt_s *of); section *sections_switch(sectionhead *headp, struct objfmt_s *of, const char *name); +void sections_print(sectionhead *headp); + bytecodehead *section_get_bytecodes(section *sect); + +const char *section_get_name(const section *sect); + +void section_print(const section *sect); #endif diff --git a/libyasm/symrec.c b/libyasm/symrec.c index 639d37e2..d18f352e 100644 --- a/libyasm/symrec.c +++ b/libyasm/symrec.c @@ -25,6 +25,8 @@ #include "util.h" +#include + #ifdef STDC_HEADERS # include # include @@ -36,6 +38,7 @@ #include "globals.h" #include "errwarn.h" #include "floatnum.h" +#include "expr.h" #include "symrec.h" #include "bytecode.h" @@ -48,13 +51,13 @@ typedef enum { SYM_NOSTATUS = 0, SYM_USED = 1 << 0, /* for using variables before definition */ SYM_DEFINED = 1 << 1, /* once it's been defined in the file */ - SYM_VALUED = 1 << 2 /* once its value has been determined */ + SYM_VALUED = 1 << 2, /* once its value has been determined */ + SYM_NOTINTABLE = 1 << 3 /* if it's not in sym_table (ex. '$') */ } SymStatus; typedef enum { SYM_UNKNOWN, /* for unknown type (COMMON/EXTERN) */ - SYM_CONSTANT_INT, /* for EQU defined symbols (integers) */ - SYM_CONSTANT_FLOAT, /* (floating point) */ + SYM_EQU, /* for EQU defined symbols (expressions) */ SYM_LABEL /* for labels */ } SymType; @@ -66,8 +69,7 @@ struct symrec { char *filename; /* file and line */ unsigned long line; /* symbol was first declared or used on */ union { - unsigned long int_val; /* integer constant */ - floatnum *flt; /* floating point constant */ + expr *expn; /* equ value */ struct label_s { /* bytecode immediately preceding a label */ section *sect; bytecode *bc; @@ -76,56 +78,60 @@ struct symrec { }; /* private functions */ -static symrec *symrec_get_or_new(const char *); -static symrec *symrec_define(const char *, SymType type); +static symrec *symrec_get_or_new(const char *name, int in_table); +static symrec *symrec_define(const char *name, SymType type, int in_table); /* The symbol table: a ternary tree. */ static ternary_tree sym_table = (ternary_tree)NULL; /* create a new symrec */ static symrec * -symrec_get_or_new(const char *name) +symrec_get_or_new(const char *name, int in_table) { symrec *rec, *rec2; rec = xmalloc(sizeof(symrec)); - rec2 = ternary_insert(&sym_table, name, rec, 0); + if (in_table) { + rec2 = ternary_insert(&sym_table, name, rec, 0); - if (rec2 != rec) { - free(rec); - return rec2; - } + if (rec2 != rec) { + free(rec); + return rec2; + } + rec->status = SYM_NOSTATUS; + } else + rec->status = SYM_NOTINTABLE; rec->name = xstrdup(name); rec->type = SYM_UNKNOWN; rec->filename = xstrdup(in_filename); rec->line = line_number; - rec->status = SYM_NOSTATUS; rec->visibility = SYM_LOCAL; return rec; } -/* call a function with each symrec. stop early if 0 returned */ -void -symrec_foreach(int (*func) (const char *name, symrec *rec)) +/* Call a function with each symrec. Stops early if 0 returned by func. + Returns 0 if stopped early. */ +int +symrec_foreach(int (*func) (symrec *sym)) { - /* TODO */ + return ternary_traverse(sym_table, (int (*) (void *))func); } symrec * symrec_use(const char *name) { - symrec *rec = symrec_get_or_new(name); + symrec *rec = symrec_get_or_new(name, 1); rec->status |= SYM_USED; return rec; } static symrec * -symrec_define(const char *name, SymType type) +symrec_define(const char *name, SymType type, int in_table) { - symrec *rec = symrec_get_or_new(name); + symrec *rec = symrec_get_or_new(name, in_table); /* Has it been defined before (either by DEFINED or COMMON/EXTERN)? */ if (rec->status & SYM_DEFINED) { @@ -140,27 +146,19 @@ symrec_define(const char *name, SymType type) } symrec * -symrec_define_constant_int(const char *name, unsigned long int_val) +symrec_define_equ(const char *name, expr *e) { - symrec *rec = symrec_define(name, SYM_CONSTANT_INT); - rec->value.int_val = int_val; + symrec *rec = symrec_define(name, SYM_EQU, 1); + rec->value.expn = e; rec->status |= SYM_VALUED; return rec; } symrec * -symrec_define_constant_float(const char *name, floatnum *flt) +symrec_define_label(const char *name, section *sect, bytecode *precbc, + int in_table) { - symrec *rec = symrec_define(name, SYM_CONSTANT_FLOAT); - rec->value.flt = flt; - rec->status |= SYM_VALUED; - return rec; -} - -symrec * -symrec_define_label(const char *name, section *sect, bytecode *precbc) -{ - symrec *rec = symrec_define(name, SYM_LABEL); + symrec *rec = symrec_define(name, SYM_LABEL, in_table); rec->value.label.sect = sect; rec->value.label.bc = precbc; return rec; @@ -169,7 +167,7 @@ symrec_define_label(const char *name, section *sect, bytecode *precbc) symrec * symrec_declare(const char *name, SymVisibility vis) { - symrec *rec = symrec_get_or_new(name); + symrec *rec = symrec_get_or_new(name, 1); /* Don't allow EXTERN and COMMON if symbol has already been DEFINED. */ /* Also, EXTERN and COMMON are mutually exclusive. */ @@ -188,7 +186,7 @@ symrec_declare(const char *name, SymVisibility vis) } return rec; } - +#if 0 int symrec_get_int_value(const symrec *sym, unsigned long *ret_val, int resolve_label) @@ -224,9 +222,67 @@ symrec_get_int_value(const symrec *sym, unsigned long *ret_val, /* We can't get the value right now. */ return 0; } - +#endif const char * symrec_get_name(const symrec *sym) { return sym->name; } + +void +symrec_print(const symrec *sym) +{ + printf("---Symbol `%s'---\n", sym->name); + + switch (sym->type) { + case SYM_UNKNOWN: + printf("-Unknown (Common/Extern)-\n"); + break; + case SYM_EQU: + printf("_EQU_\n"); + printf("Expn="); + expr_print(sym->value.expn); + printf("\n"); + break; + case SYM_LABEL: + printf("_Label_\n"); + printf("Section=`%s'\n", section_get_name(sym->value.label.sect)); + if (!sym->value.label.bc) + printf("[First bytecode]\n"); + else { + printf("[Preceding bytecode]\n"); + bytecode_print(sym->value.label.bc); + } + break; + } + + printf("Status="); + if (sym->status == SYM_NOSTATUS) + printf("None\n"); + else { + if (sym->status & SYM_USED) + printf("Used,"); + if (sym->status & SYM_DEFINED) + printf("Defined,"); + if (sym->status & SYM_VALUED) + printf("Valued,"); + if (sym->status & SYM_NOTINTABLE) + printf("Not in Table,"); + printf("\n"); + } + + printf("Visibility="); + if (sym->visibility == SYM_LOCAL) + printf("Local\n"); + else { + if (sym->visibility & SYM_GLOBAL) + printf("Global,"); + if (sym->visibility & SYM_COMMON) + printf("Common,"); + if (sym->visibility & SYM_EXTERN) + printf("Extern,"); + printf("\n"); + } + + printf("Filename=\"%s\" Line Number=%lu\n", sym->filename, sym->line); +} diff --git a/libyasm/symrec.h b/libyasm/symrec.h index 3b4cd8c3..2f136021 100644 --- a/libyasm/symrec.h +++ b/libyasm/symrec.h @@ -22,9 +22,9 @@ #ifndef YASM_SYMREC_H #define YASM_SYMREC_H -#ifndef YASM_FLOATNUM -#define YASM_FLOATNUM -typedef struct floatnum floatnum; +#ifndef YASM_EXPR +#define YASM_EXPR +typedef struct expr expr; #endif #ifndef YASM_SECTION @@ -51,9 +51,10 @@ typedef struct symrec symrec; #endif symrec *symrec_use(const char *name); -symrec *symrec_define_constant_int(const char *name, unsigned long int_val); -symrec *symrec_define_constant_float(const char *name, floatnum *flt); -symrec *symrec_define_label(const char *name, section *sect, bytecode *precbc); +symrec *symrec_define_equ(const char *name, expr *e); +/* in_table specifies if the label should be inserted into the symbol table. */ +symrec *symrec_define_label(const char *name, section *sect, bytecode *precbc, + int in_table); symrec *symrec_declare(const char *name, SymVisibility vis); /* Get the numeric 32-bit value of a symbol if possible. @@ -66,6 +67,7 @@ int symrec_get_int_value(const symrec *sym, unsigned long *ret_val, const char *symrec_get_name(const symrec *sym); -void symrec_foreach(int (*func) (const char *name, symrec *rec)); +int symrec_foreach(int (*func) (symrec *sym)); +void symrec_print(const symrec *sym); #endif diff --git a/libyasm/tests/floatnum_test.c b/libyasm/tests/floatnum_test.c index d768e3c7..78ef88e8 100644 --- a/libyasm/tests/floatnum_test.c +++ b/libyasm/tests/floatnum_test.c @@ -287,7 +287,8 @@ START_TEST(test_get_single_normalized) for (i=0; ifilename = xstrdup(in_filename); + ptr->line = line_number; + return ptr; } @@ -116,11 +125,11 @@ ExprExpr(expr *x) } ExprItem * -ExprInt(unsigned long i) +ExprInt(intnum *i) { ExprItem *e = xmalloc(sizeof(ExprItem)); e->type = EXPR_INT; - e->data.int_val = i; + e->data.intn = i; return e; } @@ -138,7 +147,7 @@ int expr_simplify(expr *e) { int simplified = 0; - unsigned long int_val; + ExprItem tmp; /* try to simplify the left side */ if (e->left.type == EXPR_EXPR) { @@ -150,14 +159,14 @@ expr_simplify(expr *e) * pull it up into the current node */ while (e->left.type == EXPR_EXPR && e->left.data.expn->op == EXPR_IDENT) { - ExprItem tmp; - e->left.type = e->left.data.expn->right.type; memcpy(&tmp, &(e->left.data.expn->right), sizeof(ExprItem)); free(e->left.data.expn); - memcpy(&(e->left.data.int_val), &tmp, sizeof(ExprItem)); + memcpy(&e->left, &tmp, sizeof(ExprItem)); simplified = 1; } - } else if (e->left.type == EXPR_SYM) { + } +#if 0 + else if (e->left.type == EXPR_SYM) { /* try to get value of symbol */ if (symrec_get_int_value(e->left.data.sym, &int_val, 0)) { e->left.type = EXPR_INT; @@ -166,6 +175,7 @@ expr_simplify(expr *e) simplified = 1; } } +#endif /* ditto on the right */ if (e->right.type == EXPR_EXPR) { @@ -174,14 +184,14 @@ expr_simplify(expr *e) while (e->right.type == EXPR_EXPR && e->right.data.expn->op == EXPR_IDENT) { - ExprItem tmp; - e->right.type = e->right.data.expn->right.type; memcpy(&tmp, &(e->right.data.expn->right), sizeof(ExprItem)); free(e->right.data.expn); - memcpy(&(e->right.data.int_val), &tmp, sizeof(ExprItem)); + memcpy(&e->right, &tmp, sizeof(ExprItem)); simplified = 1; } - } else if (e->right.type == EXPR_SYM) { + } +#if 0 + else if (e->right.type == EXPR_SYM) { if (symrec_get_int_value(e->right.data.sym, &int_val, 0)) { e->right.type = EXPR_INT; /* don't try to free the symrec here. */ @@ -189,139 +199,45 @@ expr_simplify(expr *e) simplified = 1; } } - - if ((e->left.type == EXPR_INT || e->left.type == EXPR_NONE) && - e->right.type == EXPR_INT && e->op != EXPR_IDENT) { - switch (e->op) { - case EXPR_ADD: - e->right.data.int_val = e->left.data.int_val + - e->right.data.int_val; - break; - case EXPR_SUB: - e->right.data.int_val = e->left.data.int_val - - e->right.data.int_val; - break; - case EXPR_MUL: - e->right.data.int_val = e->left.data.int_val * - e->right.data.int_val; - break; - case EXPR_DIV: - e->right.data.int_val = e->left.data.int_val / - e->right.data.int_val; - break; - case EXPR_MOD: - e->right.data.int_val = e->left.data.int_val % - e->right.data.int_val; - break; - case EXPR_NEG: - e->right.data.int_val = -(e->right.data.int_val); - break; - case EXPR_NOT: - e->right.data.int_val = ~(e->right.data.int_val); - break; - case EXPR_OR: - e->right.data.int_val = e->left.data.int_val | - e->right.data.int_val; - break; - case EXPR_AND: - e->right.data.int_val = e->left.data.int_val & - e->right.data.int_val; - break; - case EXPR_XOR: - e->right.data.int_val = e->left.data.int_val ^ - e->right.data.int_val; - break; - case EXPR_SHL: - e->right.data.int_val = e->right.data.int_val << - e->left.data.int_val; - break; - case EXPR_SHR: - e->right.data.int_val = e->right.data.int_val >> - e->left.data.int_val; - break; - case EXPR_LOR: - e->right.data.int_val = e->left.data.int_val || - e->right.data.int_val; - break; - case EXPR_LAND: - e->right.data.int_val = e->left.data.int_val && - e->right.data.int_val; - break; - case EXPR_LNOT: - e->right.data.int_val = !e->right.data.int_val; - break; - case EXPR_EQ: - e->right.data.int_val = e->right.data.int_val == - e->left.data.int_val; - break; - case EXPR_LT: - e->right.data.int_val = e->right.data.int_val < - e->left.data.int_val; - break; - case EXPR_GT: - e->right.data.int_val = e->right.data.int_val > - e->left.data.int_val; - break; - case EXPR_LE: - e->right.data.int_val = e->right.data.int_val <= - e->left.data.int_val; - break; - case EXPR_GE: - e->right.data.int_val = e->right.data.int_val >= - e->left.data.int_val; - break; - case EXPR_NE: - e->right.data.int_val = e->right.data.int_val != - e->left.data.int_val; - break; - case EXPR_IDENT: - break; - } - e->op = EXPR_IDENT; - simplified = 1; - } +#endif /* catch simple identities like 0+x, 1*x, etc., for x not a num */ - else if (e->left.type == EXPR_INT && - ((e->left.data.int_val == 1 && e->op == EXPR_MUL) || - (e->left.data.int_val == 0 && e->op == EXPR_ADD) || - (e->left.data.int_val == -1 && e->op == EXPR_AND) || - (e->left.data.int_val == 0 && e->op == EXPR_OR))) { + if (e->left.type == EXPR_INT && + ((intnum_is_pos1(e->left.data.intn) && e->op == EXPR_MUL) || + (intnum_is_zero(e->left.data.intn) && e->op == EXPR_ADD) || + (intnum_is_neg1(e->left.data.intn) && e->op == EXPR_AND) || + (intnum_is_zero(e->left.data.intn) && e->op == EXPR_OR))) { + intnum_delete(e->left.data.intn); e->op = EXPR_IDENT; simplified = 1; } /* and the corresponding x+|-0, x*&/1 */ else if (e->right.type == EXPR_INT && - ((e->right.data.int_val == 1 && e->op == EXPR_MUL) || - (e->right.data.int_val == 1 && e->op == EXPR_DIV) || - (e->right.data.int_val == 0 && e->op == EXPR_ADD) || - (e->right.data.int_val == 0 && e->op == EXPR_SUB) || - (e->right.data.int_val == -1 && e->op == EXPR_AND) || - (e->right.data.int_val == 0 && e->op == EXPR_OR) || - (e->right.data.int_val == 0 && e->op == EXPR_SHL) || - (e->right.data.int_val == 0 && e->op == EXPR_SHR))) { + ((intnum_is_pos1(e->right.data.intn) && e->op == EXPR_MUL) || + (intnum_is_pos1(e->right.data.intn) && e->op == EXPR_DIV) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_ADD) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SUB) || + (intnum_is_neg1(e->right.data.intn) && e->op == EXPR_AND) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_OR) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SHL) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SHR))) { + intnum_delete(e->right.data.intn); e->op = EXPR_IDENT; e->right.type = e->left.type; memcpy(&e->right, &e->left, sizeof(ExprItem)); simplified = 1; + } else if ((e->left.type == EXPR_INT || e->left.type == EXPR_NONE) && + e->right.type == EXPR_INT && e->op != EXPR_IDENT) { + intnum_calc(e->left.data.intn, e->op, e->right.data.intn); + intnum_delete(e->right.data.intn); + e->right.data.intn = e->left.data.intn; + e->op = EXPR_IDENT; + simplified = 1; } return simplified; } -int -expr_get_value(expr *e, unsigned long *retval) -{ - while (!(e->op == EXPR_IDENT && e->right.type == EXPR_INT) - && expr_simplify(e)) ; - - if (e->op == EXPR_IDENT && e->right.type == EXPR_INT) { - *retval = e->right.data.int_val; - return 1; - } else - return 0; -} - void expr_print(expr *e) { @@ -336,7 +252,7 @@ expr_print(expr *e) printf(")"); break; case EXPR_INT: - printf("%lu", e->left.data.int_val); + intnum_print(e->left.data.intn); break; case EXPR_FLOAT: floatnum_print(e->left.data.flt); @@ -358,9 +274,15 @@ expr_print(expr *e) case EXPR_DIV: printf("/"); break; + case EXPR_SIGNDIV: + printf("//"); + break; case EXPR_MOD: printf("%%"); break; + case EXPR_SIGNMOD: + printf("%%%%"); + break; case EXPR_NEG: printf("-"); break; @@ -422,7 +344,7 @@ expr_print(expr *e) printf(")"); break; case EXPR_INT: - printf("%lu", e->right.data.int_val); + intnum_print(e->right.data.intn); break; case EXPR_FLOAT: floatnum_print(e->right.data.flt); diff --git a/modules/arch/x86/x86expr.c b/modules/arch/x86/x86expr.c index 911fe47d..252065f7 100644 --- a/modules/arch/x86/x86expr.c +++ b/modules/arch/x86/x86expr.c @@ -40,8 +40,11 @@ #define N_(String) (String) #endif +#include "bitvect.h" + #include "globals.h" #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -61,7 +64,7 @@ struct ExprItem { union { symrec *sym; expr *expn; - unsigned long int_val; + intnum *intn; floatnum *flt; } data; }; @@ -69,6 +72,8 @@ struct ExprItem { struct expr { ExprItem left, right; ExprOp op; + char *filename; + unsigned long line; }; /* allocate a new expression node, with children as defined. @@ -93,6 +98,10 @@ expr_new(ExprItem *left, ExprOp op, ExprItem *right) InternalError(__LINE__, __FILE__, _("Right side of expression must exist")); } + + ptr->filename = xstrdup(in_filename); + ptr->line = line_number; + return ptr; } @@ -116,11 +125,11 @@ ExprExpr(expr *x) } ExprItem * -ExprInt(unsigned long i) +ExprInt(intnum *i) { ExprItem *e = xmalloc(sizeof(ExprItem)); e->type = EXPR_INT; - e->data.int_val = i; + e->data.intn = i; return e; } @@ -138,7 +147,7 @@ int expr_simplify(expr *e) { int simplified = 0; - unsigned long int_val; + ExprItem tmp; /* try to simplify the left side */ if (e->left.type == EXPR_EXPR) { @@ -150,14 +159,14 @@ expr_simplify(expr *e) * pull it up into the current node */ while (e->left.type == EXPR_EXPR && e->left.data.expn->op == EXPR_IDENT) { - ExprItem tmp; - e->left.type = e->left.data.expn->right.type; memcpy(&tmp, &(e->left.data.expn->right), sizeof(ExprItem)); free(e->left.data.expn); - memcpy(&(e->left.data.int_val), &tmp, sizeof(ExprItem)); + memcpy(&e->left, &tmp, sizeof(ExprItem)); simplified = 1; } - } else if (e->left.type == EXPR_SYM) { + } +#if 0 + else if (e->left.type == EXPR_SYM) { /* try to get value of symbol */ if (symrec_get_int_value(e->left.data.sym, &int_val, 0)) { e->left.type = EXPR_INT; @@ -166,6 +175,7 @@ expr_simplify(expr *e) simplified = 1; } } +#endif /* ditto on the right */ if (e->right.type == EXPR_EXPR) { @@ -174,14 +184,14 @@ expr_simplify(expr *e) while (e->right.type == EXPR_EXPR && e->right.data.expn->op == EXPR_IDENT) { - ExprItem tmp; - e->right.type = e->right.data.expn->right.type; memcpy(&tmp, &(e->right.data.expn->right), sizeof(ExprItem)); free(e->right.data.expn); - memcpy(&(e->right.data.int_val), &tmp, sizeof(ExprItem)); + memcpy(&e->right, &tmp, sizeof(ExprItem)); simplified = 1; } - } else if (e->right.type == EXPR_SYM) { + } +#if 0 + else if (e->right.type == EXPR_SYM) { if (symrec_get_int_value(e->right.data.sym, &int_val, 0)) { e->right.type = EXPR_INT; /* don't try to free the symrec here. */ @@ -189,139 +199,45 @@ expr_simplify(expr *e) simplified = 1; } } - - if ((e->left.type == EXPR_INT || e->left.type == EXPR_NONE) && - e->right.type == EXPR_INT && e->op != EXPR_IDENT) { - switch (e->op) { - case EXPR_ADD: - e->right.data.int_val = e->left.data.int_val + - e->right.data.int_val; - break; - case EXPR_SUB: - e->right.data.int_val = e->left.data.int_val - - e->right.data.int_val; - break; - case EXPR_MUL: - e->right.data.int_val = e->left.data.int_val * - e->right.data.int_val; - break; - case EXPR_DIV: - e->right.data.int_val = e->left.data.int_val / - e->right.data.int_val; - break; - case EXPR_MOD: - e->right.data.int_val = e->left.data.int_val % - e->right.data.int_val; - break; - case EXPR_NEG: - e->right.data.int_val = -(e->right.data.int_val); - break; - case EXPR_NOT: - e->right.data.int_val = ~(e->right.data.int_val); - break; - case EXPR_OR: - e->right.data.int_val = e->left.data.int_val | - e->right.data.int_val; - break; - case EXPR_AND: - e->right.data.int_val = e->left.data.int_val & - e->right.data.int_val; - break; - case EXPR_XOR: - e->right.data.int_val = e->left.data.int_val ^ - e->right.data.int_val; - break; - case EXPR_SHL: - e->right.data.int_val = e->right.data.int_val << - e->left.data.int_val; - break; - case EXPR_SHR: - e->right.data.int_val = e->right.data.int_val >> - e->left.data.int_val; - break; - case EXPR_LOR: - e->right.data.int_val = e->left.data.int_val || - e->right.data.int_val; - break; - case EXPR_LAND: - e->right.data.int_val = e->left.data.int_val && - e->right.data.int_val; - break; - case EXPR_LNOT: - e->right.data.int_val = !e->right.data.int_val; - break; - case EXPR_EQ: - e->right.data.int_val = e->right.data.int_val == - e->left.data.int_val; - break; - case EXPR_LT: - e->right.data.int_val = e->right.data.int_val < - e->left.data.int_val; - break; - case EXPR_GT: - e->right.data.int_val = e->right.data.int_val > - e->left.data.int_val; - break; - case EXPR_LE: - e->right.data.int_val = e->right.data.int_val <= - e->left.data.int_val; - break; - case EXPR_GE: - e->right.data.int_val = e->right.data.int_val >= - e->left.data.int_val; - break; - case EXPR_NE: - e->right.data.int_val = e->right.data.int_val != - e->left.data.int_val; - break; - case EXPR_IDENT: - break; - } - e->op = EXPR_IDENT; - simplified = 1; - } +#endif /* catch simple identities like 0+x, 1*x, etc., for x not a num */ - else if (e->left.type == EXPR_INT && - ((e->left.data.int_val == 1 && e->op == EXPR_MUL) || - (e->left.data.int_val == 0 && e->op == EXPR_ADD) || - (e->left.data.int_val == -1 && e->op == EXPR_AND) || - (e->left.data.int_val == 0 && e->op == EXPR_OR))) { + if (e->left.type == EXPR_INT && + ((intnum_is_pos1(e->left.data.intn) && e->op == EXPR_MUL) || + (intnum_is_zero(e->left.data.intn) && e->op == EXPR_ADD) || + (intnum_is_neg1(e->left.data.intn) && e->op == EXPR_AND) || + (intnum_is_zero(e->left.data.intn) && e->op == EXPR_OR))) { + intnum_delete(e->left.data.intn); e->op = EXPR_IDENT; simplified = 1; } /* and the corresponding x+|-0, x*&/1 */ else if (e->right.type == EXPR_INT && - ((e->right.data.int_val == 1 && e->op == EXPR_MUL) || - (e->right.data.int_val == 1 && e->op == EXPR_DIV) || - (e->right.data.int_val == 0 && e->op == EXPR_ADD) || - (e->right.data.int_val == 0 && e->op == EXPR_SUB) || - (e->right.data.int_val == -1 && e->op == EXPR_AND) || - (e->right.data.int_val == 0 && e->op == EXPR_OR) || - (e->right.data.int_val == 0 && e->op == EXPR_SHL) || - (e->right.data.int_val == 0 && e->op == EXPR_SHR))) { + ((intnum_is_pos1(e->right.data.intn) && e->op == EXPR_MUL) || + (intnum_is_pos1(e->right.data.intn) && e->op == EXPR_DIV) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_ADD) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SUB) || + (intnum_is_neg1(e->right.data.intn) && e->op == EXPR_AND) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_OR) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SHL) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SHR))) { + intnum_delete(e->right.data.intn); e->op = EXPR_IDENT; e->right.type = e->left.type; memcpy(&e->right, &e->left, sizeof(ExprItem)); simplified = 1; + } else if ((e->left.type == EXPR_INT || e->left.type == EXPR_NONE) && + e->right.type == EXPR_INT && e->op != EXPR_IDENT) { + intnum_calc(e->left.data.intn, e->op, e->right.data.intn); + intnum_delete(e->right.data.intn); + e->right.data.intn = e->left.data.intn; + e->op = EXPR_IDENT; + simplified = 1; } return simplified; } -int -expr_get_value(expr *e, unsigned long *retval) -{ - while (!(e->op == EXPR_IDENT && e->right.type == EXPR_INT) - && expr_simplify(e)) ; - - if (e->op == EXPR_IDENT && e->right.type == EXPR_INT) { - *retval = e->right.data.int_val; - return 1; - } else - return 0; -} - void expr_print(expr *e) { @@ -336,7 +252,7 @@ expr_print(expr *e) printf(")"); break; case EXPR_INT: - printf("%lu", e->left.data.int_val); + intnum_print(e->left.data.intn); break; case EXPR_FLOAT: floatnum_print(e->left.data.flt); @@ -358,9 +274,15 @@ expr_print(expr *e) case EXPR_DIV: printf("/"); break; + case EXPR_SIGNDIV: + printf("//"); + break; case EXPR_MOD: printf("%%"); break; + case EXPR_SIGNMOD: + printf("%%%%"); + break; case EXPR_NEG: printf("-"); break; @@ -422,7 +344,7 @@ expr_print(expr *e) printf(")"); break; case EXPR_INT: - printf("%lu", e->right.data.int_val); + intnum_print(e->right.data.intn); break; case EXPR_FLOAT: floatnum_print(e->right.data.flt); diff --git a/modules/parsers/nasm/bison.y.in b/modules/parsers/nasm/bison.y.in index c69c2e66..e44fcf45 100644 --- a/modules/parsers/nasm/bison.y.in +++ b/modules/parsers/nasm/bison.y.in @@ -35,8 +35,11 @@ #include #define _(String) gettext(String) +#include "bitvect.h" + #include "globals.h" #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -51,7 +54,6 @@ RCSID("$IdPath$"); void init_table(void); extern int nasm_parser_lex(void); -static unsigned long ConvertCharConstToInt(char *); void nasm_parser_error(const char *); extern objfmt *nasm_parser_objfmt; @@ -65,9 +67,11 @@ static bytecode *nasm_parser_temp_bc; %} %union { - unsigned long int_val; + unsigned int int_info; char *str_val; + intnum *intn; floatnum *flt; + symrec *sym; unsigned char groupdata[4]; effaddr *ea; expr *exp; @@ -78,23 +82,24 @@ static bytecode *nasm_parser_temp_bc; bytecode *bc; } -%token INTNUM +%token INTNUM %token FLTNUM %token DIRECTIVE_NAME DIRECTIVE_VAL STRING -%token BYTE WORD DWORD QWORD TWORD DQWORD -%token DECLARE_DATA -%token RESERVE_SPACE +%token BYTE WORD DWORD QWORD TWORD DQWORD +%token DECLARE_DATA +%token RESERVE_SPACE %token INCBIN EQU TIMES %token SEG WRT NEAR SHORT FAR NOSPLIT ORG %token TO %token O16 O32 A16 A32 LOCK REPNZ REP REPZ -%token OPERSIZE ADDRSIZE -%token CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG -%token REG_EAX REG_ECX REG_EDX REG_EBX REG_ESP REG_EBP REG_ESI REG_EDI -%token REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI -%token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH -%token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS -%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD +%token OPERSIZE ADDRSIZE +%token CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG +%token REG_EAX REG_ECX REG_EDX REG_EBX +%token REG_ESP REG_EBP REG_ESI REG_EDI +%token REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI +%token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH +%token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS +%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD START_SECTION_ID %token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ @@ -102,9 +107,9 @@ static bytecode *nasm_parser_temp_bc; /* @TYPES@ */ -%type line exp instr instrbase label +%type line exp instr instrbase -%type fpureg reg32 reg16 reg8 segreg +%type fpureg reg32 reg16 reg8 segreg %type mem memaddr memexp memfar %type mem8x mem16x mem32x mem64x mem80x mem128x %type mem8 mem16 mem32 mem64 mem80 mem128 mem1632 @@ -112,7 +117,8 @@ static bytecode *nasm_parser_temp_bc; %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 %type expr expr_no_string -%type explabel label_id +%type explabel +%type label_id %type target %type dataval %type datavals @@ -164,7 +170,6 @@ datavals: dataval { ; dataval: expr_no_string { $$ = dataval_new_expr($1); } - | FLTNUM { $$ = dataval_new_float($1); } | STRING { $$ = dataval_new_string($1); } | error { Error(_("expression syntax error")); @@ -173,10 +178,12 @@ dataval: expr_no_string { $$ = dataval_new_expr($1); } ; label: label_id { - symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc, + 1); } | label_id ':' { - symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc, + 1); } ; @@ -194,6 +201,8 @@ directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' { nasm_parser_cur_section = sections_switch(&nasm_parser_sections, nasm_parser_objfmt, $3); nasm_parser_prev_bc = (bytecode *)NULL; + symrec_define_label($3, nasm_parser_cur_section, (bytecode *)NULL, + 1); } else { printf("Directive: Name='%s' Value='%s'\n", $2, $3); } @@ -254,7 +263,7 @@ segreg: REG_ES ; /* memory addresses */ -memexp: expr { expr_simplify ($1); $$ = effaddr_new_expr($1); } +memexp: expr { $$ = effaddr_new_expr($1); } ; memaddr: memexp { $$ = $1; SetEASegment($$, 0); } @@ -353,7 +362,7 @@ rm128: XMMREG { $$ = effaddr_new_reg($1); } ; /* immediate values */ -imm: expr { expr_simplify($1); $$ = immval_new_expr($1); } +imm: expr { $$ = immval_new_expr($1); } ; /* explicit immediates */ @@ -383,7 +392,8 @@ target: expr { $$.val = $1; SetOpcodeSel(&$$.op_sel, JR_NONE); } /* expression trees */ expr_no_string: INTNUM { $$ = expr_new_ident(ExprInt($1)); } - | explabel { $$ = expr_new_ident(ExprSym(symrec_use($1))); } + | FLTNUM { $$ = expr_new_ident(ExprFloat($1)); } + | explabel { $$ = expr_new_ident(ExprSym($1)); } /*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); } | expr '^' expr { $$ = expr_new_tree($1, EXPR_XOR, $3); } @@ -401,7 +411,9 @@ expr_no_string: INTNUM { $$ = expr_new_ident(ExprInt($1)); } | expr '-' expr { $$ = expr_new_tree($1, EXPR_SUB, $3); } | expr '*' expr { $$ = expr_new_tree($1, EXPR_MUL, $3); } | expr '/' expr { $$ = expr_new_tree($1, EXPR_DIV, $3); } + | expr SIGNDIV expr { $$ = expr_new_tree($1, EXPR_SIGNDIV, $3); } | expr '%' expr { $$ = expr_new_tree($1, EXPR_MOD, $3); } + | expr SIGNMOD expr { $$ = expr_new_tree($1, EXPR_SIGNMOD, $3); } | '+' expr %prec UNARYOP { $$ = $2; } | '-' expr %prec UNARYOP { $$ = expr_new_branch(EXPR_NEG, $2); } /*| '!' expr { $$ = expr_new_branch(EXPR_LNOT, $2); }*/ @@ -411,13 +423,20 @@ expr_no_string: INTNUM { $$ = expr_new_ident(ExprInt($1)); } expr: expr_no_string | STRING { - $$ = expr_new_ident(ExprInt(ConvertCharConstToInt($1))); + $$ = expr_new_ident(ExprInt(intnum_new_charconst_nasm($1))); } ; -explabel: ID - | SPECIAL_ID - | LOCAL_ID +explabel: ID { $$ = symrec_use($1); } + | SPECIAL_ID { $$ = symrec_use($1); } + | LOCAL_ID { $$ = symrec_use($1); } + | '$' { + $$ = symrec_define_label("$", nasm_parser_cur_section, + nasm_parser_prev_bc, 0); + } + | START_SECTION_ID { + $$ = symrec_use(section_get_name(nasm_parser_cur_section)); + } ; instr: instrbase @@ -440,32 +459,6 @@ instr: instrbase %% -static unsigned long -ConvertCharConstToInt(char *cc) -{ - unsigned long retval = 0; - size_t len = strlen(cc); - - if (len > 4) - Warning(_("character constant too large, ignoring trailing characters")); - - switch (len) { - case 4: - retval |= (unsigned long)cc[3]; - retval <<= 8; - case 3: - retval |= (unsigned long)cc[2]; - retval <<= 8; - case 2: - retval |= (unsigned long)cc[1]; - retval <<= 8; - case 1: - retval |= (unsigned long)cc[0]; - } - - return retval; -} - void nasm_parser_error(const char *s) { diff --git a/modules/parsers/nasm/nasm-bison.y b/modules/parsers/nasm/nasm-bison.y index c69c2e66..e44fcf45 100644 --- a/modules/parsers/nasm/nasm-bison.y +++ b/modules/parsers/nasm/nasm-bison.y @@ -35,8 +35,11 @@ #include #define _(String) gettext(String) +#include "bitvect.h" + #include "globals.h" #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -51,7 +54,6 @@ RCSID("$IdPath$"); void init_table(void); extern int nasm_parser_lex(void); -static unsigned long ConvertCharConstToInt(char *); void nasm_parser_error(const char *); extern objfmt *nasm_parser_objfmt; @@ -65,9 +67,11 @@ static bytecode *nasm_parser_temp_bc; %} %union { - unsigned long int_val; + unsigned int int_info; char *str_val; + intnum *intn; floatnum *flt; + symrec *sym; unsigned char groupdata[4]; effaddr *ea; expr *exp; @@ -78,23 +82,24 @@ static bytecode *nasm_parser_temp_bc; bytecode *bc; } -%token INTNUM +%token INTNUM %token FLTNUM %token DIRECTIVE_NAME DIRECTIVE_VAL STRING -%token BYTE WORD DWORD QWORD TWORD DQWORD -%token DECLARE_DATA -%token RESERVE_SPACE +%token BYTE WORD DWORD QWORD TWORD DQWORD +%token DECLARE_DATA +%token RESERVE_SPACE %token INCBIN EQU TIMES %token SEG WRT NEAR SHORT FAR NOSPLIT ORG %token TO %token O16 O32 A16 A32 LOCK REPNZ REP REPZ -%token OPERSIZE ADDRSIZE -%token CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG -%token REG_EAX REG_ECX REG_EDX REG_EBX REG_ESP REG_EBP REG_ESI REG_EDI -%token REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI -%token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH -%token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS -%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD +%token OPERSIZE ADDRSIZE +%token CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG +%token REG_EAX REG_ECX REG_EDX REG_EBX +%token REG_ESP REG_EBP REG_ESI REG_EDI +%token REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI +%token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH +%token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS +%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD START_SECTION_ID %token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ @@ -102,9 +107,9 @@ static bytecode *nasm_parser_temp_bc; /* @TYPES@ */ -%type line exp instr instrbase label +%type line exp instr instrbase -%type fpureg reg32 reg16 reg8 segreg +%type fpureg reg32 reg16 reg8 segreg %type mem memaddr memexp memfar %type mem8x mem16x mem32x mem64x mem80x mem128x %type mem8 mem16 mem32 mem64 mem80 mem128 mem1632 @@ -112,7 +117,8 @@ static bytecode *nasm_parser_temp_bc; %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 %type expr expr_no_string -%type explabel label_id +%type explabel +%type label_id %type target %type dataval %type datavals @@ -164,7 +170,6 @@ datavals: dataval { ; dataval: expr_no_string { $$ = dataval_new_expr($1); } - | FLTNUM { $$ = dataval_new_float($1); } | STRING { $$ = dataval_new_string($1); } | error { Error(_("expression syntax error")); @@ -173,10 +178,12 @@ dataval: expr_no_string { $$ = dataval_new_expr($1); } ; label: label_id { - symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc, + 1); } | label_id ':' { - symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc, + 1); } ; @@ -194,6 +201,8 @@ directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' { nasm_parser_cur_section = sections_switch(&nasm_parser_sections, nasm_parser_objfmt, $3); nasm_parser_prev_bc = (bytecode *)NULL; + symrec_define_label($3, nasm_parser_cur_section, (bytecode *)NULL, + 1); } else { printf("Directive: Name='%s' Value='%s'\n", $2, $3); } @@ -254,7 +263,7 @@ segreg: REG_ES ; /* memory addresses */ -memexp: expr { expr_simplify ($1); $$ = effaddr_new_expr($1); } +memexp: expr { $$ = effaddr_new_expr($1); } ; memaddr: memexp { $$ = $1; SetEASegment($$, 0); } @@ -353,7 +362,7 @@ rm128: XMMREG { $$ = effaddr_new_reg($1); } ; /* immediate values */ -imm: expr { expr_simplify($1); $$ = immval_new_expr($1); } +imm: expr { $$ = immval_new_expr($1); } ; /* explicit immediates */ @@ -383,7 +392,8 @@ target: expr { $$.val = $1; SetOpcodeSel(&$$.op_sel, JR_NONE); } /* expression trees */ expr_no_string: INTNUM { $$ = expr_new_ident(ExprInt($1)); } - | explabel { $$ = expr_new_ident(ExprSym(symrec_use($1))); } + | FLTNUM { $$ = expr_new_ident(ExprFloat($1)); } + | explabel { $$ = expr_new_ident(ExprSym($1)); } /*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); } | expr '^' expr { $$ = expr_new_tree($1, EXPR_XOR, $3); } @@ -401,7 +411,9 @@ expr_no_string: INTNUM { $$ = expr_new_ident(ExprInt($1)); } | expr '-' expr { $$ = expr_new_tree($1, EXPR_SUB, $3); } | expr '*' expr { $$ = expr_new_tree($1, EXPR_MUL, $3); } | expr '/' expr { $$ = expr_new_tree($1, EXPR_DIV, $3); } + | expr SIGNDIV expr { $$ = expr_new_tree($1, EXPR_SIGNDIV, $3); } | expr '%' expr { $$ = expr_new_tree($1, EXPR_MOD, $3); } + | expr SIGNMOD expr { $$ = expr_new_tree($1, EXPR_SIGNMOD, $3); } | '+' expr %prec UNARYOP { $$ = $2; } | '-' expr %prec UNARYOP { $$ = expr_new_branch(EXPR_NEG, $2); } /*| '!' expr { $$ = expr_new_branch(EXPR_LNOT, $2); }*/ @@ -411,13 +423,20 @@ expr_no_string: INTNUM { $$ = expr_new_ident(ExprInt($1)); } expr: expr_no_string | STRING { - $$ = expr_new_ident(ExprInt(ConvertCharConstToInt($1))); + $$ = expr_new_ident(ExprInt(intnum_new_charconst_nasm($1))); } ; -explabel: ID - | SPECIAL_ID - | LOCAL_ID +explabel: ID { $$ = symrec_use($1); } + | SPECIAL_ID { $$ = symrec_use($1); } + | LOCAL_ID { $$ = symrec_use($1); } + | '$' { + $$ = symrec_define_label("$", nasm_parser_cur_section, + nasm_parser_prev_bc, 0); + } + | START_SECTION_ID { + $$ = symrec_use(section_get_name(nasm_parser_cur_section)); + } ; instr: instrbase @@ -440,32 +459,6 @@ instr: instrbase %% -static unsigned long -ConvertCharConstToInt(char *cc) -{ - unsigned long retval = 0; - size_t len = strlen(cc); - - if (len > 4) - Warning(_("character constant too large, ignoring trailing characters")); - - switch (len) { - case 4: - retval |= (unsigned long)cc[3]; - retval <<= 8; - case 3: - retval |= (unsigned long)cc[2]; - retval <<= 8; - case 2: - retval |= (unsigned long)cc[1]; - retval <<= 8; - case 1: - retval |= (unsigned long)cc[0]; - } - - return retval; -} - void nasm_parser_error(const char *s) { diff --git a/modules/parsers/nasm/token.l.in b/modules/parsers/nasm/token.l.in index 5329e1b4..17c4a996 100644 --- a/modules/parsers/nasm/token.l.in +++ b/modules/parsers/nasm/token.l.in @@ -34,7 +34,10 @@ #include #define _(String) gettext(String) +#include "bitvect.h" + #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -87,31 +90,37 @@ WS [ \t\r] /* standard decimal integer */ {DIGIT}+ { - yylval.int_val = strtoul(yytext, (char **)NULL, 10); + yylval.intn = intnum_new_dec(yytext); return INTNUM; } /* 10010011b - binary number */ {BINDIGIT}+b { - yylval.int_val = strtoul(yytext, (char **)NULL, 2); + yytext[strlen(yytext)] = '\0'; /* strip off 'b' */ + yylval.intn = intnum_new_bin(yytext); return INTNUM; } /* 777q - octal number */ {OCTDIGIT}+q { - yylval.int_val = strtoul(yytext, (char **)NULL, 8); + yytext[strlen(yytext)] = '\0'; /* strip off 'q' */ + yylval.intn = intnum_new_oct(yytext); return INTNUM; } /* 0AAh form of hexidecimal number */ 0{HEXDIGIT}+h { - yylval.int_val = strtoul(yytext+1, (char **)NULL, 16); + yytext[strlen(yytext)] = '\0'; /* strip off 'h' */ + yylval.intn = intnum_new_hex(yytext); return INTNUM; } /* $0AA and 0xAA forms of hexidecimal number */ (\$0|0x){HEXDIGIT}+ { - yylval.int_val = strtoul(yytext+2, (char **)NULL, 16); + if (yytext[1] == 'x') + yylval.intn = intnum_new_hex(yytext+2); /* 0x format, skip 0 and x */ + else + yylval.intn = intnum_new_hex(yytext+1); /* $0 format, don't skip 0 */ return INTNUM; } @@ -182,25 +191,25 @@ WS [ \t\r] } /* size specifiers */ -byte { yylval.int_val = 1; return BYTE; } -word { yylval.int_val = 2; return WORD; } -dword { yylval.int_val = 4; return DWORD; } -qword { yylval.int_val = 8; return QWORD; } -tword { yylval.int_val = 10; return TWORD; } -dqword { yylval.int_val = 16; return DQWORD; } +byte { yylval.int_info = 1; return BYTE; } +word { yylval.int_info = 2; return WORD; } +dword { yylval.int_info = 4; return DWORD; } +qword { yylval.int_info = 8; return QWORD; } +tword { yylval.int_info = 10; return TWORD; } +dqword { yylval.int_info = 16; return DQWORD; } /* pseudo-instructions */ -db { yylval.int_val = 1; return DECLARE_DATA; } -dw { yylval.int_val = 2; return DECLARE_DATA; } -dd { yylval.int_val = 4; return DECLARE_DATA; } -dq { yylval.int_val = 8; return DECLARE_DATA; } -dt { yylval.int_val = 10; return DECLARE_DATA; } - -resb { yylval.int_val = 1; return RESERVE_SPACE; } -resw { yylval.int_val = 2; return RESERVE_SPACE; } -resd { yylval.int_val = 4; return RESERVE_SPACE; } -resq { yylval.int_val = 8; return RESERVE_SPACE; } -rest { yylval.int_val = 10; return RESERVE_SPACE; } +db { yylval.int_info = 1; return DECLARE_DATA; } +dw { yylval.int_info = 2; return DECLARE_DATA; } +dd { yylval.int_info = 4; return DECLARE_DATA; } +dq { yylval.int_info = 8; return DECLARE_DATA; } +dt { yylval.int_info = 10; return DECLARE_DATA; } + +resb { yylval.int_info = 1; return RESERVE_SPACE; } +resw { yylval.int_info = 2; return RESERVE_SPACE; } +resd { yylval.int_info = 4; return RESERVE_SPACE; } +resq { yylval.int_info = 8; return RESERVE_SPACE; } +rest { yylval.int_info = 10; return RESERVE_SPACE; } incbin { return INCBIN; } @@ -221,11 +230,11 @@ org { return ORG; } to { return TO; } /* operand size overrides */ -o16 { yylval.int_val = 16; return OPERSIZE; } -o32 { yylval.int_val = 32; return OPERSIZE; } +o16 { yylval.int_info = 16; return OPERSIZE; } +o32 { yylval.int_info = 32; return OPERSIZE; } /* address size overrides */ -a16 { yylval.int_val = 16; return ADDRSIZE; } -a32 { yylval.int_val = 32; return ADDRSIZE; } +a16 { yylval.int_info = 16; return ADDRSIZE; } +a32 { yylval.int_info = 32; return ADDRSIZE; } /* instruction prefixes */ lock { return LOCK; } @@ -236,62 +245,63 @@ repe { return REPZ; } repz { return REPZ; } /* control, debug, and test registers */ -cr4 { yylval.int_val = 4; return CR4; } -cr[023] { yylval.int_val = yytext[2]-'0'; return CRREG_NOTCR4; } -dr[0-367] { yylval.int_val = yytext[2]-'0'; return DRREG; } -tr[3-7] { yylval.int_val = yytext[2]-'0'; return TRREG; } +cr4 { yylval.int_info = 4; return CR4; } +cr[023] { yylval.int_info = yytext[2]-'0'; return CRREG_NOTCR4; } +dr[0-367] { yylval.int_info = yytext[2]-'0'; return DRREG; } +tr[3-7] { yylval.int_info = yytext[2]-'0'; return TRREG; } /* floating point, MMX, and SSE registers */ -st0 { yylval.int_val = 0; return ST0; } -st[1-7] { yylval.int_val = yytext[2]-'0'; return FPUREG_NOTST0; } -mm[0-7] { yylval.int_val = yytext[2]-'0'; return MMXREG; } -xmm[0-7] { yylval.int_val = yytext[3]-'0'; return XMMREG; } +st0 { yylval.int_info = 0; return ST0; } +st[1-7] { yylval.int_info = yytext[2]-'0'; return FPUREG_NOTST0; } +mm[0-7] { yylval.int_info = yytext[2]-'0'; return MMXREG; } +xmm[0-7] { yylval.int_info = yytext[3]-'0'; return XMMREG; } /* integer registers */ -eax { yylval.int_val = 0; return REG_EAX; } -ecx { yylval.int_val = 1; return REG_ECX; } -edx { yylval.int_val = 2; return REG_EDX; } -ebx { yylval.int_val = 3; return REG_EBX; } -esp { yylval.int_val = 4; return REG_ESP; } -ebp { yylval.int_val = 5; return REG_EBP; } -esi { yylval.int_val = 6; return REG_ESI; } -edi { yylval.int_val = 7; return REG_EDI; } - -ax { yylval.int_val = 0; return REG_AX; } -cx { yylval.int_val = 1; return REG_CX; } -dx { yylval.int_val = 2; return REG_DX; } -bx { yylval.int_val = 3; return REG_BX; } -sp { yylval.int_val = 4; return REG_SP; } -bp { yylval.int_val = 5; return REG_BP; } -si { yylval.int_val = 6; return REG_SI; } -di { yylval.int_val = 7; return REG_DI; } - -al { yylval.int_val = 0; return REG_AL; } -cl { yylval.int_val = 1; return REG_CL; } -dl { yylval.int_val = 2; return REG_DL; } -bl { yylval.int_val = 3; return REG_BL; } -ah { yylval.int_val = 4; return REG_AH; } -ch { yylval.int_val = 5; return REG_CH; } -dh { yylval.int_val = 6; return REG_DH; } -bh { yylval.int_val = 7; return REG_BH; } +eax { yylval.int_info = 0; return REG_EAX; } +ecx { yylval.int_info = 1; return REG_ECX; } +edx { yylval.int_info = 2; return REG_EDX; } +ebx { yylval.int_info = 3; return REG_EBX; } +esp { yylval.int_info = 4; return REG_ESP; } +ebp { yylval.int_info = 5; return REG_EBP; } +esi { yylval.int_info = 6; return REG_ESI; } +edi { yylval.int_info = 7; return REG_EDI; } + +ax { yylval.int_info = 0; return REG_AX; } +cx { yylval.int_info = 1; return REG_CX; } +dx { yylval.int_info = 2; return REG_DX; } +bx { yylval.int_info = 3; return REG_BX; } +sp { yylval.int_info = 4; return REG_SP; } +bp { yylval.int_info = 5; return REG_BP; } +si { yylval.int_info = 6; return REG_SI; } +di { yylval.int_info = 7; return REG_DI; } + +al { yylval.int_info = 0; return REG_AL; } +cl { yylval.int_info = 1; return REG_CL; } +dl { yylval.int_info = 2; return REG_DL; } +bl { yylval.int_info = 3; return REG_BL; } +ah { yylval.int_info = 4; return REG_AH; } +ch { yylval.int_info = 5; return REG_CH; } +dh { yylval.int_info = 6; return REG_DH; } +bh { yylval.int_info = 7; return REG_BH; } /* segment registers */ -es { yylval.int_val = 0; return REG_ES; } -cs { yylval.int_val = 1; return REG_CS; } -ss { yylval.int_val = 2; return REG_SS; } -ds { yylval.int_val = 3; return REG_DS; } -fs { yylval.int_val = 4; return REG_FS; } -gs { yylval.int_val = 5; return REG_GS; } +es { yylval.int_info = 0; return REG_ES; } +cs { yylval.int_info = 1; return REG_CS; } +ss { yylval.int_info = 2; return REG_SS; } +ds { yylval.int_info = 3; return REG_DS; } +fs { yylval.int_info = 4; return REG_FS; } +gs { yylval.int_info = 5; return REG_GS; } /* operators */ "<<" { return LEFT_OP; } ">>" { return RIGHT_OP; } "//" { return SIGNDIV; } "%%" { return SIGNMOD; } -[-+|^&*/%~():[\],] { return yytext[0]; } +"$$" { return START_SECTION_ID; } +[-+|^&*/%~$():[\],] { return yytext[0]; } /* special non-local ..@label and labels like ..start */ -$$|$|\.\.[a-z0-9_$#@~.?]+ { +\.\.[a-z0-9_$#@~.?]+ { yylval.str_val = xstrdup(yytext); return SPECIAL_ID; } diff --git a/src/Makefile.am b/src/Makefile.am index 41a5782e..16dc8998 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,6 +41,8 @@ libyasm_a_SOURCES = \ parser.c \ parser.h \ optimizer.h \ + intnum.c \ + intnum.h \ floatnum.c \ floatnum.h \ ternary.c \ @@ -55,5 +57,4 @@ CFLAGS = @ANSI_CFLAGS@ EXTRA_DIST = \ instrs.dat \ - compat-queue.h \ - strtoul.c + compat-queue.h diff --git a/src/arch/x86/expr.c b/src/arch/x86/expr.c index 911fe47d..252065f7 100644 --- a/src/arch/x86/expr.c +++ b/src/arch/x86/expr.c @@ -40,8 +40,11 @@ #define N_(String) (String) #endif +#include "bitvect.h" + #include "globals.h" #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -61,7 +64,7 @@ struct ExprItem { union { symrec *sym; expr *expn; - unsigned long int_val; + intnum *intn; floatnum *flt; } data; }; @@ -69,6 +72,8 @@ struct ExprItem { struct expr { ExprItem left, right; ExprOp op; + char *filename; + unsigned long line; }; /* allocate a new expression node, with children as defined. @@ -93,6 +98,10 @@ expr_new(ExprItem *left, ExprOp op, ExprItem *right) InternalError(__LINE__, __FILE__, _("Right side of expression must exist")); } + + ptr->filename = xstrdup(in_filename); + ptr->line = line_number; + return ptr; } @@ -116,11 +125,11 @@ ExprExpr(expr *x) } ExprItem * -ExprInt(unsigned long i) +ExprInt(intnum *i) { ExprItem *e = xmalloc(sizeof(ExprItem)); e->type = EXPR_INT; - e->data.int_val = i; + e->data.intn = i; return e; } @@ -138,7 +147,7 @@ int expr_simplify(expr *e) { int simplified = 0; - unsigned long int_val; + ExprItem tmp; /* try to simplify the left side */ if (e->left.type == EXPR_EXPR) { @@ -150,14 +159,14 @@ expr_simplify(expr *e) * pull it up into the current node */ while (e->left.type == EXPR_EXPR && e->left.data.expn->op == EXPR_IDENT) { - ExprItem tmp; - e->left.type = e->left.data.expn->right.type; memcpy(&tmp, &(e->left.data.expn->right), sizeof(ExprItem)); free(e->left.data.expn); - memcpy(&(e->left.data.int_val), &tmp, sizeof(ExprItem)); + memcpy(&e->left, &tmp, sizeof(ExprItem)); simplified = 1; } - } else if (e->left.type == EXPR_SYM) { + } +#if 0 + else if (e->left.type == EXPR_SYM) { /* try to get value of symbol */ if (symrec_get_int_value(e->left.data.sym, &int_val, 0)) { e->left.type = EXPR_INT; @@ -166,6 +175,7 @@ expr_simplify(expr *e) simplified = 1; } } +#endif /* ditto on the right */ if (e->right.type == EXPR_EXPR) { @@ -174,14 +184,14 @@ expr_simplify(expr *e) while (e->right.type == EXPR_EXPR && e->right.data.expn->op == EXPR_IDENT) { - ExprItem tmp; - e->right.type = e->right.data.expn->right.type; memcpy(&tmp, &(e->right.data.expn->right), sizeof(ExprItem)); free(e->right.data.expn); - memcpy(&(e->right.data.int_val), &tmp, sizeof(ExprItem)); + memcpy(&e->right, &tmp, sizeof(ExprItem)); simplified = 1; } - } else if (e->right.type == EXPR_SYM) { + } +#if 0 + else if (e->right.type == EXPR_SYM) { if (symrec_get_int_value(e->right.data.sym, &int_val, 0)) { e->right.type = EXPR_INT; /* don't try to free the symrec here. */ @@ -189,139 +199,45 @@ expr_simplify(expr *e) simplified = 1; } } - - if ((e->left.type == EXPR_INT || e->left.type == EXPR_NONE) && - e->right.type == EXPR_INT && e->op != EXPR_IDENT) { - switch (e->op) { - case EXPR_ADD: - e->right.data.int_val = e->left.data.int_val + - e->right.data.int_val; - break; - case EXPR_SUB: - e->right.data.int_val = e->left.data.int_val - - e->right.data.int_val; - break; - case EXPR_MUL: - e->right.data.int_val = e->left.data.int_val * - e->right.data.int_val; - break; - case EXPR_DIV: - e->right.data.int_val = e->left.data.int_val / - e->right.data.int_val; - break; - case EXPR_MOD: - e->right.data.int_val = e->left.data.int_val % - e->right.data.int_val; - break; - case EXPR_NEG: - e->right.data.int_val = -(e->right.data.int_val); - break; - case EXPR_NOT: - e->right.data.int_val = ~(e->right.data.int_val); - break; - case EXPR_OR: - e->right.data.int_val = e->left.data.int_val | - e->right.data.int_val; - break; - case EXPR_AND: - e->right.data.int_val = e->left.data.int_val & - e->right.data.int_val; - break; - case EXPR_XOR: - e->right.data.int_val = e->left.data.int_val ^ - e->right.data.int_val; - break; - case EXPR_SHL: - e->right.data.int_val = e->right.data.int_val << - e->left.data.int_val; - break; - case EXPR_SHR: - e->right.data.int_val = e->right.data.int_val >> - e->left.data.int_val; - break; - case EXPR_LOR: - e->right.data.int_val = e->left.data.int_val || - e->right.data.int_val; - break; - case EXPR_LAND: - e->right.data.int_val = e->left.data.int_val && - e->right.data.int_val; - break; - case EXPR_LNOT: - e->right.data.int_val = !e->right.data.int_val; - break; - case EXPR_EQ: - e->right.data.int_val = e->right.data.int_val == - e->left.data.int_val; - break; - case EXPR_LT: - e->right.data.int_val = e->right.data.int_val < - e->left.data.int_val; - break; - case EXPR_GT: - e->right.data.int_val = e->right.data.int_val > - e->left.data.int_val; - break; - case EXPR_LE: - e->right.data.int_val = e->right.data.int_val <= - e->left.data.int_val; - break; - case EXPR_GE: - e->right.data.int_val = e->right.data.int_val >= - e->left.data.int_val; - break; - case EXPR_NE: - e->right.data.int_val = e->right.data.int_val != - e->left.data.int_val; - break; - case EXPR_IDENT: - break; - } - e->op = EXPR_IDENT; - simplified = 1; - } +#endif /* catch simple identities like 0+x, 1*x, etc., for x not a num */ - else if (e->left.type == EXPR_INT && - ((e->left.data.int_val == 1 && e->op == EXPR_MUL) || - (e->left.data.int_val == 0 && e->op == EXPR_ADD) || - (e->left.data.int_val == -1 && e->op == EXPR_AND) || - (e->left.data.int_val == 0 && e->op == EXPR_OR))) { + if (e->left.type == EXPR_INT && + ((intnum_is_pos1(e->left.data.intn) && e->op == EXPR_MUL) || + (intnum_is_zero(e->left.data.intn) && e->op == EXPR_ADD) || + (intnum_is_neg1(e->left.data.intn) && e->op == EXPR_AND) || + (intnum_is_zero(e->left.data.intn) && e->op == EXPR_OR))) { + intnum_delete(e->left.data.intn); e->op = EXPR_IDENT; simplified = 1; } /* and the corresponding x+|-0, x*&/1 */ else if (e->right.type == EXPR_INT && - ((e->right.data.int_val == 1 && e->op == EXPR_MUL) || - (e->right.data.int_val == 1 && e->op == EXPR_DIV) || - (e->right.data.int_val == 0 && e->op == EXPR_ADD) || - (e->right.data.int_val == 0 && e->op == EXPR_SUB) || - (e->right.data.int_val == -1 && e->op == EXPR_AND) || - (e->right.data.int_val == 0 && e->op == EXPR_OR) || - (e->right.data.int_val == 0 && e->op == EXPR_SHL) || - (e->right.data.int_val == 0 && e->op == EXPR_SHR))) { + ((intnum_is_pos1(e->right.data.intn) && e->op == EXPR_MUL) || + (intnum_is_pos1(e->right.data.intn) && e->op == EXPR_DIV) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_ADD) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SUB) || + (intnum_is_neg1(e->right.data.intn) && e->op == EXPR_AND) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_OR) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SHL) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SHR))) { + intnum_delete(e->right.data.intn); e->op = EXPR_IDENT; e->right.type = e->left.type; memcpy(&e->right, &e->left, sizeof(ExprItem)); simplified = 1; + } else if ((e->left.type == EXPR_INT || e->left.type == EXPR_NONE) && + e->right.type == EXPR_INT && e->op != EXPR_IDENT) { + intnum_calc(e->left.data.intn, e->op, e->right.data.intn); + intnum_delete(e->right.data.intn); + e->right.data.intn = e->left.data.intn; + e->op = EXPR_IDENT; + simplified = 1; } return simplified; } -int -expr_get_value(expr *e, unsigned long *retval) -{ - while (!(e->op == EXPR_IDENT && e->right.type == EXPR_INT) - && expr_simplify(e)) ; - - if (e->op == EXPR_IDENT && e->right.type == EXPR_INT) { - *retval = e->right.data.int_val; - return 1; - } else - return 0; -} - void expr_print(expr *e) { @@ -336,7 +252,7 @@ expr_print(expr *e) printf(")"); break; case EXPR_INT: - printf("%lu", e->left.data.int_val); + intnum_print(e->left.data.intn); break; case EXPR_FLOAT: floatnum_print(e->left.data.flt); @@ -358,9 +274,15 @@ expr_print(expr *e) case EXPR_DIV: printf("/"); break; + case EXPR_SIGNDIV: + printf("//"); + break; case EXPR_MOD: printf("%%"); break; + case EXPR_SIGNMOD: + printf("%%%%"); + break; case EXPR_NEG: printf("-"); break; @@ -422,7 +344,7 @@ expr_print(expr *e) printf(")"); break; case EXPR_INT: - printf("%lu", e->right.data.int_val); + intnum_print(e->right.data.intn); break; case EXPR_FLOAT: floatnum_print(e->right.data.flt); diff --git a/src/arch/x86/x86expr.c b/src/arch/x86/x86expr.c index 911fe47d..252065f7 100644 --- a/src/arch/x86/x86expr.c +++ b/src/arch/x86/x86expr.c @@ -40,8 +40,11 @@ #define N_(String) (String) #endif +#include "bitvect.h" + #include "globals.h" #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -61,7 +64,7 @@ struct ExprItem { union { symrec *sym; expr *expn; - unsigned long int_val; + intnum *intn; floatnum *flt; } data; }; @@ -69,6 +72,8 @@ struct ExprItem { struct expr { ExprItem left, right; ExprOp op; + char *filename; + unsigned long line; }; /* allocate a new expression node, with children as defined. @@ -93,6 +98,10 @@ expr_new(ExprItem *left, ExprOp op, ExprItem *right) InternalError(__LINE__, __FILE__, _("Right side of expression must exist")); } + + ptr->filename = xstrdup(in_filename); + ptr->line = line_number; + return ptr; } @@ -116,11 +125,11 @@ ExprExpr(expr *x) } ExprItem * -ExprInt(unsigned long i) +ExprInt(intnum *i) { ExprItem *e = xmalloc(sizeof(ExprItem)); e->type = EXPR_INT; - e->data.int_val = i; + e->data.intn = i; return e; } @@ -138,7 +147,7 @@ int expr_simplify(expr *e) { int simplified = 0; - unsigned long int_val; + ExprItem tmp; /* try to simplify the left side */ if (e->left.type == EXPR_EXPR) { @@ -150,14 +159,14 @@ expr_simplify(expr *e) * pull it up into the current node */ while (e->left.type == EXPR_EXPR && e->left.data.expn->op == EXPR_IDENT) { - ExprItem tmp; - e->left.type = e->left.data.expn->right.type; memcpy(&tmp, &(e->left.data.expn->right), sizeof(ExprItem)); free(e->left.data.expn); - memcpy(&(e->left.data.int_val), &tmp, sizeof(ExprItem)); + memcpy(&e->left, &tmp, sizeof(ExprItem)); simplified = 1; } - } else if (e->left.type == EXPR_SYM) { + } +#if 0 + else if (e->left.type == EXPR_SYM) { /* try to get value of symbol */ if (symrec_get_int_value(e->left.data.sym, &int_val, 0)) { e->left.type = EXPR_INT; @@ -166,6 +175,7 @@ expr_simplify(expr *e) simplified = 1; } } +#endif /* ditto on the right */ if (e->right.type == EXPR_EXPR) { @@ -174,14 +184,14 @@ expr_simplify(expr *e) while (e->right.type == EXPR_EXPR && e->right.data.expn->op == EXPR_IDENT) { - ExprItem tmp; - e->right.type = e->right.data.expn->right.type; memcpy(&tmp, &(e->right.data.expn->right), sizeof(ExprItem)); free(e->right.data.expn); - memcpy(&(e->right.data.int_val), &tmp, sizeof(ExprItem)); + memcpy(&e->right, &tmp, sizeof(ExprItem)); simplified = 1; } - } else if (e->right.type == EXPR_SYM) { + } +#if 0 + else if (e->right.type == EXPR_SYM) { if (symrec_get_int_value(e->right.data.sym, &int_val, 0)) { e->right.type = EXPR_INT; /* don't try to free the symrec here. */ @@ -189,139 +199,45 @@ expr_simplify(expr *e) simplified = 1; } } - - if ((e->left.type == EXPR_INT || e->left.type == EXPR_NONE) && - e->right.type == EXPR_INT && e->op != EXPR_IDENT) { - switch (e->op) { - case EXPR_ADD: - e->right.data.int_val = e->left.data.int_val + - e->right.data.int_val; - break; - case EXPR_SUB: - e->right.data.int_val = e->left.data.int_val - - e->right.data.int_val; - break; - case EXPR_MUL: - e->right.data.int_val = e->left.data.int_val * - e->right.data.int_val; - break; - case EXPR_DIV: - e->right.data.int_val = e->left.data.int_val / - e->right.data.int_val; - break; - case EXPR_MOD: - e->right.data.int_val = e->left.data.int_val % - e->right.data.int_val; - break; - case EXPR_NEG: - e->right.data.int_val = -(e->right.data.int_val); - break; - case EXPR_NOT: - e->right.data.int_val = ~(e->right.data.int_val); - break; - case EXPR_OR: - e->right.data.int_val = e->left.data.int_val | - e->right.data.int_val; - break; - case EXPR_AND: - e->right.data.int_val = e->left.data.int_val & - e->right.data.int_val; - break; - case EXPR_XOR: - e->right.data.int_val = e->left.data.int_val ^ - e->right.data.int_val; - break; - case EXPR_SHL: - e->right.data.int_val = e->right.data.int_val << - e->left.data.int_val; - break; - case EXPR_SHR: - e->right.data.int_val = e->right.data.int_val >> - e->left.data.int_val; - break; - case EXPR_LOR: - e->right.data.int_val = e->left.data.int_val || - e->right.data.int_val; - break; - case EXPR_LAND: - e->right.data.int_val = e->left.data.int_val && - e->right.data.int_val; - break; - case EXPR_LNOT: - e->right.data.int_val = !e->right.data.int_val; - break; - case EXPR_EQ: - e->right.data.int_val = e->right.data.int_val == - e->left.data.int_val; - break; - case EXPR_LT: - e->right.data.int_val = e->right.data.int_val < - e->left.data.int_val; - break; - case EXPR_GT: - e->right.data.int_val = e->right.data.int_val > - e->left.data.int_val; - break; - case EXPR_LE: - e->right.data.int_val = e->right.data.int_val <= - e->left.data.int_val; - break; - case EXPR_GE: - e->right.data.int_val = e->right.data.int_val >= - e->left.data.int_val; - break; - case EXPR_NE: - e->right.data.int_val = e->right.data.int_val != - e->left.data.int_val; - break; - case EXPR_IDENT: - break; - } - e->op = EXPR_IDENT; - simplified = 1; - } +#endif /* catch simple identities like 0+x, 1*x, etc., for x not a num */ - else if (e->left.type == EXPR_INT && - ((e->left.data.int_val == 1 && e->op == EXPR_MUL) || - (e->left.data.int_val == 0 && e->op == EXPR_ADD) || - (e->left.data.int_val == -1 && e->op == EXPR_AND) || - (e->left.data.int_val == 0 && e->op == EXPR_OR))) { + if (e->left.type == EXPR_INT && + ((intnum_is_pos1(e->left.data.intn) && e->op == EXPR_MUL) || + (intnum_is_zero(e->left.data.intn) && e->op == EXPR_ADD) || + (intnum_is_neg1(e->left.data.intn) && e->op == EXPR_AND) || + (intnum_is_zero(e->left.data.intn) && e->op == EXPR_OR))) { + intnum_delete(e->left.data.intn); e->op = EXPR_IDENT; simplified = 1; } /* and the corresponding x+|-0, x*&/1 */ else if (e->right.type == EXPR_INT && - ((e->right.data.int_val == 1 && e->op == EXPR_MUL) || - (e->right.data.int_val == 1 && e->op == EXPR_DIV) || - (e->right.data.int_val == 0 && e->op == EXPR_ADD) || - (e->right.data.int_val == 0 && e->op == EXPR_SUB) || - (e->right.data.int_val == -1 && e->op == EXPR_AND) || - (e->right.data.int_val == 0 && e->op == EXPR_OR) || - (e->right.data.int_val == 0 && e->op == EXPR_SHL) || - (e->right.data.int_val == 0 && e->op == EXPR_SHR))) { + ((intnum_is_pos1(e->right.data.intn) && e->op == EXPR_MUL) || + (intnum_is_pos1(e->right.data.intn) && e->op == EXPR_DIV) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_ADD) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SUB) || + (intnum_is_neg1(e->right.data.intn) && e->op == EXPR_AND) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_OR) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SHL) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SHR))) { + intnum_delete(e->right.data.intn); e->op = EXPR_IDENT; e->right.type = e->left.type; memcpy(&e->right, &e->left, sizeof(ExprItem)); simplified = 1; + } else if ((e->left.type == EXPR_INT || e->left.type == EXPR_NONE) && + e->right.type == EXPR_INT && e->op != EXPR_IDENT) { + intnum_calc(e->left.data.intn, e->op, e->right.data.intn); + intnum_delete(e->right.data.intn); + e->right.data.intn = e->left.data.intn; + e->op = EXPR_IDENT; + simplified = 1; } return simplified; } -int -expr_get_value(expr *e, unsigned long *retval) -{ - while (!(e->op == EXPR_IDENT && e->right.type == EXPR_INT) - && expr_simplify(e)) ; - - if (e->op == EXPR_IDENT && e->right.type == EXPR_INT) { - *retval = e->right.data.int_val; - return 1; - } else - return 0; -} - void expr_print(expr *e) { @@ -336,7 +252,7 @@ expr_print(expr *e) printf(")"); break; case EXPR_INT: - printf("%lu", e->left.data.int_val); + intnum_print(e->left.data.intn); break; case EXPR_FLOAT: floatnum_print(e->left.data.flt); @@ -358,9 +274,15 @@ expr_print(expr *e) case EXPR_DIV: printf("/"); break; + case EXPR_SIGNDIV: + printf("//"); + break; case EXPR_MOD: printf("%%"); break; + case EXPR_SIGNMOD: + printf("%%%%"); + break; case EXPR_NEG: printf("-"); break; @@ -422,7 +344,7 @@ expr_print(expr *e) printf(")"); break; case EXPR_INT: - printf("%lu", e->right.data.int_val); + intnum_print(e->right.data.intn); break; case EXPR_FLOAT: floatnum_print(e->right.data.flt); diff --git a/src/bytecode.c b/src/bytecode.c index 96620a1d..24bf0b20 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -37,6 +37,7 @@ #include "globals.h" #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" @@ -73,11 +74,10 @@ struct immval { struct dataval { STAILQ_ENTRY(dataval) link; - enum { DV_EMPTY, DV_EXPR, DV_FLOAT, DV_STRING } type; + enum { DV_EMPTY, DV_EXPR, DV_STRING } type; union { expr *expn; - floatnum *flt; char *str_val; } data; }; @@ -229,7 +229,7 @@ immval_new_int(unsigned long int_val) { immval *im = xmalloc(sizeof(immval)); - im->val = expr_new_ident(ExprInt(int_val)); + im->val = expr_new_ident(ExprInt(intnum_new_int(int_val))); if ((int_val & 0xFF) == int_val) im->len = 1; @@ -249,7 +249,7 @@ immval_new_expr(expr *expr_ptr) immval *im = xmalloc(sizeof(immval)); im->val = expr_ptr; - + im->len = 0; im->isneg = 0; return im; @@ -486,46 +486,7 @@ bytecode_new_jmprel(targetval *target, bytecode * bytecode_new_data(datavalhead *datahead, unsigned long size) { - bytecode *bc; - dataval *cur; - - /* First check to see if all the data elements are valid for the size - * being set. - * Validity table: - * db (1) -> expr, string - * dw (2) -> expr, string - * dd (4) -> expr, float, string - * dq (8) -> expr, float, string - * dt (10) -> float, string - * - * Once we calculate expr we'll have to validate it against the size - * and warn/error appropriately (symbol constants versus labels: - * constants (equ's) should always be legal, but labels should raise - * warnings when used in db or dq context at the minimum). - */ - STAILQ_FOREACH(cur, datahead, link) { - switch (cur->type) { - case DV_EMPTY: - case DV_STRING: - /* string is valid in every size */ - break; - case DV_FLOAT: - if (size == 1) - Error(_("floating-point constant encountered in `%s'"), - "DB"); - else if (size == 2) - Error(_("floating-point constant encountered in `%s'"), - "DW"); - break; - case DV_EXPR: - if (size == 10) - Error(_("non-floating-point value encountered in `%s'"), - "DT"); - break; - } - } - - bc = bytecode_new_common(); + bytecode *bc = bytecode_new_common(); bc->type = BC_DATA; @@ -570,14 +531,14 @@ bytecode_print(bytecode *bc) printf("\n Disp="); expr_print(bc->data.insn.ea->disp); printf("\n"); - printf(" Len=%u SegmentOv=%2x\n", + printf(" Len=%u SegmentOv=%02x\n", (unsigned int)bc->data.insn.ea->len, (unsigned int)bc->data.insn.ea->segment); - printf(" ModRM=%2x ValidRM=%u NeedRM=%u\n", + printf(" ModRM=%02x ValidRM=%u NeedRM=%u\n", (unsigned int)bc->data.insn.ea->modrm, (unsigned int)bc->data.insn.ea->valid_modrm, (unsigned int)bc->data.insn.ea->need_modrm); - printf(" SIB=%2x ValidSIB=%u NeedSIB=%u\n", + printf(" SIB=%02x ValidSIB=%u NeedSIB=%u\n", (unsigned int)bc->data.insn.ea->sib, (unsigned int)bc->data.insn.ea->valid_sib, (unsigned int)bc->data.insn.ea->need_sib); @@ -595,16 +556,17 @@ bytecode_print(bytecode *bc) printf(" FLen=%u, FSign=%u\n", (unsigned int)bc->data.insn.imm->f_len, (unsigned int)bc->data.insn.imm->f_sign); - printf("Opcode: %2x %2x %2x OpLen=%u\n", - (unsigned int)bc->data.insn.opcode[0], - (unsigned int)bc->data.insn.opcode[1], - (unsigned int)bc->data.insn.opcode[2], - (unsigned int)bc->data.insn.opcode_len); - printf("AddrSize=%u OperSize=%u LockRepPre=%2x\n", - (unsigned int)bc->data.insn.addrsize, - (unsigned int)bc->data.insn.opersize, - (unsigned int)bc->data.insn.lockrep_pre); } + printf("Opcode: %02x %02x %02x OpLen=%u\n", + (unsigned int)bc->data.insn.opcode[0], + (unsigned int)bc->data.insn.opcode[1], + (unsigned int)bc->data.insn.opcode[2], + (unsigned int)bc->data.insn.opcode_len); + printf("AddrSize=%u OperSize=%u LockRepPre=%02x ShiftOp=%u\n", + (unsigned int)bc->data.insn.addrsize, + (unsigned int)bc->data.insn.opersize, + (unsigned int)bc->data.insn.lockrep_pre, + (unsigned int)bc->data.insn.shift_op); break; case BC_JMPREL: printf("_Relative Jump_\n"); @@ -614,7 +576,7 @@ bytecode_print(bytecode *bc) if (!bc->data.jmprel.shortop.opcode_len == 0) printf(" None\n"); else - printf(" Opcode: %2x %2x %2x OpLen=%u\n", + printf(" Opcode: %02x %02x %02x OpLen=%u\n", (unsigned int)bc->data.jmprel.shortop.opcode[0], (unsigned int)bc->data.jmprel.shortop.opcode[1], (unsigned int)bc->data.jmprel.shortop.opcode[2], @@ -622,7 +584,7 @@ bytecode_print(bytecode *bc) if (!bc->data.jmprel.nearop.opcode_len == 0) printf(" None\n"); else - printf(" Opcode: %2x %2x %2x OpLen=%u\n", + printf(" Opcode: %02x %02x %02x OpLen=%u\n", (unsigned int)bc->data.jmprel.nearop.opcode[0], (unsigned int)bc->data.jmprel.nearop.opcode[1], (unsigned int)bc->data.jmprel.nearop.opcode[2], @@ -648,7 +610,7 @@ bytecode_print(bytecode *bc) printf("UNKNOWN!!"); break; } - printf("\nAddrSize=%u OperSize=%u LockRepPre=%2x\n", + printf("\nAddrSize=%u OperSize=%u LockRepPre=%02x\n", (unsigned int)bc->data.jmprel.addrsize, (unsigned int)bc->data.jmprel.opersize, (unsigned int)bc->data.jmprel.lockrep_pre); @@ -690,24 +652,24 @@ bytecodes_append(bytecodehead *headp, bytecode *bc) return (bytecode *)NULL; } -dataval * -dataval_new_expr(expr *expn) +void +bytecodes_print(const bytecodehead *headp) { - dataval *retval = xmalloc(sizeof(dataval)); - - retval->type = DV_EXPR; - retval->data.expn = expn; + bytecode *cur; - return retval; + STAILQ_FOREACH(cur, headp, link) { + printf("---Next Bytecode---\n"); + bytecode_print(cur); + } } dataval * -dataval_new_float(floatnum *flt) +dataval_new_expr(expr *expn) { dataval *retval = xmalloc(sizeof(dataval)); - retval->type = DV_FLOAT; - retval->data.flt = flt; + retval->type = DV_EXPR; + retval->data.expn = expn; return retval; } @@ -748,11 +710,6 @@ dataval_print(datavalhead *head) expr_print(cur->data.expn); printf("\n"); break; - case DV_FLOAT: - printf(" Float="); - floatnum_print(cur->data.flt); - printf("\n"); - break; case DV_STRING: printf(" String=%s\n", cur->data.str_val); break; diff --git a/src/bytecode.h b/src/bytecode.h index 32ffa963..be485e4f 100644 --- a/src/bytecode.h +++ b/src/bytecode.h @@ -129,6 +129,8 @@ void bytecode_print(bytecode *bc); */ bytecode *bytecodes_append(bytecodehead *headp, bytecode *bc); +void bytecodes_print(const bytecodehead *headp); + dataval *dataval_new_expr(expr *expn); dataval *dataval_new_float(floatnum *flt); dataval *dataval_new_string(char *str_val); diff --git a/src/expr.c b/src/expr.c index 911fe47d..252065f7 100644 --- a/src/expr.c +++ b/src/expr.c @@ -40,8 +40,11 @@ #define N_(String) (String) #endif +#include "bitvect.h" + #include "globals.h" #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -61,7 +64,7 @@ struct ExprItem { union { symrec *sym; expr *expn; - unsigned long int_val; + intnum *intn; floatnum *flt; } data; }; @@ -69,6 +72,8 @@ struct ExprItem { struct expr { ExprItem left, right; ExprOp op; + char *filename; + unsigned long line; }; /* allocate a new expression node, with children as defined. @@ -93,6 +98,10 @@ expr_new(ExprItem *left, ExprOp op, ExprItem *right) InternalError(__LINE__, __FILE__, _("Right side of expression must exist")); } + + ptr->filename = xstrdup(in_filename); + ptr->line = line_number; + return ptr; } @@ -116,11 +125,11 @@ ExprExpr(expr *x) } ExprItem * -ExprInt(unsigned long i) +ExprInt(intnum *i) { ExprItem *e = xmalloc(sizeof(ExprItem)); e->type = EXPR_INT; - e->data.int_val = i; + e->data.intn = i; return e; } @@ -138,7 +147,7 @@ int expr_simplify(expr *e) { int simplified = 0; - unsigned long int_val; + ExprItem tmp; /* try to simplify the left side */ if (e->left.type == EXPR_EXPR) { @@ -150,14 +159,14 @@ expr_simplify(expr *e) * pull it up into the current node */ while (e->left.type == EXPR_EXPR && e->left.data.expn->op == EXPR_IDENT) { - ExprItem tmp; - e->left.type = e->left.data.expn->right.type; memcpy(&tmp, &(e->left.data.expn->right), sizeof(ExprItem)); free(e->left.data.expn); - memcpy(&(e->left.data.int_val), &tmp, sizeof(ExprItem)); + memcpy(&e->left, &tmp, sizeof(ExprItem)); simplified = 1; } - } else if (e->left.type == EXPR_SYM) { + } +#if 0 + else if (e->left.type == EXPR_SYM) { /* try to get value of symbol */ if (symrec_get_int_value(e->left.data.sym, &int_val, 0)) { e->left.type = EXPR_INT; @@ -166,6 +175,7 @@ expr_simplify(expr *e) simplified = 1; } } +#endif /* ditto on the right */ if (e->right.type == EXPR_EXPR) { @@ -174,14 +184,14 @@ expr_simplify(expr *e) while (e->right.type == EXPR_EXPR && e->right.data.expn->op == EXPR_IDENT) { - ExprItem tmp; - e->right.type = e->right.data.expn->right.type; memcpy(&tmp, &(e->right.data.expn->right), sizeof(ExprItem)); free(e->right.data.expn); - memcpy(&(e->right.data.int_val), &tmp, sizeof(ExprItem)); + memcpy(&e->right, &tmp, sizeof(ExprItem)); simplified = 1; } - } else if (e->right.type == EXPR_SYM) { + } +#if 0 + else if (e->right.type == EXPR_SYM) { if (symrec_get_int_value(e->right.data.sym, &int_val, 0)) { e->right.type = EXPR_INT; /* don't try to free the symrec here. */ @@ -189,139 +199,45 @@ expr_simplify(expr *e) simplified = 1; } } - - if ((e->left.type == EXPR_INT || e->left.type == EXPR_NONE) && - e->right.type == EXPR_INT && e->op != EXPR_IDENT) { - switch (e->op) { - case EXPR_ADD: - e->right.data.int_val = e->left.data.int_val + - e->right.data.int_val; - break; - case EXPR_SUB: - e->right.data.int_val = e->left.data.int_val - - e->right.data.int_val; - break; - case EXPR_MUL: - e->right.data.int_val = e->left.data.int_val * - e->right.data.int_val; - break; - case EXPR_DIV: - e->right.data.int_val = e->left.data.int_val / - e->right.data.int_val; - break; - case EXPR_MOD: - e->right.data.int_val = e->left.data.int_val % - e->right.data.int_val; - break; - case EXPR_NEG: - e->right.data.int_val = -(e->right.data.int_val); - break; - case EXPR_NOT: - e->right.data.int_val = ~(e->right.data.int_val); - break; - case EXPR_OR: - e->right.data.int_val = e->left.data.int_val | - e->right.data.int_val; - break; - case EXPR_AND: - e->right.data.int_val = e->left.data.int_val & - e->right.data.int_val; - break; - case EXPR_XOR: - e->right.data.int_val = e->left.data.int_val ^ - e->right.data.int_val; - break; - case EXPR_SHL: - e->right.data.int_val = e->right.data.int_val << - e->left.data.int_val; - break; - case EXPR_SHR: - e->right.data.int_val = e->right.data.int_val >> - e->left.data.int_val; - break; - case EXPR_LOR: - e->right.data.int_val = e->left.data.int_val || - e->right.data.int_val; - break; - case EXPR_LAND: - e->right.data.int_val = e->left.data.int_val && - e->right.data.int_val; - break; - case EXPR_LNOT: - e->right.data.int_val = !e->right.data.int_val; - break; - case EXPR_EQ: - e->right.data.int_val = e->right.data.int_val == - e->left.data.int_val; - break; - case EXPR_LT: - e->right.data.int_val = e->right.data.int_val < - e->left.data.int_val; - break; - case EXPR_GT: - e->right.data.int_val = e->right.data.int_val > - e->left.data.int_val; - break; - case EXPR_LE: - e->right.data.int_val = e->right.data.int_val <= - e->left.data.int_val; - break; - case EXPR_GE: - e->right.data.int_val = e->right.data.int_val >= - e->left.data.int_val; - break; - case EXPR_NE: - e->right.data.int_val = e->right.data.int_val != - e->left.data.int_val; - break; - case EXPR_IDENT: - break; - } - e->op = EXPR_IDENT; - simplified = 1; - } +#endif /* catch simple identities like 0+x, 1*x, etc., for x not a num */ - else if (e->left.type == EXPR_INT && - ((e->left.data.int_val == 1 && e->op == EXPR_MUL) || - (e->left.data.int_val == 0 && e->op == EXPR_ADD) || - (e->left.data.int_val == -1 && e->op == EXPR_AND) || - (e->left.data.int_val == 0 && e->op == EXPR_OR))) { + if (e->left.type == EXPR_INT && + ((intnum_is_pos1(e->left.data.intn) && e->op == EXPR_MUL) || + (intnum_is_zero(e->left.data.intn) && e->op == EXPR_ADD) || + (intnum_is_neg1(e->left.data.intn) && e->op == EXPR_AND) || + (intnum_is_zero(e->left.data.intn) && e->op == EXPR_OR))) { + intnum_delete(e->left.data.intn); e->op = EXPR_IDENT; simplified = 1; } /* and the corresponding x+|-0, x*&/1 */ else if (e->right.type == EXPR_INT && - ((e->right.data.int_val == 1 && e->op == EXPR_MUL) || - (e->right.data.int_val == 1 && e->op == EXPR_DIV) || - (e->right.data.int_val == 0 && e->op == EXPR_ADD) || - (e->right.data.int_val == 0 && e->op == EXPR_SUB) || - (e->right.data.int_val == -1 && e->op == EXPR_AND) || - (e->right.data.int_val == 0 && e->op == EXPR_OR) || - (e->right.data.int_val == 0 && e->op == EXPR_SHL) || - (e->right.data.int_val == 0 && e->op == EXPR_SHR))) { + ((intnum_is_pos1(e->right.data.intn) && e->op == EXPR_MUL) || + (intnum_is_pos1(e->right.data.intn) && e->op == EXPR_DIV) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_ADD) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SUB) || + (intnum_is_neg1(e->right.data.intn) && e->op == EXPR_AND) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_OR) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SHL) || + (intnum_is_zero(e->right.data.intn) && e->op == EXPR_SHR))) { + intnum_delete(e->right.data.intn); e->op = EXPR_IDENT; e->right.type = e->left.type; memcpy(&e->right, &e->left, sizeof(ExprItem)); simplified = 1; + } else if ((e->left.type == EXPR_INT || e->left.type == EXPR_NONE) && + e->right.type == EXPR_INT && e->op != EXPR_IDENT) { + intnum_calc(e->left.data.intn, e->op, e->right.data.intn); + intnum_delete(e->right.data.intn); + e->right.data.intn = e->left.data.intn; + e->op = EXPR_IDENT; + simplified = 1; } return simplified; } -int -expr_get_value(expr *e, unsigned long *retval) -{ - while (!(e->op == EXPR_IDENT && e->right.type == EXPR_INT) - && expr_simplify(e)) ; - - if (e->op == EXPR_IDENT && e->right.type == EXPR_INT) { - *retval = e->right.data.int_val; - return 1; - } else - return 0; -} - void expr_print(expr *e) { @@ -336,7 +252,7 @@ expr_print(expr *e) printf(")"); break; case EXPR_INT: - printf("%lu", e->left.data.int_val); + intnum_print(e->left.data.intn); break; case EXPR_FLOAT: floatnum_print(e->left.data.flt); @@ -358,9 +274,15 @@ expr_print(expr *e) case EXPR_DIV: printf("/"); break; + case EXPR_SIGNDIV: + printf("//"); + break; case EXPR_MOD: printf("%%"); break; + case EXPR_SIGNMOD: + printf("%%%%"); + break; case EXPR_NEG: printf("-"); break; @@ -422,7 +344,7 @@ expr_print(expr *e) printf(")"); break; case EXPR_INT: - printf("%lu", e->right.data.int_val); + intnum_print(e->right.data.intn); break; case EXPR_FLOAT: floatnum_print(e->right.data.flt); diff --git a/src/expr.h b/src/expr.h index 25a0bb48..8adad2db 100644 --- a/src/expr.h +++ b/src/expr.h @@ -32,12 +32,21 @@ typedef struct symrec symrec; typedef struct floatnum floatnum; #endif +#ifndef YASM_INTNUM +#define YASM_INTNUM +typedef struct intnum intnum; +#endif + +#ifndef YASM_EXPROP +#define YASM_EXPROP typedef enum { EXPR_ADD, EXPR_SUB, EXPR_MUL, EXPR_DIV, + EXPR_SIGNDIV, EXPR_MOD, + EXPR_SIGNMOD, EXPR_NEG, EXPR_NOT, EXPR_OR, @@ -56,6 +65,7 @@ typedef enum { EXPR_NE, EXPR_IDENT /* if right is IDENT, then the entire expr is just a num */ } ExprOp; +#endif typedef struct ExprItem ExprItem; @@ -68,7 +78,7 @@ expr *expr_new(ExprItem *, ExprOp, ExprItem *); ExprItem *ExprSym(symrec *); ExprItem *ExprExpr(expr *); -ExprItem *ExprInt(unsigned long); +ExprItem *ExprInt(intnum *); ExprItem *ExprFloat(floatnum *); #define expr_new_tree(l,o,r) \ @@ -81,7 +91,4 @@ ExprItem *ExprFloat(floatnum *); int expr_simplify(expr *); void expr_print(expr *); -/* get the value if possible. return value is IF POSSIBLE, not the val */ -int expr_get_value(expr *, unsigned long *); - #endif diff --git a/src/floatnum.c b/src/floatnum.c index d2e143ff..30ae7414 100644 --- a/src/floatnum.c +++ b/src/floatnum.c @@ -498,20 +498,28 @@ floatnum_delete(floatnum *flt) free(flt); } +void +floatnum_calc(floatnum *acc, ExprOp op, floatnum *operand) +{ + if (op != EXPR_NEG) + Error(_("Unsupported floating-point arithmetic operation")); + else + acc->sign ^= 1; +} + int floatnum_get_int(unsigned long *ret_val, const floatnum *flt) { unsigned char t[4]; - if (floatnum_get_single(t, flt)) + if (floatnum_get_sized(t, flt, 4)) return 1; LOAD_LONG(*ret_val, &t[0]); return 0; } -/* Function used by single, double, and extended conversion routines to actually - * perform the conversion. +/* Function used by conversion routines to actually perform the conversion. * * ptr -> the array to return the little-endian floating point value into. * flt -> the floating point value to convert. @@ -614,14 +622,8 @@ floatnum_get_common(unsigned char *ptr, const floatnum *flt, int byte_size, * e = bias 127 exponent * s = sign bit * m = mantissa bits, bit 23 is an implied one bit. - */ -int -floatnum_get_single(unsigned char *ptr, const floatnum *flt) -{ - return floatnum_get_common(ptr, flt, 4, 23, 1, 8); -} - -/* IEEE-754 (Intel) "double precision" format: + * + * IEEE-754 (Intel) "double precision" format: * 64 bits: * bit 63 bit 51 bit 0 * | | | @@ -630,14 +632,8 @@ floatnum_get_single(unsigned char *ptr, const floatnum *flt) * e = bias 1023 exponent. * s = sign bit. * m = mantissa bits. Bit 52 is an implied one bit. - */ -int -floatnum_get_double(unsigned char *ptr, const floatnum *flt) -{ - return floatnum_get_common(ptr, flt, 8, 52, 1, 11); -} - -/* IEEE-754 (Intel) "extended precision" format: + * + * IEEE-754 (Intel) "extended precision" format: * 80 bits: * bit 79 bit 63 bit 0 * | | | @@ -648,9 +644,34 @@ floatnum_get_double(unsigned char *ptr, const floatnum *flt) * s = sign (for mantissa) */ int -floatnum_get_extended(unsigned char *ptr, const floatnum *flt) +floatnum_get_sized(unsigned char *ptr, const floatnum *flt, size_t size) { - return floatnum_get_common(ptr, flt, 10, 64, 0, 15); + switch (size) { + case 4: + return floatnum_get_common(ptr, flt, 4, 23, 1, 8); + case 8: + return floatnum_get_common(ptr, flt, 8, 52, 1, 11); + case 10: + return floatnum_get_common(ptr, flt, 10, 64, 0, 15); + default: + InternalError(__LINE__, __FILE__, + _("Invalid float conversion size")); + return 1; /* never reached, but silence GCC warning */ + } +} + +/* 1 if the size is valid, 0 if it isn't */ +int +floatnum_check_size(const floatnum *flt, size_t size) +{ + switch (size) { + case 4: + case 8: + case 10: + return 1; + default: + return 0; + } } void @@ -666,19 +687,19 @@ floatnum_print(const floatnum *flt) free(str); /* 32-bit (single precision) format */ - printf("32-bit: %d: ", floatnum_get_single(out, flt)); + printf("32-bit: %d: ", floatnum_get_sized(out, flt, 4)); for (i=0; i<4; i++) printf("%02x ", out[i]); printf("\n"); /* 64-bit (double precision) format */ - printf("64-bit: %d: ", floatnum_get_double(out, flt)); + printf("64-bit: %d: ", floatnum_get_sized(out, flt, 8)); for (i=0; i<8; i++) printf("%02x ", out[i]); printf("\n"); /* 80-bit (extended precision) format */ - printf("80-bit: %d: ", floatnum_get_extended(out, flt)); + printf("80-bit: %d: ", floatnum_get_sized(out, flt, 10)); for (i=0; i<10; i++) printf("%02x ", out[i]); printf("\n"); diff --git a/src/floatnum.h b/src/floatnum.h index 61292249..4963e79a 100644 --- a/src/floatnum.h +++ b/src/floatnum.h @@ -24,6 +24,36 @@ #ifndef YASM_FLOATNUM_H #define YASM_FLOATNUM_H +#ifndef YASM_EXPROP +#define YASM_EXPROP +typedef enum { + EXPR_ADD, + EXPR_SUB, + EXPR_MUL, + EXPR_DIV, + EXPR_SIGNDIV, + EXPR_MOD, + EXPR_SIGNMOD, + EXPR_NEG, + EXPR_NOT, + EXPR_OR, + EXPR_AND, + EXPR_XOR, + EXPR_SHL, + EXPR_SHR, + EXPR_LOR, + EXPR_LAND, + EXPR_LNOT, + EXPR_LT, + EXPR_GT, + EXPR_EQ, + EXPR_LE, + EXPR_GE, + EXPR_NE, + EXPR_IDENT /* if right is IDENT, then the entire expr is just a num */ +} ExprOp; +#endif + #ifndef YASM_FLOATNUM #define YASM_FLOATNUM typedef struct floatnum floatnum; @@ -32,7 +62,12 @@ typedef struct floatnum floatnum; floatnum *floatnum_new(const char *str); void floatnum_delete(floatnum *flt); -/* The get functions return nonzero if flt can't fit into that size format. */ +/* calculation function: acc = acc op operand */ +void floatnum_calc(floatnum *acc, ExprOp op, floatnum *operand); + +/* The get functions return nonzero if flt can't fit into that size format: + * -1 if underflow occurred, 1 if overflow occurred. + */ /* Essentially a convert to single-precision and return as 32-bit value. * The 32-bit value is a "standard" C value (eg, of unknown endian). @@ -42,9 +77,13 @@ int floatnum_get_int(unsigned long *ret_val, const floatnum *flt); /* ptr will point to the Intel-format little-endian byte string after a * successful call (eg, [0] should be the first byte output to the file). */ -int floatnum_get_single(unsigned char *ptr, const floatnum *flt); -int floatnum_get_double(unsigned char *ptr, const floatnum *flt); -int floatnum_get_extended(unsigned char *ptr, const floatnum *flt); +int floatnum_get_sized(unsigned char *ptr, const floatnum *flt, size_t size); + +/* Basic check to see if size is even valid for flt conversion (doesn't + * actually check for underflow/overflow but rather checks for size=4,8,10). + * Returns 1 if valid, 0 if not. + */ +int floatnum_check_size(const floatnum *flt, size_t size); void floatnum_print(const floatnum *flt); diff --git a/src/intnum.c b/src/intnum.c new file mode 100644 index 00000000..05f5303e --- /dev/null +++ b/src/intnum.c @@ -0,0 +1,542 @@ +/* $IdPath$ + * Integer number functions. + * + * Copyright (C) 2001 Peter Johnson + * + * This file is part of YASM. + * + * YASM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * YASM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "util.h" + +#include +#include + +#ifdef STDC_HEADERS +# include +# include +#endif + +#include +#define _(String) gettext(String) + +#include "bitvect.h" +#include "file.h" + +#include "errwarn.h" +#include "intnum.h" + +RCSID("$IdPath$"); + +#define BITVECT_ALLOC_SIZE 80 + +struct intnum { + union val { + unsigned long ul; /* integer value (for integers <=32 bits) */ + intptr bv; /* bit vector (for integers >32 bits) */ + } val; + enum { INTNUM_UL, INTNUM_BV } type; + unsigned char origsize; /* original (parsed) size, in bits */ +}; + +intnum * +intnum_new_dec(char *str) +{ + intnum *intn = xmalloc(sizeof(intnum)); + wordptr bv; + + intn->origsize = 0; /* no reliable way to figure this out */ + + bv = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + if (BitVector_from_Dec(bv, (unsigned char *)str) == ErrCode_Ovfl) + Warning(_("Numeric constant too large for internal format")); + if (Set_Max(bv) < 32) { + intn->type = INTNUM_UL; + intn->val.ul = BitVector_Chunk_Read(bv, 32, 0); + BitVector_Destroy(bv); + } else { + intn->type = INTNUM_BV; + intn->val.bv = bv; + } + + return intn; +} + +intnum * +intnum_new_bin(char *str) +{ + intnum *intn = xmalloc(sizeof(intnum)); + wordptr bv; + + intn->origsize = strlen(str); + + if(intn->origsize > BITVECT_ALLOC_SIZE) + Warning(_("Numeric constant too large for internal format")); + + bv = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + BitVector_from_Bin(bv, (unsigned char *)str); + if (Set_Max(bv) < 32) { + intn->type = INTNUM_UL; + intn->val.ul = BitVector_Chunk_Read(bv, 32, 0); + BitVector_Destroy(bv); + } else { + intn->type = INTNUM_BV; + intn->val.bv = bv; + } + + return intn; +} + +intnum * +intnum_new_oct(char *str) +{ + intnum *intn = xmalloc(sizeof(intnum)); + wordptr bv; + + intn->origsize = strlen(str)*3; + + if(intn->origsize > BITVECT_ALLOC_SIZE) + Warning(_("Numeric constant too large for internal format")); + + bv = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + BitVector_from_Oct(bv, (unsigned char *)str); + if (Set_Max(bv) < 32) { + intn->type = INTNUM_UL; + intn->val.ul = BitVector_Chunk_Read(bv, 32, 0); + BitVector_Destroy(bv); + } else { + intn->type = INTNUM_BV; + intn->val.bv = bv; + } + + return intn; +} + +intnum * +intnum_new_hex(char *str) +{ + intnum *intn = xmalloc(sizeof(intnum)); + wordptr bv; + + intn->origsize = strlen(str)*4; + + if(intn->origsize > BITVECT_ALLOC_SIZE) + Warning(_("Numeric constant too large for internal format")); + + bv = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + BitVector_from_Hex(bv, (unsigned char *)str); + if (Set_Max(bv) < 32) { + intn->type = INTNUM_UL; + intn->val.ul = BitVector_Chunk_Read(bv, 32, 0); + BitVector_Destroy(bv); + } else { + intn->type = INTNUM_BV; + intn->val.bv = bv; + } + + return intn; +} + +intnum * +intnum_new_charconst_nasm(const char *str) +{ + intnum *intn = xmalloc(sizeof(intnum)); + size_t len = strlen(str); + + if (len > 4) + Warning(_("character constant too large, ignoring trailing characters")); + + intn->val.ul = 0; + intn->type = INTNUM_UL; + intn->origsize = len*8; + + switch (len) { + case 4: + intn->val.ul |= (unsigned long)str[3]; + intn->val.ul <<= 8; + case 3: + intn->val.ul |= (unsigned long)str[2]; + intn->val.ul <<= 8; + case 2: + intn->val.ul |= (unsigned long)str[1]; + intn->val.ul <<= 8; + case 1: + intn->val.ul |= (unsigned long)str[0]; + } + + return intn; +} + +intnum * +intnum_new_int(unsigned long i) +{ + intnum *intn = xmalloc(sizeof(intnum)); + + intn->val.ul = i; + intn->type = INTNUM_UL; + intn->origsize = 0; + + return intn; +} + +void +intnum_delete(intnum *intn) +{ + if (intn->type == INTNUM_BV) + BitVector_Destroy(intn->val.bv); + free(intn); +} + +void +intnum_calc(intnum *acc, ExprOp op, intnum *operand) +{ + wordptr result = (wordptr)NULL, op1 = (wordptr)NULL, op2 = (wordptr)NULL; + wordptr spare; + boolean carry; + + /* upsize to bitvector op if one of two parameters is bitvector already. + * BitVector results must be calculated through intermediate storage. + */ + if (acc->type == INTNUM_BV || (operand && operand->type == INTNUM_BV)) { + result = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + spare = BitVector_Create(BITVECT_ALLOC_SIZE, FALSE); + + if (acc->type == INTNUM_BV) + op1 = acc->val.bv; + else { + op1 = BitVector_Create(BITVECT_ALLOC_SIZE, TRUE); + BitVector_Chunk_Store(op1, 32, 0, acc->val.ul); + } + + if (operand) { + if (operand->type == INTNUM_BV) + op2 = acc->val.bv; + else { + op2 = BitVector_Create(BITVECT_ALLOC_SIZE, TRUE); + BitVector_Chunk_Store(op2, 32, 0, operand->val.ul); + } + } + } + + if (!operand && op != EXPR_NEG && op != EXPR_NOT && op != EXPR_LNOT) + InternalError(__LINE__, __FILE__, _("Operation needs an operand")); + + /* A operation does a bitvector computation if result is allocated. */ + switch (op) { + case EXPR_ADD: + if (result) + BitVector_add(result, op1, op2, &carry); + else + acc->val.ul = acc->val.ul + operand->val.ul; + break; + case EXPR_SUB: + if (result) + BitVector_sub(result, op1, op2, &carry); + else + acc->val.ul = acc->val.ul - operand->val.ul; + break; + case EXPR_MUL: + if (result) + /* TODO: Make sure result size = op1+op2 */ + BitVector_Multiply(result, op1, op2); + else + acc->val.ul = acc->val.ul * operand->val.ul; + break; + case EXPR_DIV: + if (result) { + /* TODO: make sure op1 and op2 are unsigned */ + BitVector_Divide(result, op1, op2, spare); + } else + acc->val.ul = acc->val.ul / operand->val.ul; + break; + case EXPR_SIGNDIV: + if (result) + BitVector_Divide(result, op1, op2, spare); + else + acc->val.ul = (unsigned long)((signed long)acc->val.ul / + (signed long)operand->val.ul); + break; + case EXPR_MOD: + if (result) { + /* TODO: make sure op1 and op2 are unsigned */ + BitVector_Divide(spare, op1, op2, result); + } else + acc->val.ul = acc->val.ul % operand->val.ul; + break; + case EXPR_SIGNMOD: + if (result) + BitVector_Divide(spare, op1, op2, result); + else + acc->val.ul = (unsigned long)((signed long)acc->val.ul % + (signed long)operand->val.ul); + break; + case EXPR_NEG: + if (result) + BitVector_Negate(result, op1); + else + acc->val.ul = -(acc->val.ul); + break; + case EXPR_NOT: + if (result) + Set_Complement(result, op1); + else + acc->val.ul = ~(acc->val.ul); + break; + case EXPR_OR: + if (result) + Set_Union(result, op1, op2); + else + acc->val.ul = acc->val.ul | operand->val.ul; + break; + case EXPR_AND: + if (result) + Set_Intersection(result, op1, op2); + else + acc->val.ul = acc->val.ul & operand->val.ul; + break; + case EXPR_XOR: + if (result) + Set_ExclusiveOr(result, op1, op2); + else + acc->val.ul = acc->val.ul ^ operand->val.ul; + break; + case EXPR_SHL: + if (result) { + if (operand->type == INTNUM_UL) { + BitVector_Copy(result, op1); + BitVector_Move_Left(result, operand->val.ul); + } else /* don't even bother, just zero result */ + BitVector_Empty(result); + } else + acc->val.ul = acc->val.ul << operand->val.ul; + break; + case EXPR_SHR: + if (result) { + if (operand->type == INTNUM_UL) { + BitVector_Copy(result, op1); + BitVector_Move_Right(result, operand->val.ul); + } else /* don't even bother, just zero result */ + BitVector_Empty(result); + } else + acc->val.ul = acc->val.ul >> operand->val.ul; + break; + case EXPR_LOR: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, !BitVector_is_empty(op1) || + !BitVector_is_empty(op2)); + } else + acc->val.ul = acc->val.ul || operand->val.ul; + break; + case EXPR_LAND: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, !BitVector_is_empty(op1) && + !BitVector_is_empty(op2)); + } else + acc->val.ul = acc->val.ul && operand->val.ul; + break; + case EXPR_LNOT: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, BitVector_is_empty(op1)); + } else + acc->val.ul = !acc->val.ul; + break; + case EXPR_EQ: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, BitVector_equal(op1, op2)); + } else + acc->val.ul = acc->val.ul == operand->val.ul; + break; + case EXPR_LT: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, BitVector_Lexicompare(op1, op2) < 0); + } else + acc->val.ul = acc->val.ul < operand->val.ul; + break; + case EXPR_GT: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, BitVector_Lexicompare(op1, op2) > 0); + } else + acc->val.ul = acc->val.ul > operand->val.ul; + break; + case EXPR_LE: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, BitVector_Lexicompare(op1, op2) <= 0); + } else + acc->val.ul = acc->val.ul <= operand->val.ul; + break; + case EXPR_GE: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, BitVector_Lexicompare(op1, op2) >= 0); + } else + acc->val.ul = acc->val.ul >= operand->val.ul; + break; + case EXPR_NE: + if (result) { + BitVector_Empty(result); + BitVector_LSB(result, !BitVector_equal(op1, op2)); + } else + acc->val.ul = acc->val.ul != operand->val.ul; + break; + case EXPR_IDENT: + if (result) + BitVector_Copy(result, op1); + break; + } + + /* If we were doing a bitvector computation... */ + if (result) { + BitVector_Destroy(spare); + + if (op1 && acc->type != INTNUM_BV) + BitVector_Destroy(op1); + if (op2 && operand && operand->type != INTNUM_BV) + BitVector_Destroy(op2); + + /* Try to fit the result into 32 bits if possible */ + if (Set_Max(result) < 32) { + if (acc->type == INTNUM_BV) { + BitVector_Destroy(acc->val.bv); + acc->type = INTNUM_UL; + } + acc->val.ul = BitVector_Chunk_Read(result, 32, 0); + BitVector_Destroy(result); + } else { + if (acc->type == INTNUM_BV) { + BitVector_Copy(acc->val.bv, result); + BitVector_Destroy(result); + } else { + acc->type = INTNUM_BV; + acc->val.bv = result; + } + } + } +} + +int +intnum_is_zero(intnum *intn) +{ + return ((intn->type == INTNUM_UL && intn->val.ul == 0) || + (intn->type == INTNUM_BV && BitVector_is_empty(intn->val.bv))); +} + +int +intnum_is_pos1(intnum *intn) +{ + return ((intn->type == INTNUM_UL && intn->val.ul == 1) || + (intn->type == INTNUM_BV && Set_Max(intn->val.bv) == 0)); +} + +int +intnum_is_neg1(intnum *intn) +{ + return ((intn->type == INTNUM_UL && intn->val.ul == -1) || + (intn->type == INTNUM_BV && BitVector_is_full(intn->val.bv))); +} + +void +intnum_get_int(unsigned long *ret_val, const intnum *intn) +{ + switch (intn->type) { + case INTNUM_UL: + *ret_val = intn->val.ul; + break; + case INTNUM_BV: + *ret_val = BitVector_Chunk_Read(intn->val.bv, 32, 0); + break; + } +} + +void +intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size) +{ + unsigned long ul; + unsigned char *buf; + unsigned int len; + + switch (intn->type) { + case INTNUM_UL: + ul = intn->val.ul; + while (size-- > 0) { + WRITE_BYTE(ptr, ul); + if (ul != 0) + ul >>= 8; + } + break; + case INTNUM_BV: + buf = BitVector_Block_Read(intn->val.bv, &len); + if (len < size) + InternalError(__LINE__, __FILE__, + _("Invalid size specified (too large)")); + memcpy(ptr, buf, size); + free(buf); + break; + } +} + +/* Return 1 if okay size, 0 if not */ +int +intnum_check_size(const intnum *intn, size_t size) +{ + switch (intn->type) { + case INTNUM_UL: + if (size >= 4) + return 1; + switch (size) { + case 3: + return ((intn->val.ul & 0x00FFFFFF) == intn->val.ul); + case 2: + return ((intn->val.ul & 0x0000FFFF) == intn->val.ul); + case 1: + return ((intn->val.ul & 0x000000FF) == intn->val.ul); + } + break; + case INTNUM_BV: + if (size >= 10) + return 1; + else + return (Set_Max(intn->val.bv) < size*8); + break; + } + return 0; +} + +void +intnum_print(const intnum *intn) +{ + unsigned char *s; + + switch (intn->type) { + case INTNUM_UL: + printf("0x%lx/%u", intn->val.ul, (unsigned int)intn->origsize); + break; + case INTNUM_BV: + s = BitVector_to_Hex(intn->val.bv); + printf("0x%s/%u", s, (unsigned int)intn->origsize); + free(s); + break; + } +} diff --git a/src/intnum.h b/src/intnum.h new file mode 100644 index 00000000..62fe9e27 --- /dev/null +++ b/src/intnum.h @@ -0,0 +1,96 @@ +/* $IdPath$ + * Integer number functions header file. + * + * Copyright (C) 2001 Peter Johnson + * + * This file is part of YASM. + * + * YASM is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * YASM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef YASM_INTNUM_H +#define YASM_INTNUM_H + +#ifndef YASM_EXPROP +#define YASM_EXPROP +typedef enum { + EXPR_ADD, + EXPR_SUB, + EXPR_MUL, + EXPR_DIV, + EXPR_SIGNDIV, + EXPR_MOD, + EXPR_SIGNMOD, + EXPR_NEG, + EXPR_NOT, + EXPR_OR, + EXPR_AND, + EXPR_XOR, + EXPR_SHL, + EXPR_SHR, + EXPR_LOR, + EXPR_LAND, + EXPR_LNOT, + EXPR_LT, + EXPR_GT, + EXPR_EQ, + EXPR_LE, + EXPR_GE, + EXPR_NE, + EXPR_IDENT /* if right is IDENT, then the entire expr is just a num */ +} ExprOp; +#endif + +#ifndef YASM_INTNUM +#define YASM_INTNUM +typedef struct intnum intnum; +#endif + +intnum *intnum_new_dec(char *str); +intnum *intnum_new_bin(char *str); +intnum *intnum_new_oct(char *str); +intnum *intnum_new_hex(char *str); +/* convert character constant to integer value, using NASM rules */ +intnum *intnum_new_charconst_nasm(const char *str); +intnum *intnum_new_int(unsigned long i); +void intnum_delete(intnum *intn); + +/* calculation function: acc = acc op operand */ +void intnum_calc(intnum *acc, ExprOp op, intnum *operand); + +/* simple value checks (for catching identities and the like) */ +int intnum_is_zero(intnum *acc); +int intnum_is_pos1(intnum *acc); +int intnum_is_neg1(intnum *acc); + +/* The get functions truncate intn to the size specified; they don't check + * for overflow. Use intnum_check_size() to check for overflow. + */ + +/* Return a 32-bit value in "standard" C format (eg, of unknown endian). */ +void intnum_get_int(unsigned long *ret_val, const intnum *intn); + +/* ptr will point to the Intel-format little-endian byte string after + * call (eg, [0] should be the first byte output to the file). + */ +void intnum_get_sized(unsigned char *ptr, const intnum *intn, size_t size); + +/* Check to see if intn will fit without overflow in size bytes. + * Returns 1 if it will, 0 if not. + */ +int intnum_check_size(const intnum *intn, size_t size); + +void intnum_print(const intnum *intn); + +#endif diff --git a/src/main.c b/src/main.c index 8e1e6b1f..6cad2ab2 100644 --- a/src/main.c +++ b/src/main.c @@ -45,6 +45,7 @@ #include "globals.h" #include "options.h" #include "errwarn.h" +#include "symrec.h" #include "bytecode.h" #include "section.h" @@ -99,6 +100,8 @@ char help_tail[] = "\n" int main(int argc, char *argv[]) { + sectionhead *sections; + if (parse_cmdline(argc, argv, options, countof(options, opt_option))) return EXIT_FAILURE; @@ -123,11 +126,15 @@ main(int argc, char *argv[]) /* Get initial BITS setting from object format */ mode_bits = dbg_objfmt.default_mode_bits; - nasm_parser.do_parse(&nasm_parser, &dbg_objfmt, in); + sections = nasm_parser.do_parse(&nasm_parser, &dbg_objfmt, in); if (OutputAllErrorWarning() > 0) return EXIT_FAILURE; + sections_print(sections); + printf("\n***Symbol Table***\n"); + symrec_foreach((int (*) (symrec *))symrec_print); + if (in_filename) free(in_filename); return EXIT_SUCCESS; diff --git a/src/parsers/nasm/bison.y.in b/src/parsers/nasm/bison.y.in index c69c2e66..e44fcf45 100644 --- a/src/parsers/nasm/bison.y.in +++ b/src/parsers/nasm/bison.y.in @@ -35,8 +35,11 @@ #include #define _(String) gettext(String) +#include "bitvect.h" + #include "globals.h" #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -51,7 +54,6 @@ RCSID("$IdPath$"); void init_table(void); extern int nasm_parser_lex(void); -static unsigned long ConvertCharConstToInt(char *); void nasm_parser_error(const char *); extern objfmt *nasm_parser_objfmt; @@ -65,9 +67,11 @@ static bytecode *nasm_parser_temp_bc; %} %union { - unsigned long int_val; + unsigned int int_info; char *str_val; + intnum *intn; floatnum *flt; + symrec *sym; unsigned char groupdata[4]; effaddr *ea; expr *exp; @@ -78,23 +82,24 @@ static bytecode *nasm_parser_temp_bc; bytecode *bc; } -%token INTNUM +%token INTNUM %token FLTNUM %token DIRECTIVE_NAME DIRECTIVE_VAL STRING -%token BYTE WORD DWORD QWORD TWORD DQWORD -%token DECLARE_DATA -%token RESERVE_SPACE +%token BYTE WORD DWORD QWORD TWORD DQWORD +%token DECLARE_DATA +%token RESERVE_SPACE %token INCBIN EQU TIMES %token SEG WRT NEAR SHORT FAR NOSPLIT ORG %token TO %token O16 O32 A16 A32 LOCK REPNZ REP REPZ -%token OPERSIZE ADDRSIZE -%token CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG -%token REG_EAX REG_ECX REG_EDX REG_EBX REG_ESP REG_EBP REG_ESI REG_EDI -%token REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI -%token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH -%token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS -%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD +%token OPERSIZE ADDRSIZE +%token CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG +%token REG_EAX REG_ECX REG_EDX REG_EBX +%token REG_ESP REG_EBP REG_ESI REG_EDI +%token REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI +%token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH +%token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS +%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD START_SECTION_ID %token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ @@ -102,9 +107,9 @@ static bytecode *nasm_parser_temp_bc; /* @TYPES@ */ -%type line exp instr instrbase label +%type line exp instr instrbase -%type fpureg reg32 reg16 reg8 segreg +%type fpureg reg32 reg16 reg8 segreg %type mem memaddr memexp memfar %type mem8x mem16x mem32x mem64x mem80x mem128x %type mem8 mem16 mem32 mem64 mem80 mem128 mem1632 @@ -112,7 +117,8 @@ static bytecode *nasm_parser_temp_bc; %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 %type expr expr_no_string -%type explabel label_id +%type explabel +%type label_id %type target %type dataval %type datavals @@ -164,7 +170,6 @@ datavals: dataval { ; dataval: expr_no_string { $$ = dataval_new_expr($1); } - | FLTNUM { $$ = dataval_new_float($1); } | STRING { $$ = dataval_new_string($1); } | error { Error(_("expression syntax error")); @@ -173,10 +178,12 @@ dataval: expr_no_string { $$ = dataval_new_expr($1); } ; label: label_id { - symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc, + 1); } | label_id ':' { - symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc, + 1); } ; @@ -194,6 +201,8 @@ directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' { nasm_parser_cur_section = sections_switch(&nasm_parser_sections, nasm_parser_objfmt, $3); nasm_parser_prev_bc = (bytecode *)NULL; + symrec_define_label($3, nasm_parser_cur_section, (bytecode *)NULL, + 1); } else { printf("Directive: Name='%s' Value='%s'\n", $2, $3); } @@ -254,7 +263,7 @@ segreg: REG_ES ; /* memory addresses */ -memexp: expr { expr_simplify ($1); $$ = effaddr_new_expr($1); } +memexp: expr { $$ = effaddr_new_expr($1); } ; memaddr: memexp { $$ = $1; SetEASegment($$, 0); } @@ -353,7 +362,7 @@ rm128: XMMREG { $$ = effaddr_new_reg($1); } ; /* immediate values */ -imm: expr { expr_simplify($1); $$ = immval_new_expr($1); } +imm: expr { $$ = immval_new_expr($1); } ; /* explicit immediates */ @@ -383,7 +392,8 @@ target: expr { $$.val = $1; SetOpcodeSel(&$$.op_sel, JR_NONE); } /* expression trees */ expr_no_string: INTNUM { $$ = expr_new_ident(ExprInt($1)); } - | explabel { $$ = expr_new_ident(ExprSym(symrec_use($1))); } + | FLTNUM { $$ = expr_new_ident(ExprFloat($1)); } + | explabel { $$ = expr_new_ident(ExprSym($1)); } /*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); } | expr '^' expr { $$ = expr_new_tree($1, EXPR_XOR, $3); } @@ -401,7 +411,9 @@ expr_no_string: INTNUM { $$ = expr_new_ident(ExprInt($1)); } | expr '-' expr { $$ = expr_new_tree($1, EXPR_SUB, $3); } | expr '*' expr { $$ = expr_new_tree($1, EXPR_MUL, $3); } | expr '/' expr { $$ = expr_new_tree($1, EXPR_DIV, $3); } + | expr SIGNDIV expr { $$ = expr_new_tree($1, EXPR_SIGNDIV, $3); } | expr '%' expr { $$ = expr_new_tree($1, EXPR_MOD, $3); } + | expr SIGNMOD expr { $$ = expr_new_tree($1, EXPR_SIGNMOD, $3); } | '+' expr %prec UNARYOP { $$ = $2; } | '-' expr %prec UNARYOP { $$ = expr_new_branch(EXPR_NEG, $2); } /*| '!' expr { $$ = expr_new_branch(EXPR_LNOT, $2); }*/ @@ -411,13 +423,20 @@ expr_no_string: INTNUM { $$ = expr_new_ident(ExprInt($1)); } expr: expr_no_string | STRING { - $$ = expr_new_ident(ExprInt(ConvertCharConstToInt($1))); + $$ = expr_new_ident(ExprInt(intnum_new_charconst_nasm($1))); } ; -explabel: ID - | SPECIAL_ID - | LOCAL_ID +explabel: ID { $$ = symrec_use($1); } + | SPECIAL_ID { $$ = symrec_use($1); } + | LOCAL_ID { $$ = symrec_use($1); } + | '$' { + $$ = symrec_define_label("$", nasm_parser_cur_section, + nasm_parser_prev_bc, 0); + } + | START_SECTION_ID { + $$ = symrec_use(section_get_name(nasm_parser_cur_section)); + } ; instr: instrbase @@ -440,32 +459,6 @@ instr: instrbase %% -static unsigned long -ConvertCharConstToInt(char *cc) -{ - unsigned long retval = 0; - size_t len = strlen(cc); - - if (len > 4) - Warning(_("character constant too large, ignoring trailing characters")); - - switch (len) { - case 4: - retval |= (unsigned long)cc[3]; - retval <<= 8; - case 3: - retval |= (unsigned long)cc[2]; - retval <<= 8; - case 2: - retval |= (unsigned long)cc[1]; - retval <<= 8; - case 1: - retval |= (unsigned long)cc[0]; - } - - return retval; -} - void nasm_parser_error(const char *s) { diff --git a/src/parsers/nasm/nasm-bison.y b/src/parsers/nasm/nasm-bison.y index c69c2e66..e44fcf45 100644 --- a/src/parsers/nasm/nasm-bison.y +++ b/src/parsers/nasm/nasm-bison.y @@ -35,8 +35,11 @@ #include #define _(String) gettext(String) +#include "bitvect.h" + #include "globals.h" #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -51,7 +54,6 @@ RCSID("$IdPath$"); void init_table(void); extern int nasm_parser_lex(void); -static unsigned long ConvertCharConstToInt(char *); void nasm_parser_error(const char *); extern objfmt *nasm_parser_objfmt; @@ -65,9 +67,11 @@ static bytecode *nasm_parser_temp_bc; %} %union { - unsigned long int_val; + unsigned int int_info; char *str_val; + intnum *intn; floatnum *flt; + symrec *sym; unsigned char groupdata[4]; effaddr *ea; expr *exp; @@ -78,23 +82,24 @@ static bytecode *nasm_parser_temp_bc; bytecode *bc; } -%token INTNUM +%token INTNUM %token FLTNUM %token DIRECTIVE_NAME DIRECTIVE_VAL STRING -%token BYTE WORD DWORD QWORD TWORD DQWORD -%token DECLARE_DATA -%token RESERVE_SPACE +%token BYTE WORD DWORD QWORD TWORD DQWORD +%token DECLARE_DATA +%token RESERVE_SPACE %token INCBIN EQU TIMES %token SEG WRT NEAR SHORT FAR NOSPLIT ORG %token TO %token O16 O32 A16 A32 LOCK REPNZ REP REPZ -%token OPERSIZE ADDRSIZE -%token CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG -%token REG_EAX REG_ECX REG_EDX REG_EBX REG_ESP REG_EBP REG_ESI REG_EDI -%token REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI -%token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH -%token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS -%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD +%token OPERSIZE ADDRSIZE +%token CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG +%token REG_EAX REG_ECX REG_EDX REG_EBX +%token REG_ESP REG_EBP REG_ESI REG_EDI +%token REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI +%token REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH +%token REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS +%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD START_SECTION_ID %token ID LOCAL_ID SPECIAL_ID /* instruction tokens (dynamically generated) */ @@ -102,9 +107,9 @@ static bytecode *nasm_parser_temp_bc; /* @TYPES@ */ -%type line exp instr instrbase label +%type line exp instr instrbase -%type fpureg reg32 reg16 reg8 segreg +%type fpureg reg32 reg16 reg8 segreg %type mem memaddr memexp memfar %type mem8x mem16x mem32x mem64x mem80x mem128x %type mem8 mem16 mem32 mem64 mem80 mem128 mem1632 @@ -112,7 +117,8 @@ static bytecode *nasm_parser_temp_bc; %type rm8 rm16 rm32 rm64 rm128 %type imm imm8x imm16x imm32x imm8 imm16 imm32 %type expr expr_no_string -%type explabel label_id +%type explabel +%type label_id %type target %type dataval %type datavals @@ -164,7 +170,6 @@ datavals: dataval { ; dataval: expr_no_string { $$ = dataval_new_expr($1); } - | FLTNUM { $$ = dataval_new_float($1); } | STRING { $$ = dataval_new_string($1); } | error { Error(_("expression syntax error")); @@ -173,10 +178,12 @@ dataval: expr_no_string { $$ = dataval_new_expr($1); } ; label: label_id { - symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc, + 1); } | label_id ':' { - symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc); + symrec_define_label($1, nasm_parser_cur_section, nasm_parser_prev_bc, + 1); } ; @@ -194,6 +201,8 @@ directive: '[' DIRECTIVE_NAME DIRECTIVE_VAL ']' { nasm_parser_cur_section = sections_switch(&nasm_parser_sections, nasm_parser_objfmt, $3); nasm_parser_prev_bc = (bytecode *)NULL; + symrec_define_label($3, nasm_parser_cur_section, (bytecode *)NULL, + 1); } else { printf("Directive: Name='%s' Value='%s'\n", $2, $3); } @@ -254,7 +263,7 @@ segreg: REG_ES ; /* memory addresses */ -memexp: expr { expr_simplify ($1); $$ = effaddr_new_expr($1); } +memexp: expr { $$ = effaddr_new_expr($1); } ; memaddr: memexp { $$ = $1; SetEASegment($$, 0); } @@ -353,7 +362,7 @@ rm128: XMMREG { $$ = effaddr_new_reg($1); } ; /* immediate values */ -imm: expr { expr_simplify($1); $$ = immval_new_expr($1); } +imm: expr { $$ = immval_new_expr($1); } ; /* explicit immediates */ @@ -383,7 +392,8 @@ target: expr { $$.val = $1; SetOpcodeSel(&$$.op_sel, JR_NONE); } /* expression trees */ expr_no_string: INTNUM { $$ = expr_new_ident(ExprInt($1)); } - | explabel { $$ = expr_new_ident(ExprSym(symrec_use($1))); } + | FLTNUM { $$ = expr_new_ident(ExprFloat($1)); } + | explabel { $$ = expr_new_ident(ExprSym($1)); } /*| expr '||' expr { $$ = expr_new_tree($1, EXPR_LOR, $3); }*/ | expr '|' expr { $$ = expr_new_tree($1, EXPR_OR, $3); } | expr '^' expr { $$ = expr_new_tree($1, EXPR_XOR, $3); } @@ -401,7 +411,9 @@ expr_no_string: INTNUM { $$ = expr_new_ident(ExprInt($1)); } | expr '-' expr { $$ = expr_new_tree($1, EXPR_SUB, $3); } | expr '*' expr { $$ = expr_new_tree($1, EXPR_MUL, $3); } | expr '/' expr { $$ = expr_new_tree($1, EXPR_DIV, $3); } + | expr SIGNDIV expr { $$ = expr_new_tree($1, EXPR_SIGNDIV, $3); } | expr '%' expr { $$ = expr_new_tree($1, EXPR_MOD, $3); } + | expr SIGNMOD expr { $$ = expr_new_tree($1, EXPR_SIGNMOD, $3); } | '+' expr %prec UNARYOP { $$ = $2; } | '-' expr %prec UNARYOP { $$ = expr_new_branch(EXPR_NEG, $2); } /*| '!' expr { $$ = expr_new_branch(EXPR_LNOT, $2); }*/ @@ -411,13 +423,20 @@ expr_no_string: INTNUM { $$ = expr_new_ident(ExprInt($1)); } expr: expr_no_string | STRING { - $$ = expr_new_ident(ExprInt(ConvertCharConstToInt($1))); + $$ = expr_new_ident(ExprInt(intnum_new_charconst_nasm($1))); } ; -explabel: ID - | SPECIAL_ID - | LOCAL_ID +explabel: ID { $$ = symrec_use($1); } + | SPECIAL_ID { $$ = symrec_use($1); } + | LOCAL_ID { $$ = symrec_use($1); } + | '$' { + $$ = symrec_define_label("$", nasm_parser_cur_section, + nasm_parser_prev_bc, 0); + } + | START_SECTION_ID { + $$ = symrec_use(section_get_name(nasm_parser_cur_section)); + } ; instr: instrbase @@ -440,32 +459,6 @@ instr: instrbase %% -static unsigned long -ConvertCharConstToInt(char *cc) -{ - unsigned long retval = 0; - size_t len = strlen(cc); - - if (len > 4) - Warning(_("character constant too large, ignoring trailing characters")); - - switch (len) { - case 4: - retval |= (unsigned long)cc[3]; - retval <<= 8; - case 3: - retval |= (unsigned long)cc[2]; - retval <<= 8; - case 2: - retval |= (unsigned long)cc[1]; - retval <<= 8; - case 1: - retval |= (unsigned long)cc[0]; - } - - return retval; -} - void nasm_parser_error(const char *s) { diff --git a/src/parsers/nasm/token.l.in b/src/parsers/nasm/token.l.in index 5329e1b4..17c4a996 100644 --- a/src/parsers/nasm/token.l.in +++ b/src/parsers/nasm/token.l.in @@ -34,7 +34,10 @@ #include #define _(String) gettext(String) +#include "bitvect.h" + #include "errwarn.h" +#include "intnum.h" #include "floatnum.h" #include "expr.h" #include "symrec.h" @@ -87,31 +90,37 @@ WS [ \t\r] /* standard decimal integer */ {DIGIT}+ { - yylval.int_val = strtoul(yytext, (char **)NULL, 10); + yylval.intn = intnum_new_dec(yytext); return INTNUM; } /* 10010011b - binary number */ {BINDIGIT}+b { - yylval.int_val = strtoul(yytext, (char **)NULL, 2); + yytext[strlen(yytext)] = '\0'; /* strip off 'b' */ + yylval.intn = intnum_new_bin(yytext); return INTNUM; } /* 777q - octal number */ {OCTDIGIT}+q { - yylval.int_val = strtoul(yytext, (char **)NULL, 8); + yytext[strlen(yytext)] = '\0'; /* strip off 'q' */ + yylval.intn = intnum_new_oct(yytext); return INTNUM; } /* 0AAh form of hexidecimal number */ 0{HEXDIGIT}+h { - yylval.int_val = strtoul(yytext+1, (char **)NULL, 16); + yytext[strlen(yytext)] = '\0'; /* strip off 'h' */ + yylval.intn = intnum_new_hex(yytext); return INTNUM; } /* $0AA and 0xAA forms of hexidecimal number */ (\$0|0x){HEXDIGIT}+ { - yylval.int_val = strtoul(yytext+2, (char **)NULL, 16); + if (yytext[1] == 'x') + yylval.intn = intnum_new_hex(yytext+2); /* 0x format, skip 0 and x */ + else + yylval.intn = intnum_new_hex(yytext+1); /* $0 format, don't skip 0 */ return INTNUM; } @@ -182,25 +191,25 @@ WS [ \t\r] } /* size specifiers */ -byte { yylval.int_val = 1; return BYTE; } -word { yylval.int_val = 2; return WORD; } -dword { yylval.int_val = 4; return DWORD; } -qword { yylval.int_val = 8; return QWORD; } -tword { yylval.int_val = 10; return TWORD; } -dqword { yylval.int_val = 16; return DQWORD; } +byte { yylval.int_info = 1; return BYTE; } +word { yylval.int_info = 2; return WORD; } +dword { yylval.int_info = 4; return DWORD; } +qword { yylval.int_info = 8; return QWORD; } +tword { yylval.int_info = 10; return TWORD; } +dqword { yylval.int_info = 16; return DQWORD; } /* pseudo-instructions */ -db { yylval.int_val = 1; return DECLARE_DATA; } -dw { yylval.int_val = 2; return DECLARE_DATA; } -dd { yylval.int_val = 4; return DECLARE_DATA; } -dq { yylval.int_val = 8; return DECLARE_DATA; } -dt { yylval.int_val = 10; return DECLARE_DATA; } - -resb { yylval.int_val = 1; return RESERVE_SPACE; } -resw { yylval.int_val = 2; return RESERVE_SPACE; } -resd { yylval.int_val = 4; return RESERVE_SPACE; } -resq { yylval.int_val = 8; return RESERVE_SPACE; } -rest { yylval.int_val = 10; return RESERVE_SPACE; } +db { yylval.int_info = 1; return DECLARE_DATA; } +dw { yylval.int_info = 2; return DECLARE_DATA; } +dd { yylval.int_info = 4; return DECLARE_DATA; } +dq { yylval.int_info = 8; return DECLARE_DATA; } +dt { yylval.int_info = 10; return DECLARE_DATA; } + +resb { yylval.int_info = 1; return RESERVE_SPACE; } +resw { yylval.int_info = 2; return RESERVE_SPACE; } +resd { yylval.int_info = 4; return RESERVE_SPACE; } +resq { yylval.int_info = 8; return RESERVE_SPACE; } +rest { yylval.int_info = 10; return RESERVE_SPACE; } incbin { return INCBIN; } @@ -221,11 +230,11 @@ org { return ORG; } to { return TO; } /* operand size overrides */ -o16 { yylval.int_val = 16; return OPERSIZE; } -o32 { yylval.int_val = 32; return OPERSIZE; } +o16 { yylval.int_info = 16; return OPERSIZE; } +o32 { yylval.int_info = 32; return OPERSIZE; } /* address size overrides */ -a16 { yylval.int_val = 16; return ADDRSIZE; } -a32 { yylval.int_val = 32; return ADDRSIZE; } +a16 { yylval.int_info = 16; return ADDRSIZE; } +a32 { yylval.int_info = 32; return ADDRSIZE; } /* instruction prefixes */ lock { return LOCK; } @@ -236,62 +245,63 @@ repe { return REPZ; } repz { return REPZ; } /* control, debug, and test registers */ -cr4 { yylval.int_val = 4; return CR4; } -cr[023] { yylval.int_val = yytext[2]-'0'; return CRREG_NOTCR4; } -dr[0-367] { yylval.int_val = yytext[2]-'0'; return DRREG; } -tr[3-7] { yylval.int_val = yytext[2]-'0'; return TRREG; } +cr4 { yylval.int_info = 4; return CR4; } +cr[023] { yylval.int_info = yytext[2]-'0'; return CRREG_NOTCR4; } +dr[0-367] { yylval.int_info = yytext[2]-'0'; return DRREG; } +tr[3-7] { yylval.int_info = yytext[2]-'0'; return TRREG; } /* floating point, MMX, and SSE registers */ -st0 { yylval.int_val = 0; return ST0; } -st[1-7] { yylval.int_val = yytext[2]-'0'; return FPUREG_NOTST0; } -mm[0-7] { yylval.int_val = yytext[2]-'0'; return MMXREG; } -xmm[0-7] { yylval.int_val = yytext[3]-'0'; return XMMREG; } +st0 { yylval.int_info = 0; return ST0; } +st[1-7] { yylval.int_info = yytext[2]-'0'; return FPUREG_NOTST0; } +mm[0-7] { yylval.int_info = yytext[2]-'0'; return MMXREG; } +xmm[0-7] { yylval.int_info = yytext[3]-'0'; return XMMREG; } /* integer registers */ -eax { yylval.int_val = 0; return REG_EAX; } -ecx { yylval.int_val = 1; return REG_ECX; } -edx { yylval.int_val = 2; return REG_EDX; } -ebx { yylval.int_val = 3; return REG_EBX; } -esp { yylval.int_val = 4; return REG_ESP; } -ebp { yylval.int_val = 5; return REG_EBP; } -esi { yylval.int_val = 6; return REG_ESI; } -edi { yylval.int_val = 7; return REG_EDI; } - -ax { yylval.int_val = 0; return REG_AX; } -cx { yylval.int_val = 1; return REG_CX; } -dx { yylval.int_val = 2; return REG_DX; } -bx { yylval.int_val = 3; return REG_BX; } -sp { yylval.int_val = 4; return REG_SP; } -bp { yylval.int_val = 5; return REG_BP; } -si { yylval.int_val = 6; return REG_SI; } -di { yylval.int_val = 7; return REG_DI; } - -al { yylval.int_val = 0; return REG_AL; } -cl { yylval.int_val = 1; return REG_CL; } -dl { yylval.int_val = 2; return REG_DL; } -bl { yylval.int_val = 3; return REG_BL; } -ah { yylval.int_val = 4; return REG_AH; } -ch { yylval.int_val = 5; return REG_CH; } -dh { yylval.int_val = 6; return REG_DH; } -bh { yylval.int_val = 7; return REG_BH; } +eax { yylval.int_info = 0; return REG_EAX; } +ecx { yylval.int_info = 1; return REG_ECX; } +edx { yylval.int_info = 2; return REG_EDX; } +ebx { yylval.int_info = 3; return REG_EBX; } +esp { yylval.int_info = 4; return REG_ESP; } +ebp { yylval.int_info = 5; return REG_EBP; } +esi { yylval.int_info = 6; return REG_ESI; } +edi { yylval.int_info = 7; return REG_EDI; } + +ax { yylval.int_info = 0; return REG_AX; } +cx { yylval.int_info = 1; return REG_CX; } +dx { yylval.int_info = 2; return REG_DX; } +bx { yylval.int_info = 3; return REG_BX; } +sp { yylval.int_info = 4; return REG_SP; } +bp { yylval.int_info = 5; return REG_BP; } +si { yylval.int_info = 6; return REG_SI; } +di { yylval.int_info = 7; return REG_DI; } + +al { yylval.int_info = 0; return REG_AL; } +cl { yylval.int_info = 1; return REG_CL; } +dl { yylval.int_info = 2; return REG_DL; } +bl { yylval.int_info = 3; return REG_BL; } +ah { yylval.int_info = 4; return REG_AH; } +ch { yylval.int_info = 5; return REG_CH; } +dh { yylval.int_info = 6; return REG_DH; } +bh { yylval.int_info = 7; return REG_BH; } /* segment registers */ -es { yylval.int_val = 0; return REG_ES; } -cs { yylval.int_val = 1; return REG_CS; } -ss { yylval.int_val = 2; return REG_SS; } -ds { yylval.int_val = 3; return REG_DS; } -fs { yylval.int_val = 4; return REG_FS; } -gs { yylval.int_val = 5; return REG_GS; } +es { yylval.int_info = 0; return REG_ES; } +cs { yylval.int_info = 1; return REG_CS; } +ss { yylval.int_info = 2; return REG_SS; } +ds { yylval.int_info = 3; return REG_DS; } +fs { yylval.int_info = 4; return REG_FS; } +gs { yylval.int_info = 5; return REG_GS; } /* operators */ "<<" { return LEFT_OP; } ">>" { return RIGHT_OP; } "//" { return SIGNDIV; } "%%" { return SIGNMOD; } -[-+|^&*/%~():[\],] { return yytext[0]; } +"$$" { return START_SECTION_ID; } +[-+|^&*/%~$():[\],] { return yytext[0]; } /* special non-local ..@label and labels like ..start */ -$$|$|\.\.[a-z0-9_$#@~.?]+ { +\.\.[a-z0-9_$#@~.?]+ { yylval.str_val = xstrdup(yytext); return SPECIAL_ID; } diff --git a/src/section.c b/src/section.c index e655a5c2..d9db4be3 100644 --- a/src/section.c +++ b/src/section.c @@ -124,8 +124,42 @@ sections_switch(sectionhead *headp, objfmt *of, const char *name) return s; } +void +sections_print(sectionhead *headp) +{ + section *cur; + + STAILQ_FOREACH(cur, headp, link) + section_print(cur); +} + bytecodehead * section_get_bytecodes(section *sect) { return §->bc; } + +const char * +section_get_name(const section *sect) +{ + return sect->name; +} + +void +section_print(const section *sect) +{ + printf("***SECTION %s***\n", sect->name); + printf(" type="); + switch (sect->type) { + case SECTION_GENERAL: + printf("general\n"); + break; + case SECTION_ABSOLUTE: + printf("absolute\n"); + printf("start=%lu\n", sect->data.start); + break; + } + + printf(" Bytecodes:\n"); + bytecodes_print(§->bc); +} diff --git a/src/section.h b/src/section.h index ff881721..93aa3de4 100644 --- a/src/section.h +++ b/src/section.h @@ -36,5 +36,11 @@ section *sections_initialize(sectionhead *headp, struct objfmt_s *of); section *sections_switch(sectionhead *headp, struct objfmt_s *of, const char *name); +void sections_print(sectionhead *headp); + bytecodehead *section_get_bytecodes(section *sect); + +const char *section_get_name(const section *sect); + +void section_print(const section *sect); #endif diff --git a/src/strtoul.c b/src/strtoul.c deleted file mode 100644 index 9eedc365..00000000 --- a/src/strtoul.c +++ /dev/null @@ -1,119 +0,0 @@ -/* $IdPath$ - * strtoul() implementation for systems that don't have it. - * - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "util.h" - -#ifdef HAVE_LIMITS_H -# include -#endif -#include -#include - -#ifdef STDC_HEADERS -# include -#endif - -RCSID("$IdPath$"); - -/* - * Convert a string to an unsigned long integer. - * - * Ignores `locale' stuff. Assumes that the upper and lower case - * alphabets and digits are each contiguous. - */ -unsigned long -strtoul(const char *nptr, - char **endptr, - int base) -{ - const char *s = nptr; - unsigned long acc; - unsigned char c; - unsigned long cutoff; - int neg = 0, any, cutlim; - - /* - * See strtol for comments as to the logic used. - */ - do { - c = *s++; - } while (isspace(c)); - if (c == '-') { - neg = 1; - c = *s++; - } else if (c == '+') - c = *s++; - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; - cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; - for (acc = 0, any = 0;; c = *s++) { - if (!isascii(c)) - break; - if (isdigit(c)) - c -= '0'; - else if (isalpha(c)) - c -= isupper(c) ? 'A' - 10 : 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = ULONG_MAX; - errno = ERANGE; - } else if (neg) - acc = -acc; - if (endptr != 0) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); -} diff --git a/src/symrec.c b/src/symrec.c index 639d37e2..d18f352e 100644 --- a/src/symrec.c +++ b/src/symrec.c @@ -25,6 +25,8 @@ #include "util.h" +#include + #ifdef STDC_HEADERS # include # include @@ -36,6 +38,7 @@ #include "globals.h" #include "errwarn.h" #include "floatnum.h" +#include "expr.h" #include "symrec.h" #include "bytecode.h" @@ -48,13 +51,13 @@ typedef enum { SYM_NOSTATUS = 0, SYM_USED = 1 << 0, /* for using variables before definition */ SYM_DEFINED = 1 << 1, /* once it's been defined in the file */ - SYM_VALUED = 1 << 2 /* once its value has been determined */ + SYM_VALUED = 1 << 2, /* once its value has been determined */ + SYM_NOTINTABLE = 1 << 3 /* if it's not in sym_table (ex. '$') */ } SymStatus; typedef enum { SYM_UNKNOWN, /* for unknown type (COMMON/EXTERN) */ - SYM_CONSTANT_INT, /* for EQU defined symbols (integers) */ - SYM_CONSTANT_FLOAT, /* (floating point) */ + SYM_EQU, /* for EQU defined symbols (expressions) */ SYM_LABEL /* for labels */ } SymType; @@ -66,8 +69,7 @@ struct symrec { char *filename; /* file and line */ unsigned long line; /* symbol was first declared or used on */ union { - unsigned long int_val; /* integer constant */ - floatnum *flt; /* floating point constant */ + expr *expn; /* equ value */ struct label_s { /* bytecode immediately preceding a label */ section *sect; bytecode *bc; @@ -76,56 +78,60 @@ struct symrec { }; /* private functions */ -static symrec *symrec_get_or_new(const char *); -static symrec *symrec_define(const char *, SymType type); +static symrec *symrec_get_or_new(const char *name, int in_table); +static symrec *symrec_define(const char *name, SymType type, int in_table); /* The symbol table: a ternary tree. */ static ternary_tree sym_table = (ternary_tree)NULL; /* create a new symrec */ static symrec * -symrec_get_or_new(const char *name) +symrec_get_or_new(const char *name, int in_table) { symrec *rec, *rec2; rec = xmalloc(sizeof(symrec)); - rec2 = ternary_insert(&sym_table, name, rec, 0); + if (in_table) { + rec2 = ternary_insert(&sym_table, name, rec, 0); - if (rec2 != rec) { - free(rec); - return rec2; - } + if (rec2 != rec) { + free(rec); + return rec2; + } + rec->status = SYM_NOSTATUS; + } else + rec->status = SYM_NOTINTABLE; rec->name = xstrdup(name); rec->type = SYM_UNKNOWN; rec->filename = xstrdup(in_filename); rec->line = line_number; - rec->status = SYM_NOSTATUS; rec->visibility = SYM_LOCAL; return rec; } -/* call a function with each symrec. stop early if 0 returned */ -void -symrec_foreach(int (*func) (const char *name, symrec *rec)) +/* Call a function with each symrec. Stops early if 0 returned by func. + Returns 0 if stopped early. */ +int +symrec_foreach(int (*func) (symrec *sym)) { - /* TODO */ + return ternary_traverse(sym_table, (int (*) (void *))func); } symrec * symrec_use(const char *name) { - symrec *rec = symrec_get_or_new(name); + symrec *rec = symrec_get_or_new(name, 1); rec->status |= SYM_USED; return rec; } static symrec * -symrec_define(const char *name, SymType type) +symrec_define(const char *name, SymType type, int in_table) { - symrec *rec = symrec_get_or_new(name); + symrec *rec = symrec_get_or_new(name, in_table); /* Has it been defined before (either by DEFINED or COMMON/EXTERN)? */ if (rec->status & SYM_DEFINED) { @@ -140,27 +146,19 @@ symrec_define(const char *name, SymType type) } symrec * -symrec_define_constant_int(const char *name, unsigned long int_val) +symrec_define_equ(const char *name, expr *e) { - symrec *rec = symrec_define(name, SYM_CONSTANT_INT); - rec->value.int_val = int_val; + symrec *rec = symrec_define(name, SYM_EQU, 1); + rec->value.expn = e; rec->status |= SYM_VALUED; return rec; } symrec * -symrec_define_constant_float(const char *name, floatnum *flt) +symrec_define_label(const char *name, section *sect, bytecode *precbc, + int in_table) { - symrec *rec = symrec_define(name, SYM_CONSTANT_FLOAT); - rec->value.flt = flt; - rec->status |= SYM_VALUED; - return rec; -} - -symrec * -symrec_define_label(const char *name, section *sect, bytecode *precbc) -{ - symrec *rec = symrec_define(name, SYM_LABEL); + symrec *rec = symrec_define(name, SYM_LABEL, in_table); rec->value.label.sect = sect; rec->value.label.bc = precbc; return rec; @@ -169,7 +167,7 @@ symrec_define_label(const char *name, section *sect, bytecode *precbc) symrec * symrec_declare(const char *name, SymVisibility vis) { - symrec *rec = symrec_get_or_new(name); + symrec *rec = symrec_get_or_new(name, 1); /* Don't allow EXTERN and COMMON if symbol has already been DEFINED. */ /* Also, EXTERN and COMMON are mutually exclusive. */ @@ -188,7 +186,7 @@ symrec_declare(const char *name, SymVisibility vis) } return rec; } - +#if 0 int symrec_get_int_value(const symrec *sym, unsigned long *ret_val, int resolve_label) @@ -224,9 +222,67 @@ symrec_get_int_value(const symrec *sym, unsigned long *ret_val, /* We can't get the value right now. */ return 0; } - +#endif const char * symrec_get_name(const symrec *sym) { return sym->name; } + +void +symrec_print(const symrec *sym) +{ + printf("---Symbol `%s'---\n", sym->name); + + switch (sym->type) { + case SYM_UNKNOWN: + printf("-Unknown (Common/Extern)-\n"); + break; + case SYM_EQU: + printf("_EQU_\n"); + printf("Expn="); + expr_print(sym->value.expn); + printf("\n"); + break; + case SYM_LABEL: + printf("_Label_\n"); + printf("Section=`%s'\n", section_get_name(sym->value.label.sect)); + if (!sym->value.label.bc) + printf("[First bytecode]\n"); + else { + printf("[Preceding bytecode]\n"); + bytecode_print(sym->value.label.bc); + } + break; + } + + printf("Status="); + if (sym->status == SYM_NOSTATUS) + printf("None\n"); + else { + if (sym->status & SYM_USED) + printf("Used,"); + if (sym->status & SYM_DEFINED) + printf("Defined,"); + if (sym->status & SYM_VALUED) + printf("Valued,"); + if (sym->status & SYM_NOTINTABLE) + printf("Not in Table,"); + printf("\n"); + } + + printf("Visibility="); + if (sym->visibility == SYM_LOCAL) + printf("Local\n"); + else { + if (sym->visibility & SYM_GLOBAL) + printf("Global,"); + if (sym->visibility & SYM_COMMON) + printf("Common,"); + if (sym->visibility & SYM_EXTERN) + printf("Extern,"); + printf("\n"); + } + + printf("Filename=\"%s\" Line Number=%lu\n", sym->filename, sym->line); +} diff --git a/src/symrec.h b/src/symrec.h index 3b4cd8c3..2f136021 100644 --- a/src/symrec.h +++ b/src/symrec.h @@ -22,9 +22,9 @@ #ifndef YASM_SYMREC_H #define YASM_SYMREC_H -#ifndef YASM_FLOATNUM -#define YASM_FLOATNUM -typedef struct floatnum floatnum; +#ifndef YASM_EXPR +#define YASM_EXPR +typedef struct expr expr; #endif #ifndef YASM_SECTION @@ -51,9 +51,10 @@ typedef struct symrec symrec; #endif symrec *symrec_use(const char *name); -symrec *symrec_define_constant_int(const char *name, unsigned long int_val); -symrec *symrec_define_constant_float(const char *name, floatnum *flt); -symrec *symrec_define_label(const char *name, section *sect, bytecode *precbc); +symrec *symrec_define_equ(const char *name, expr *e); +/* in_table specifies if the label should be inserted into the symbol table. */ +symrec *symrec_define_label(const char *name, section *sect, bytecode *precbc, + int in_table); symrec *symrec_declare(const char *name, SymVisibility vis); /* Get the numeric 32-bit value of a symbol if possible. @@ -66,6 +67,7 @@ int symrec_get_int_value(const symrec *sym, unsigned long *ret_val, const char *symrec_get_name(const symrec *sym); -void symrec_foreach(int (*func) (const char *name, symrec *rec)); +int symrec_foreach(int (*func) (symrec *sym)); +void symrec_print(const symrec *sym); #endif diff --git a/src/ternary.c b/src/ternary.c index b1320d54..7b7b920f 100644 --- a/src/ternary.c +++ b/src/ternary.c @@ -3,6 +3,9 @@ Contributed by Daniel Berlin (dan@cgsoftware.com) + ternary_traverse by Peter Johnson (adapted from code by Jon Bentley and + Robert Sedgewick). + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any @@ -160,3 +163,23 @@ ternary_recursivesearch (ternary_tree p, const char *s) return ternary_recursivesearch (p->eqkid, ++s); } } + +/* Traverse over tree, calling callback function for each leaf. + Stops early if func returns 0. */ +int +ternary_traverse (ternary_tree p, int (*func) (void *d)) +{ + if (!p) + return 1; + if (ternary_traverse (p->lokid, func) == 0) + return 0; + if (p->splitchar) + { + if (ternary_traverse (p->eqkid, func) == 0) + return 0; + } + else + if (func (p->eqkid) == 0) + return 0; + return ternary_traverse (p->hikid, func); +} diff --git a/src/ternary.h b/src/ternary.h index 8e0ff6a2..e9f78b80 100644 --- a/src/ternary.h +++ b/src/ternary.h @@ -47,4 +47,8 @@ void ternary_cleanup (ternary_tree p); /* Search the ternary tree for string S, returning the data associated with it if found. */ void *ternary_search (ternary_tree p, const char *s); + +/* Traverse over tree, calling callback function for each leaf. + Stops early if func returns 0. */ +int ternary_traverse (ternary_tree p, int (*func) (void *d)); #endif diff --git a/src/tests/floatnum_test.c b/src/tests/floatnum_test.c index d768e3c7..78ef88e8 100644 --- a/src/tests/floatnum_test.c +++ b/src/tests/floatnum_test.c @@ -287,7 +287,8 @@ START_TEST(test_get_single_normalized) for (i=0; i