e->op = EXPR_IDENT;
break;
case EXPR_IDENT:
- /* Negating an ident? Change it into a MUL w/ -1. */
- e->op = EXPR_MUL;
- e->numterms = 2;
- e->terms[1].type = EXPR_INT;
- e->terms[1].data.intn = intnum_new_int((unsigned long)-1);
+ /* Negating an ident? Change it into a MUL w/ -1 if there's no
+ * floatnums present below; if there ARE floatnums, recurse.
+ */
+ if (e->terms[0].type == EXPR_FLOAT)
+ floatnum_calc(e->terms[0].data.flt, EXPR_NEG, NULL);
+ else if (e->terms[0].type == EXPR_EXPR &&
+ expr_contains(e->terms[0].data.expn, EXPR_FLOAT))
+ expr_xform_neg_helper(e->terms[0].data.expn);
+ else {
+ e->op = EXPR_MUL;
+ e->numterms = 2;
+ e->terms[1].type = EXPR_INT;
+ e->terms[1].data.intn = intnum_new_int((unsigned long)-1);
+ }
break;
default:
/* Everything else. MUL will be combined when it's leveled.
/*@observer@*/ bin_objfmt_expr_data data;
/*@dependent@*/ /*@null@*/ const intnum *num;
/*@dependent@*/ /*@null@*/ const floatnum *flt;
- unsigned long val;
assert(info != NULL);
flt = expr_get_floatnum(ep);
if (flt) {
int fltret;
+
+ if (!floatnum_check_size(flt, (size_t)valsize)) {
+ ErrorAt((*ep)->line, _("invalid floating point constant size"));
+ return 1;
+ }
+
fltret = floatnum_get_sized(flt, *bufp, (size_t)valsize);
if (fltret < 0) {
ErrorAt((*ep)->line, _("underflow in floating point expression"));
/* Handle integer expressions */
num = expr_get_intnum(ep);
- if (!num) {
- ErrorAt((*ep)->line,
- _("binary object format does not support external references"));
- return 1;
+ if (num) {
+ if (rel) {
+ unsigned long val;
+ /* FIXME: Check against BITS setting on x86 */
+ if (valsize != 2 && valsize != 4)
+ InternalError(_("tried to do PC-relative offset from invalid sized value"));
+ val = intnum_get_uint(num);
+ val = (unsigned long)((long)(val - (bc->offset + bc->len)));
+ }
+
+ /* Write value out. */
+ intnum_get_sized(num, *bufp, (size_t)valsize);
+ *bufp += valsize;
+ return 0;
}
- val = intnum_get_uint(num);
-
- if (rel)
- val = (unsigned long)((long)(val - (bc->offset + bc->len)));
-
- /* Write value out. */
- /* FIXME: Should we warn here about truncation if it doesn't fit? */
- switch (valsize) {
- case 1:
- WRITE_BYTE(*bufp, val);
- break;
- case 2:
- WRITE_SHORT(*bufp, val);
- break;
- case 4:
- WRITE_LONG(*bufp, val);
- break;
- default:
- InternalError(_("unexpected size in bin objfmt output expr"));
+
+ /* Check for complex float expressions */
+ if (expr_contains(*ep, EXPR_FLOAT)) {
+ ErrorAt((*ep)->line, _("floating point expression too complex"));
+ return 1;
}
- return 0;
+ /* Couldn't output, assume it contains an external reference. */
+ ErrorAt((*ep)->line,
+ _("binary object format does not support external references"));
+ return 1;
}
static int
EXTRA_DIST += \
src/objfmts/bin/tests/objfmt_test.sh \
+ src/objfmts/bin/tests/float-err.asm \
+ src/objfmts/bin/tests/float-err.errwarn \
+ src/objfmts/bin/tests/float.asm \
+ src/objfmts/bin/tests/float.bin.hx \
+ src/objfmts/bin/tests/float.errwarn \
+ src/objfmts/bin/tests/integer.asm \
+ src/objfmts/bin/tests/integer.bin.hx \
+ src/objfmts/bin/tests/integer.errwarn \
src/objfmts/bin/tests/reserve.asm \
src/objfmts/bin/tests/reserve.bin.hx \
src/objfmts/bin/tests/reserve.errwarn
CLEANFILES += \
+ float-err.ew \
+ float \
+ float.hx \
+ float.ew \
+ integer \
+ integer.hx \
+ integer.ew \
reserve \
reserve.ew \
reserve.hx
--- /dev/null
+; Tests illegal float handling
+db 1.2
+dw 3.14
+dd 5.12e100000
+dq 3.141592653589793e-158105
+dt 5653894745.318293470142875104710284019245e-1999
+
+db -1.5
+dw -5593824513450897123075109385109385019324871093470134710984.34981
+dd -47102940.46710358135703124751034875109875103294510984019324
+dq -45102571092751092341095.5827509174509178450917845019e15555
+dt -1.e-100000
--- /dev/null
+./src/objfmts/bin/tests/float-err.asm:2: invalid floating point constant size
+./src/objfmts/bin/tests/float-err.asm:3: invalid floating point constant size
+./src/objfmts/bin/tests/float-err.asm:4: overflow in floating point expression
+./src/objfmts/bin/tests/float-err.asm:5: underflow in floating point expression
+./src/objfmts/bin/tests/float-err.asm:8: invalid floating point constant size
+./src/objfmts/bin/tests/float-err.asm:9: invalid floating point constant size
+./src/objfmts/bin/tests/float-err.asm:11: overflow in floating point expression
+./src/objfmts/bin/tests/float-err.asm:12: underflow in floating point expression
--- /dev/null
+; Tests float handling
+dd 5.12
+dq 3.141592653589793
+dt 5653894745.318293470142875104710284019245e335
+
+dd -47102940.467103581
+dq -45102571092751092341095.5827509174509178450917845019
+dt -1.e-1000
--- /dev/null
+0a
+d7
+a3
+40
+18
+2d
+44
+54
+fb
+21
+09
+40
+75
+4e
+ef
+f1
+30
+25
+6e
+97
+78
+44
+f7
+ae
+33
+cc
+4d
+63
+8a
+d2
+07
+1a
+a3
+c4
+67
+14
+9e
+a8
+88
+91
+8a
+86
+05
+b3
--- /dev/null
+; Tests integer constant handling (for output, not parsing)
+
+db 0x51
+dw 0x3875
+dd 0x35783134
+dq 0xABCDEF0123456789
+dt 0xa907bc890d0e907f0134
+
--- /dev/null
+51
+75
+38
+34
+31
+78
+35
+89
+67
+45
+23
+01
+ef
+cd
+ab
+34
+01
+7f
+90
+0e
+0d
+89
+bc
+07
+a9
e->op = EXPR_IDENT;
break;
case EXPR_IDENT:
- /* Negating an ident? Change it into a MUL w/ -1. */
- e->op = EXPR_MUL;
- e->numterms = 2;
- e->terms[1].type = EXPR_INT;
- e->terms[1].data.intn = intnum_new_int((unsigned long)-1);
+ /* Negating an ident? Change it into a MUL w/ -1 if there's no
+ * floatnums present below; if there ARE floatnums, recurse.
+ */
+ if (e->terms[0].type == EXPR_FLOAT)
+ floatnum_calc(e->terms[0].data.flt, EXPR_NEG, NULL);
+ else if (e->terms[0].type == EXPR_EXPR &&
+ expr_contains(e->terms[0].data.expn, EXPR_FLOAT))
+ expr_xform_neg_helper(e->terms[0].data.expn);
+ else {
+ e->op = EXPR_MUL;
+ e->numterms = 2;
+ e->terms[1].type = EXPR_INT;
+ e->terms[1].data.intn = intnum_new_int((unsigned long)-1);
+ }
break;
default:
/* Everything else. MUL will be combined when it's leveled.
/*@observer@*/ bin_objfmt_expr_data data;
/*@dependent@*/ /*@null@*/ const intnum *num;
/*@dependent@*/ /*@null@*/ const floatnum *flt;
- unsigned long val;
assert(info != NULL);
flt = expr_get_floatnum(ep);
if (flt) {
int fltret;
+
+ if (!floatnum_check_size(flt, (size_t)valsize)) {
+ ErrorAt((*ep)->line, _("invalid floating point constant size"));
+ return 1;
+ }
+
fltret = floatnum_get_sized(flt, *bufp, (size_t)valsize);
if (fltret < 0) {
ErrorAt((*ep)->line, _("underflow in floating point expression"));
/* Handle integer expressions */
num = expr_get_intnum(ep);
- if (!num) {
- ErrorAt((*ep)->line,
- _("binary object format does not support external references"));
- return 1;
+ if (num) {
+ if (rel) {
+ unsigned long val;
+ /* FIXME: Check against BITS setting on x86 */
+ if (valsize != 2 && valsize != 4)
+ InternalError(_("tried to do PC-relative offset from invalid sized value"));
+ val = intnum_get_uint(num);
+ val = (unsigned long)((long)(val - (bc->offset + bc->len)));
+ }
+
+ /* Write value out. */
+ intnum_get_sized(num, *bufp, (size_t)valsize);
+ *bufp += valsize;
+ return 0;
}
- val = intnum_get_uint(num);
-
- if (rel)
- val = (unsigned long)((long)(val - (bc->offset + bc->len)));
-
- /* Write value out. */
- /* FIXME: Should we warn here about truncation if it doesn't fit? */
- switch (valsize) {
- case 1:
- WRITE_BYTE(*bufp, val);
- break;
- case 2:
- WRITE_SHORT(*bufp, val);
- break;
- case 4:
- WRITE_LONG(*bufp, val);
- break;
- default:
- InternalError(_("unexpected size in bin objfmt output expr"));
+
+ /* Check for complex float expressions */
+ if (expr_contains(*ep, EXPR_FLOAT)) {
+ ErrorAt((*ep)->line, _("floating point expression too complex"));
+ return 1;
}
- return 0;
+ /* Couldn't output, assume it contains an external reference. */
+ ErrorAt((*ep)->line,
+ _("binary object format does not support external references"));
+ return 1;
}
static int
EXTRA_DIST += \
src/objfmts/bin/tests/objfmt_test.sh \
+ src/objfmts/bin/tests/float-err.asm \
+ src/objfmts/bin/tests/float-err.errwarn \
+ src/objfmts/bin/tests/float.asm \
+ src/objfmts/bin/tests/float.bin.hx \
+ src/objfmts/bin/tests/float.errwarn \
+ src/objfmts/bin/tests/integer.asm \
+ src/objfmts/bin/tests/integer.bin.hx \
+ src/objfmts/bin/tests/integer.errwarn \
src/objfmts/bin/tests/reserve.asm \
src/objfmts/bin/tests/reserve.bin.hx \
src/objfmts/bin/tests/reserve.errwarn
CLEANFILES += \
+ float-err.ew \
+ float \
+ float.hx \
+ float.ew \
+ integer \
+ integer.hx \
+ integer.ew \
reserve \
reserve.ew \
reserve.hx
--- /dev/null
+; Tests illegal float handling
+db 1.2
+dw 3.14
+dd 5.12e100000
+dq 3.141592653589793e-158105
+dt 5653894745.318293470142875104710284019245e-1999
+
+db -1.5
+dw -5593824513450897123075109385109385019324871093470134710984.34981
+dd -47102940.46710358135703124751034875109875103294510984019324
+dq -45102571092751092341095.5827509174509178450917845019e15555
+dt -1.e-100000
--- /dev/null
+./src/objfmts/bin/tests/float-err.asm:2: invalid floating point constant size
+./src/objfmts/bin/tests/float-err.asm:3: invalid floating point constant size
+./src/objfmts/bin/tests/float-err.asm:4: overflow in floating point expression
+./src/objfmts/bin/tests/float-err.asm:5: underflow in floating point expression
+./src/objfmts/bin/tests/float-err.asm:8: invalid floating point constant size
+./src/objfmts/bin/tests/float-err.asm:9: invalid floating point constant size
+./src/objfmts/bin/tests/float-err.asm:11: overflow in floating point expression
+./src/objfmts/bin/tests/float-err.asm:12: underflow in floating point expression
--- /dev/null
+; Tests float handling
+dd 5.12
+dq 3.141592653589793
+dt 5653894745.318293470142875104710284019245e335
+
+dd -47102940.467103581
+dq -45102571092751092341095.5827509174509178450917845019
+dt -1.e-1000
--- /dev/null
+0a
+d7
+a3
+40
+18
+2d
+44
+54
+fb
+21
+09
+40
+75
+4e
+ef
+f1
+30
+25
+6e
+97
+78
+44
+f7
+ae
+33
+cc
+4d
+63
+8a
+d2
+07
+1a
+a3
+c4
+67
+14
+9e
+a8
+88
+91
+8a
+86
+05
+b3
--- /dev/null
+; Tests integer constant handling (for output, not parsing)
+
+db 0x51
+dw 0x3875
+dd 0x35783134
+dq 0xABCDEF0123456789
+dt 0xa907bc890d0e907f0134
+
--- /dev/null
+51
+75
+38
+34
+31
+78
+35
+89
+67
+45
+23
+01
+ef
+cd
+ab
+34
+01
+7f
+90
+0e
+0d
+89
+bc
+07
+a9