- 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
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)
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)
#include "globals.h"
#include "options.h"
#include "errwarn.h"
+#include "symrec.h"
#include "bytecode.h"
#include "section.h"
int
main(int argc, char *argv[])
{
+ sectionhead *sections;
+
if (parse_cmdline(argc, argv, options, countof(options, opt_option)))
return EXIT_FAILURE;
/* 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;
#include "globals.h"
#include "errwarn.h"
+#include "intnum.h"
#include "floatnum.h"
#include "expr.h"
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;
};
{
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;
immval *im = xmalloc(sizeof(immval));
im->val = expr_ptr;
-
+ im->len = 0;
im->isneg = 0;
return im;
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;
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);
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");
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],
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],
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);
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;
}
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;
*/
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);
#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"
union {
symrec *sym;
expr *expn;
- unsigned long int_val;
+ intnum *intn;
floatnum *flt;
} data;
};
struct expr {
ExprItem left, right;
ExprOp op;
+ char *filename;
+ unsigned long line;
};
/* allocate a new expression node, with children as defined.
InternalError(__LINE__, __FILE__,
_("Right side of expression must exist"));
}
+
+ ptr->filename = xstrdup(in_filename);
+ ptr->line = line_number;
+
return ptr;
}
}
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;
}
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) {
* 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;
simplified = 1;
}
}
+#endif
/* ditto on the right */
if (e->right.type == EXPR_EXPR) {
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. */
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)
{
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);
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;
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);
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,
EXPR_NE,
EXPR_IDENT /* if right is IDENT, then the entire expr is just a num */
} ExprOp;
+#endif
typedef struct ExprItem ExprItem;
ExprItem *ExprSym(symrec *);
ExprItem *ExprExpr(expr *);
-ExprItem *ExprInt(unsigned long);
+ExprItem *ExprInt(intnum *);
ExprItem *ExprFloat(floatnum *);
#define expr_new_tree(l,o,r) \
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
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.
* 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
* | | |
* 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
* | | |
* 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
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");
#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;
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).
/* 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);
--- /dev/null
+/* $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 <stdio.h>
+#include <ctype.h>
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#include <libintl.h>
+#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;
+ }
+}
--- /dev/null
+/* $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
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);
+}
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
#include "util.h"
+#include <stdio.h>
+
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#include "globals.h"
#include "errwarn.h"
#include "floatnum.h"
+#include "expr.h"
#include "symrec.h"
#include "bytecode.h"
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;
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;
};
/* 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) {
}
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;
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. */
}
return rec;
}
-
+#if 0
int
symrec_get_int_value(const symrec *sym, unsigned long *ret_val,
int resolve_label)
/* 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);
+}
#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
#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.
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
for (i=0; i<num; i++) {
get_common_setup(vals, i);
- fail_unless(floatnum_get_single(outval, flt) == vals[i].ret32, ret_msg);
+ fail_unless(floatnum_get_sized(outval, flt, 4) == vals[i].ret32,
+ ret_msg);
fail_unless(get_common_check_result(4, outval, vals[i].result32) == 0,
result_msg);
}
for (i=0; i<num; i++) {
get_common_setup(vals, i);
- fail_unless(floatnum_get_single(outval, flt) == vals[i].ret32, ret_msg);
+ fail_unless(floatnum_get_sized(outval, flt, 4) == vals[i].ret32,
+ ret_msg);
fail_unless(get_common_check_result(4, outval, vals[i].result32) == 0,
result_msg);
}
for (i=0; i<num; i++) {
get_common_setup(vals, i);
- fail_unless(floatnum_get_double(outval, flt) == vals[i].ret64, ret_msg);
+ fail_unless(floatnum_get_sized(outval, flt, 8) == vals[i].ret64,
+ ret_msg);
fail_unless(get_common_check_result(8, outval, vals[i].result64) == 0,
result_msg);
}
for (i=0; i<num; i++) {
get_common_setup(vals, i);
- fail_unless(floatnum_get_double(outval, flt) == vals[i].ret64, ret_msg);
+ fail_unless(floatnum_get_sized(outval, flt, 8) == vals[i].ret64,
+ ret_msg);
fail_unless(get_common_check_result(8, outval, vals[i].result64) == 0,
result_msg);
}
for (i=0; i<num; i++) {
get_common_setup(vals, i);
- fail_unless(floatnum_get_extended(outval, flt) == vals[i].ret80,
+ fail_unless(floatnum_get_sized(outval, flt, 10) == vals[i].ret80,
ret_msg);
fail_unless(get_common_check_result(10, outval, vals[i].result80) == 0,
result_msg);
for (i=0; i<num; i++) {
get_common_setup(vals, i);
- fail_unless(floatnum_get_extended(outval, flt) == vals[i].ret80,
+ fail_unless(floatnum_get_sized(outval, flt, 10) == vals[i].ret80,
ret_msg);
fail_unless(get_common_check_result(10, outval, vals[i].result80) == 0,
result_msg);
char *strsep(char **stringp, const char *delim);
#endif
-#if !defined(HAVE_STRTOUL) || defined(HAVE_GNU_C_LIBRARY)
-unsigned long strtoul(const char *nptr, char **endptr, int base);
-#endif
-
#ifndef HAVE_STRCASECMP
# ifdef HAVE_STRICMP
# define strcasecmp(x, y) stricmp(x, y)
#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"
union {
symrec *sym;
expr *expn;
- unsigned long int_val;
+ intnum *intn;
floatnum *flt;
} data;
};
struct expr {
ExprItem left, right;
ExprOp op;
+ char *filename;
+ unsigned long line;
};
/* allocate a new expression node, with children as defined.
InternalError(__LINE__, __FILE__,
_("Right side of expression must exist"));
}
+
+ ptr->filename = xstrdup(in_filename);
+ ptr->line = line_number;
+
return ptr;
}
}
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;
}
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) {
* 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;
simplified = 1;
}
}
+#endif
/* ditto on the right */
if (e->right.type == EXPR_EXPR) {
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. */
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)
{
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);
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;
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);
#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"
union {
symrec *sym;
expr *expn;
- unsigned long int_val;
+ intnum *intn;
floatnum *flt;
} data;
};
struct expr {
ExprItem left, right;
ExprOp op;
+ char *filename;
+ unsigned long line;
};
/* allocate a new expression node, with children as defined.
InternalError(__LINE__, __FILE__,
_("Right side of expression must exist"));
}
+
+ ptr->filename = xstrdup(in_filename);
+ ptr->line = line_number;
+
return ptr;
}
}
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;
}
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) {
* 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;
simplified = 1;
}
}
+#endif
/* ditto on the right */
if (e->right.type == EXPR_EXPR) {
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. */
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)
{
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);
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;
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);
#include <libintl.h>
#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"
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;
%}
%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;
bytecode *bc;
}
-%token <int_val> INTNUM
+%token <intn> INTNUM
%token <flt> FLTNUM
%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
-%token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
-%token <int_val> DECLARE_DATA
-%token <int_val> RESERVE_SPACE
+%token <int_info> BYTE WORD DWORD QWORD TWORD DQWORD
+%token <int_info> DECLARE_DATA
+%token <int_info> 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 <int_val> OPERSIZE ADDRSIZE
-%token <int_val> CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG
-%token <int_val> REG_EAX REG_ECX REG_EDX REG_EBX REG_ESP REG_EBP REG_ESI REG_EDI
-%token <int_val> REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI
-%token <int_val> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
-%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
-%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
+%token <int_info> OPERSIZE ADDRSIZE
+%token <int_info> CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG
+%token <int_info> REG_EAX REG_ECX REG_EDX REG_EBX
+%token <int_info> REG_ESP REG_EBP REG_ESI REG_EDI
+%token <int_info> REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI
+%token <int_info> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
+%token <int_info> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
+%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD START_SECTION_ID
%token <str_val> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TYPES@ */
-%type <bc> line exp instr instrbase label
+%type <bc> line exp instr instrbase
-%type <int_val> fpureg reg32 reg16 reg8 segreg
+%type <int_info> fpureg reg32 reg16 reg8 segreg
%type <ea> mem memaddr memexp memfar
%type <ea> mem8x mem16x mem32x mem64x mem80x mem128x
%type <ea> mem8 mem16 mem32 mem64 mem80 mem128 mem1632
%type <ea> rm8 rm16 rm32 rm64 rm128
%type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
%type <exp> expr expr_no_string
-%type <str_val> explabel label_id
+%type <sym> explabel
+%type <str_val> label_id
%type <tgt_val> target
%type <data> dataval
%type <datahead> datavals
;
dataval: expr_no_string { $$ = dataval_new_expr($1); }
- | FLTNUM { $$ = dataval_new_float($1); }
| STRING { $$ = dataval_new_string($1); }
| error {
Error(_("expression syntax error"));
;
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);
}
;
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);
}
;
/* memory addresses */
-memexp: expr { expr_simplify ($1); $$ = effaddr_new_expr($1); }
+memexp: expr { $$ = effaddr_new_expr($1); }
;
memaddr: memexp { $$ = $1; SetEASegment($$, 0); }
;
/* immediate values */
-imm: expr { expr_simplify($1); $$ = immval_new_expr($1); }
+imm: expr { $$ = immval_new_expr($1); }
;
/* explicit immediates */
/* 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); }
| 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); }*/
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
%%
-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)
{
#include <libintl.h>
#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"
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;
%}
%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;
bytecode *bc;
}
-%token <int_val> INTNUM
+%token <intn> INTNUM
%token <flt> FLTNUM
%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
-%token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
-%token <int_val> DECLARE_DATA
-%token <int_val> RESERVE_SPACE
+%token <int_info> BYTE WORD DWORD QWORD TWORD DQWORD
+%token <int_info> DECLARE_DATA
+%token <int_info> 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 <int_val> OPERSIZE ADDRSIZE
-%token <int_val> CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG
-%token <int_val> REG_EAX REG_ECX REG_EDX REG_EBX REG_ESP REG_EBP REG_ESI REG_EDI
-%token <int_val> REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI
-%token <int_val> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
-%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
-%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
+%token <int_info> OPERSIZE ADDRSIZE
+%token <int_info> CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG
+%token <int_info> REG_EAX REG_ECX REG_EDX REG_EBX
+%token <int_info> REG_ESP REG_EBP REG_ESI REG_EDI
+%token <int_info> REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI
+%token <int_info> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
+%token <int_info> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
+%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD START_SECTION_ID
%token <str_val> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TYPES@ */
-%type <bc> line exp instr instrbase label
+%type <bc> line exp instr instrbase
-%type <int_val> fpureg reg32 reg16 reg8 segreg
+%type <int_info> fpureg reg32 reg16 reg8 segreg
%type <ea> mem memaddr memexp memfar
%type <ea> mem8x mem16x mem32x mem64x mem80x mem128x
%type <ea> mem8 mem16 mem32 mem64 mem80 mem128 mem1632
%type <ea> rm8 rm16 rm32 rm64 rm128
%type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
%type <exp> expr expr_no_string
-%type <str_val> explabel label_id
+%type <sym> explabel
+%type <str_val> label_id
%type <tgt_val> target
%type <data> dataval
%type <datahead> datavals
;
dataval: expr_no_string { $$ = dataval_new_expr($1); }
- | FLTNUM { $$ = dataval_new_float($1); }
| STRING { $$ = dataval_new_string($1); }
| error {
Error(_("expression syntax error"));
;
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);
}
;
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);
}
;
/* memory addresses */
-memexp: expr { expr_simplify ($1); $$ = effaddr_new_expr($1); }
+memexp: expr { $$ = effaddr_new_expr($1); }
;
memaddr: memexp { $$ = $1; SetEASegment($$, 0); }
;
/* immediate values */
-imm: expr { expr_simplify($1); $$ = immval_new_expr($1); }
+imm: expr { $$ = immval_new_expr($1); }
;
/* explicit immediates */
/* 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); }
| 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); }*/
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
%%
-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)
{
#include <libintl.h>
#define _(String) gettext(String)
+#include "bitvect.h"
+
#include "errwarn.h"
+#include "intnum.h"
#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
/* 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;
}
}
/* 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; }
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; }
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;
}
parser.c \
parser.h \
optimizer.h \
+ intnum.c \
+ intnum.h \
floatnum.c \
floatnum.h \
ternary.c \
EXTRA_DIST = \
instrs.dat \
- compat-queue.h \
- strtoul.c
+ compat-queue.h
#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"
union {
symrec *sym;
expr *expn;
- unsigned long int_val;
+ intnum *intn;
floatnum *flt;
} data;
};
struct expr {
ExprItem left, right;
ExprOp op;
+ char *filename;
+ unsigned long line;
};
/* allocate a new expression node, with children as defined.
InternalError(__LINE__, __FILE__,
_("Right side of expression must exist"));
}
+
+ ptr->filename = xstrdup(in_filename);
+ ptr->line = line_number;
+
return ptr;
}
}
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;
}
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) {
* 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;
simplified = 1;
}
}
+#endif
/* ditto on the right */
if (e->right.type == EXPR_EXPR) {
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. */
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)
{
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);
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;
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);
#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"
union {
symrec *sym;
expr *expn;
- unsigned long int_val;
+ intnum *intn;
floatnum *flt;
} data;
};
struct expr {
ExprItem left, right;
ExprOp op;
+ char *filename;
+ unsigned long line;
};
/* allocate a new expression node, with children as defined.
InternalError(__LINE__, __FILE__,
_("Right side of expression must exist"));
}
+
+ ptr->filename = xstrdup(in_filename);
+ ptr->line = line_number;
+
return ptr;
}
}
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;
}
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) {
* 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;
simplified = 1;
}
}
+#endif
/* ditto on the right */
if (e->right.type == EXPR_EXPR) {
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. */
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)
{
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);
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;
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);
#include "globals.h"
#include "errwarn.h"
+#include "intnum.h"
#include "floatnum.h"
#include "expr.h"
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;
};
{
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;
immval *im = xmalloc(sizeof(immval));
im->val = expr_ptr;
-
+ im->len = 0;
im->isneg = 0;
return im;
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;
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);
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");
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],
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],
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);
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;
}
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;
*/
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);
#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"
union {
symrec *sym;
expr *expn;
- unsigned long int_val;
+ intnum *intn;
floatnum *flt;
} data;
};
struct expr {
ExprItem left, right;
ExprOp op;
+ char *filename;
+ unsigned long line;
};
/* allocate a new expression node, with children as defined.
InternalError(__LINE__, __FILE__,
_("Right side of expression must exist"));
}
+
+ ptr->filename = xstrdup(in_filename);
+ ptr->line = line_number;
+
return ptr;
}
}
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;
}
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) {
* 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;
simplified = 1;
}
}
+#endif
/* ditto on the right */
if (e->right.type == EXPR_EXPR) {
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. */
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)
{
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);
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;
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);
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,
EXPR_NE,
EXPR_IDENT /* if right is IDENT, then the entire expr is just a num */
} ExprOp;
+#endif
typedef struct ExprItem ExprItem;
ExprItem *ExprSym(symrec *);
ExprItem *ExprExpr(expr *);
-ExprItem *ExprInt(unsigned long);
+ExprItem *ExprInt(intnum *);
ExprItem *ExprFloat(floatnum *);
#define expr_new_tree(l,o,r) \
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
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.
* 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
* | | |
* 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
* | | |
* 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
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");
#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;
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).
/* 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);
--- /dev/null
+/* $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 <stdio.h>
+#include <ctype.h>
+
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#include <libintl.h>
+#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;
+ }
+}
--- /dev/null
+/* $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
#include "globals.h"
#include "options.h"
#include "errwarn.h"
+#include "symrec.h"
#include "bytecode.h"
#include "section.h"
int
main(int argc, char *argv[])
{
+ sectionhead *sections;
+
if (parse_cmdline(argc, argv, options, countof(options, opt_option)))
return EXIT_FAILURE;
/* 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;
#include <libintl.h>
#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"
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;
%}
%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;
bytecode *bc;
}
-%token <int_val> INTNUM
+%token <intn> INTNUM
%token <flt> FLTNUM
%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
-%token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
-%token <int_val> DECLARE_DATA
-%token <int_val> RESERVE_SPACE
+%token <int_info> BYTE WORD DWORD QWORD TWORD DQWORD
+%token <int_info> DECLARE_DATA
+%token <int_info> 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 <int_val> OPERSIZE ADDRSIZE
-%token <int_val> CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG
-%token <int_val> REG_EAX REG_ECX REG_EDX REG_EBX REG_ESP REG_EBP REG_ESI REG_EDI
-%token <int_val> REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI
-%token <int_val> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
-%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
-%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
+%token <int_info> OPERSIZE ADDRSIZE
+%token <int_info> CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG
+%token <int_info> REG_EAX REG_ECX REG_EDX REG_EBX
+%token <int_info> REG_ESP REG_EBP REG_ESI REG_EDI
+%token <int_info> REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI
+%token <int_info> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
+%token <int_info> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
+%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD START_SECTION_ID
%token <str_val> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TYPES@ */
-%type <bc> line exp instr instrbase label
+%type <bc> line exp instr instrbase
-%type <int_val> fpureg reg32 reg16 reg8 segreg
+%type <int_info> fpureg reg32 reg16 reg8 segreg
%type <ea> mem memaddr memexp memfar
%type <ea> mem8x mem16x mem32x mem64x mem80x mem128x
%type <ea> mem8 mem16 mem32 mem64 mem80 mem128 mem1632
%type <ea> rm8 rm16 rm32 rm64 rm128
%type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
%type <exp> expr expr_no_string
-%type <str_val> explabel label_id
+%type <sym> explabel
+%type <str_val> label_id
%type <tgt_val> target
%type <data> dataval
%type <datahead> datavals
;
dataval: expr_no_string { $$ = dataval_new_expr($1); }
- | FLTNUM { $$ = dataval_new_float($1); }
| STRING { $$ = dataval_new_string($1); }
| error {
Error(_("expression syntax error"));
;
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);
}
;
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);
}
;
/* memory addresses */
-memexp: expr { expr_simplify ($1); $$ = effaddr_new_expr($1); }
+memexp: expr { $$ = effaddr_new_expr($1); }
;
memaddr: memexp { $$ = $1; SetEASegment($$, 0); }
;
/* immediate values */
-imm: expr { expr_simplify($1); $$ = immval_new_expr($1); }
+imm: expr { $$ = immval_new_expr($1); }
;
/* explicit immediates */
/* 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); }
| 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); }*/
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
%%
-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)
{
#include <libintl.h>
#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"
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;
%}
%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;
bytecode *bc;
}
-%token <int_val> INTNUM
+%token <intn> INTNUM
%token <flt> FLTNUM
%token <str_val> DIRECTIVE_NAME DIRECTIVE_VAL STRING
-%token <int_val> BYTE WORD DWORD QWORD TWORD DQWORD
-%token <int_val> DECLARE_DATA
-%token <int_val> RESERVE_SPACE
+%token <int_info> BYTE WORD DWORD QWORD TWORD DQWORD
+%token <int_info> DECLARE_DATA
+%token <int_info> 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 <int_val> OPERSIZE ADDRSIZE
-%token <int_val> CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG
-%token <int_val> REG_EAX REG_ECX REG_EDX REG_EBX REG_ESP REG_EBP REG_ESI REG_EDI
-%token <int_val> REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI
-%token <int_val> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
-%token <int_val> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
-%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD
+%token <int_info> OPERSIZE ADDRSIZE
+%token <int_info> CR4 CRREG_NOTCR4 DRREG TRREG ST0 FPUREG_NOTST0 MMXREG XMMREG
+%token <int_info> REG_EAX REG_ECX REG_EDX REG_EBX
+%token <int_info> REG_ESP REG_EBP REG_ESI REG_EDI
+%token <int_info> REG_AX REG_CX REG_DX REG_BX REG_SP REG_BP REG_SI REG_DI
+%token <int_info> REG_AL REG_CL REG_DL REG_BL REG_AH REG_CH REG_DH REG_BH
+%token <int_info> REG_ES REG_CS REG_SS REG_DS REG_FS REG_GS
+%token LEFT_OP RIGHT_OP SIGNDIV SIGNMOD START_SECTION_ID
%token <str_val> ID LOCAL_ID SPECIAL_ID
/* instruction tokens (dynamically generated) */
/* @TYPES@ */
-%type <bc> line exp instr instrbase label
+%type <bc> line exp instr instrbase
-%type <int_val> fpureg reg32 reg16 reg8 segreg
+%type <int_info> fpureg reg32 reg16 reg8 segreg
%type <ea> mem memaddr memexp memfar
%type <ea> mem8x mem16x mem32x mem64x mem80x mem128x
%type <ea> mem8 mem16 mem32 mem64 mem80 mem128 mem1632
%type <ea> rm8 rm16 rm32 rm64 rm128
%type <im_val> imm imm8x imm16x imm32x imm8 imm16 imm32
%type <exp> expr expr_no_string
-%type <str_val> explabel label_id
+%type <sym> explabel
+%type <str_val> label_id
%type <tgt_val> target
%type <data> dataval
%type <datahead> datavals
;
dataval: expr_no_string { $$ = dataval_new_expr($1); }
- | FLTNUM { $$ = dataval_new_float($1); }
| STRING { $$ = dataval_new_string($1); }
| error {
Error(_("expression syntax error"));
;
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);
}
;
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);
}
;
/* memory addresses */
-memexp: expr { expr_simplify ($1); $$ = effaddr_new_expr($1); }
+memexp: expr { $$ = effaddr_new_expr($1); }
;
memaddr: memexp { $$ = $1; SetEASegment($$, 0); }
;
/* immediate values */
-imm: expr { expr_simplify($1); $$ = immval_new_expr($1); }
+imm: expr { $$ = immval_new_expr($1); }
;
/* explicit immediates */
/* 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); }
| 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); }*/
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
%%
-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)
{
#include <libintl.h>
#define _(String) gettext(String)
+#include "bitvect.h"
+
#include "errwarn.h"
+#include "intnum.h"
#include "floatnum.h"
#include "expr.h"
#include "symrec.h"
/* 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;
}
}
/* 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; }
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; }
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;
}
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);
+}
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
+++ /dev/null
-/* $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 <limits.h>
-#endif
-#include <ctype.h>
-#include <errno.h>
-
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-#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);
-}
#include "util.h"
+#include <stdio.h>
+
#ifdef STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#include "globals.h"
#include "errwarn.h"
#include "floatnum.h"
+#include "expr.h"
#include "symrec.h"
#include "bytecode.h"
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;
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;
};
/* 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) {
}
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;
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. */
}
return rec;
}
-
+#if 0
int
symrec_get_int_value(const symrec *sym, unsigned long *ret_val,
int resolve_label)
/* 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);
+}
#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
#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.
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
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
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);
+}
/* 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
for (i=0; i<num; i++) {
get_common_setup(vals, i);
- fail_unless(floatnum_get_single(outval, flt) == vals[i].ret32, ret_msg);
+ fail_unless(floatnum_get_sized(outval, flt, 4) == vals[i].ret32,
+ ret_msg);
fail_unless(get_common_check_result(4, outval, vals[i].result32) == 0,
result_msg);
}
for (i=0; i<num; i++) {
get_common_setup(vals, i);
- fail_unless(floatnum_get_single(outval, flt) == vals[i].ret32, ret_msg);
+ fail_unless(floatnum_get_sized(outval, flt, 4) == vals[i].ret32,
+ ret_msg);
fail_unless(get_common_check_result(4, outval, vals[i].result32) == 0,
result_msg);
}
for (i=0; i<num; i++) {
get_common_setup(vals, i);
- fail_unless(floatnum_get_double(outval, flt) == vals[i].ret64, ret_msg);
+ fail_unless(floatnum_get_sized(outval, flt, 8) == vals[i].ret64,
+ ret_msg);
fail_unless(get_common_check_result(8, outval, vals[i].result64) == 0,
result_msg);
}
for (i=0; i<num; i++) {
get_common_setup(vals, i);
- fail_unless(floatnum_get_double(outval, flt) == vals[i].ret64, ret_msg);
+ fail_unless(floatnum_get_sized(outval, flt, 8) == vals[i].ret64,
+ ret_msg);
fail_unless(get_common_check_result(8, outval, vals[i].result64) == 0,
result_msg);
}
for (i=0; i<num; i++) {
get_common_setup(vals, i);
- fail_unless(floatnum_get_extended(outval, flt) == vals[i].ret80,
+ fail_unless(floatnum_get_sized(outval, flt, 10) == vals[i].ret80,
ret_msg);
fail_unless(get_common_check_result(10, outval, vals[i].result80) == 0,
result_msg);
for (i=0; i<num; i++) {
get_common_setup(vals, i);
- fail_unless(floatnum_get_extended(outval, flt) == vals[i].ret80,
+ fail_unless(floatnum_get_sized(outval, flt, 10) == vals[i].ret80,
ret_msg);
fail_unless(get_common_check_result(10, outval, vals[i].result80) == 0,
result_msg);
char *strsep(char **stringp, const char *delim);
#endif
-#if !defined(HAVE_STRTOUL) || defined(HAVE_GNU_C_LIBRARY)
-unsigned long strtoul(const char *nptr, char **endptr, int base);
-#endif
-
#ifndef HAVE_STRCASECMP
# ifdef HAVE_STRICMP
# define strcasecmp(x, y) stricmp(x, y)
char *strsep(char **stringp, const char *delim);
#endif
-#if !defined(HAVE_STRTOUL) || defined(HAVE_GNU_C_LIBRARY)
-unsigned long strtoul(const char *nptr, char **endptr, int base);
-#endif
-
#ifndef HAVE_STRCASECMP
# ifdef HAVE_STRICMP
# define strcasecmp(x, y) stricmp(x, y)