summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-07-03 20:12:37 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-07-03 20:12:37 -0700
commit45f22924ea0b8d2459d4f7d8a883ad325f196ba9 (patch)
tree675d5abfc78f521304f16731406127bd879dfdee
parent5aa689f80d66830181044b2977ded7d3c605cd5f (diff)
downloadnasm-45f22924ea0b8d2459d4f7d8a883ad325f196ba9.tar.gz
nasm-45f22924ea0b8d2459d4f7d8a883ad325f196ba9.tar.bz2
nasm-45f22924ea0b8d2459d4f7d8a883ad325f196ba9.zip
float: support packed-BCD constants in 'dt' statements
Support packed-BCD constants in 'dt' statements (and elsewhere 80-bit floating point is handled), using MASM syntax (terminal 'p').
-rw-r--r--float.c77
1 files changed, 70 insertions, 7 deletions
diff --git a/float.c b/float.c
index 467eafa..5e73372 100644
--- a/float.c
+++ b/float.c
@@ -492,7 +492,7 @@ static bool ieee_flconvert_bin(const char *string, int bits,
int32_t twopwr;
bool seendot, seendigit;
unsigned char c;
- int radix = 1 << bits;
+ const int radix = 1 << bits;
fp_limb v;
twopwr = 0;
@@ -638,21 +638,84 @@ enum floats {
FL_SNAN
};
-static int to_float(const char *str, int s, uint8_t * result,
+static int to_packed_bcd(const char *str, const char *strend,
+ int s, uint8_t *result,
+ const struct ieee_format *fmt)
+{
+ int n = 0;
+ char c;
+ int tv = -1;
+ const char *p = strend-2;
+
+ if (fmt != &ieee_80) {
+ error(ERR_NONFATAL|ERR_PASS1,
+ "packed BCD requires an 80-bit format");
+ return 0;
+ }
+
+ while (p >= str) {
+ c = *p--;
+ if (c >= '0' && c <= '9') {
+ if (tv < 0) {
+ if (n == 9) {
+ error(ERR_WARNING|ERR_PASS1,
+ "packed BCD truncated to 18 digits");
+ }
+ tv = c-'0';
+ } else {
+ if (n < 9)
+ *result++ = tv + ((c-'0') << 4);
+ n++;
+ tv = -1;
+ }
+ } else if (c == '_') {
+ /* do nothing */
+ } else {
+ error(ERR_NONFATAL|ERR_PASS1,
+ "invalid character `%c' in packed BCD constant", c);
+ return 0;
+ }
+ }
+ if (tv >= 0) {
+ if (n < 9)
+ *result++ = tv;
+ n++;
+ }
+ while (n < 9) {
+ *result++ = 0;
+ n++;
+ }
+ *result = (s < 0) ? 0x80 : 0;
+
+ return 1; /* success */
+}
+
+static int to_float(const char *str, int s, uint8_t *result,
const struct ieee_format *fmt)
{
fp_limb mant[MANT_LIMBS];
int32_t exponent = 0;
- int32_t expmax = 1 << (fmt->exponent - 1);
+ const int32_t expmax = 1 << (fmt->exponent - 1);
fp_limb one_mask = LIMB_TOP_BIT >>
((fmt->exponent+fmt->explicit) % LIMB_BITS);
- int one_pos = (fmt->exponent+fmt->explicit)/LIMB_BITS;
+ const int one_pos = (fmt->exponent+fmt->explicit)/LIMB_BITS;
int i;
int shift;
enum floats type;
bool ok;
- bool minus = s < 0;
- int bits = fmt->bytes * 8;
+ const bool minus = s < 0;
+ const int bits = fmt->bytes * 8;
+ const char *strend;
+
+ if (!str[0]) {
+ error(ERR_PANIC,
+ "internal errror: empty string passed to float_const");
+ return 0;
+ }
+
+ strend = strchr(str, '\0');
+ if (strend[-1] == 'P' || strend[-1] == 'p')
+ return to_packed_bcd(str, strend, s, result, fmt);
if (str[0] == '_') {
/* Special tokens */
@@ -810,7 +873,7 @@ static int to_float(const char *str, int s, uint8_t * result,
return 1; /* success */
}
-int float_const(const char *number, int sign, uint8_t * result,
+int float_const(const char *number, int sign, uint8_t *result,
int bytes, efunc err)
{
error = err;