mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-04-12 18:40:23 +08:00
data: replace data->sign with a flags field
Signed and unsigned are really two flags; might as well allow this field to contain additional flags. Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
parent
f399172a83
commit
79fd2b9645
@ -301,24 +301,16 @@ static void warn_overflow_const(int64_t data, int size)
|
||||
warn_overflow(size);
|
||||
}
|
||||
|
||||
static void warn_overflow_out(int64_t data, int size, enum out_sign sign)
|
||||
static void warn_overflow_out(int64_t data, int size, enum out_flags flags)
|
||||
{
|
||||
bool err;
|
||||
|
||||
switch (sign) {
|
||||
case OUT_WRAP:
|
||||
err = overflow_general(data, size);
|
||||
break;
|
||||
case OUT_SIGNED:
|
||||
if (flags & OUT_SIGNED)
|
||||
err = overflow_signed(data, size);
|
||||
break;
|
||||
case OUT_UNSIGNED:
|
||||
else if (flags & OUT_UNSIGNED)
|
||||
err = overflow_unsigned(data, size);
|
||||
break;
|
||||
default:
|
||||
panic();
|
||||
break;
|
||||
}
|
||||
else
|
||||
err = overflow_general(data, size);
|
||||
|
||||
if (err)
|
||||
warn_overflow(size);
|
||||
@ -393,11 +385,14 @@ static void out(struct out_data *data)
|
||||
nasm_assert(data->size <= 8);
|
||||
asize = data->size;
|
||||
amax = ofmt->maxbits >> 3; /* Maximum address size in bytes */
|
||||
if ((ofmt->flags & OFMT_KEEP_ADDR) == 0 && data->tsegment == fixseg &&
|
||||
if (!(ofmt->flags & OFMT_KEEP_ADDR) &&
|
||||
data->tsegment == fixseg &&
|
||||
data->twrt == NO_SEG) {
|
||||
if (asize >= (size_t)(data->bits >> 3))
|
||||
data->sign = OUT_WRAP; /* Support address space wrapping for low-bit modes */
|
||||
warn_overflow_out(addrval, asize, data->sign);
|
||||
if (asize >= (size_t)(data->bits >> 3)) {
|
||||
/* Support address space wrapping for low-bit modes */
|
||||
data->flags &= ~OUT_SIGNMASK;
|
||||
}
|
||||
warn_overflow_out(addrval, asize, data->flags);
|
||||
xdata.q = cpu_to_le64(addrval);
|
||||
data->data = xdata.b;
|
||||
data->type = OUT_RAWDATA;
|
||||
@ -428,7 +423,7 @@ static void out(struct out_data *data)
|
||||
dfmt->linenum(lnfname, lineno, data->segment);
|
||||
|
||||
if (asize > amax) {
|
||||
if (data->type == OUT_RELADDR || data->sign == OUT_SIGNED) {
|
||||
if (data->type == OUT_RELADDR || (data->flags & OUT_SIGNED)) {
|
||||
nasm_nonfatal("%u-bit signed relocation unsupported by output format %s",
|
||||
(unsigned int)(asize << 3), ofmt->shortname);
|
||||
} else {
|
||||
@ -506,17 +501,17 @@ static void out_segment(struct out_data *data, const struct operand *opx)
|
||||
if (opx->opflags & OPFLAG_RELATIVE)
|
||||
nasm_nonfatal("segment references cannot be relative");
|
||||
|
||||
data->type = OUT_SEGMENT;
|
||||
data->sign = OUT_UNSIGNED;
|
||||
data->size = 2;
|
||||
data->toffset = opx->offset;
|
||||
data->tsegment = ofmt->segbase(opx->segment | 1);
|
||||
data->twrt = opx->wrt;
|
||||
data->type = OUT_SEGMENT;
|
||||
data->flags = OUT_UNSIGNED;
|
||||
data->size = 2;
|
||||
data->toffset = opx->offset;
|
||||
data->tsegment = ofmt->segbase(opx->segment | 1);
|
||||
data->twrt = opx->wrt;
|
||||
out(data);
|
||||
}
|
||||
|
||||
static void out_imm(struct out_data *data, const struct operand *opx,
|
||||
int size, enum out_sign sign)
|
||||
int size, enum out_flags sign)
|
||||
{
|
||||
if (opx->segment != NO_SEG && (opx->segment & 1)) {
|
||||
/*
|
||||
@ -531,10 +526,10 @@ static void out_imm(struct out_data *data, const struct operand *opx,
|
||||
data->type = (opx->opflags & OPFLAG_RELATIVE)
|
||||
? OUT_RELADDR : OUT_ADDRESS;
|
||||
}
|
||||
data->sign = sign;
|
||||
data->toffset = opx->offset;
|
||||
data->flags = sign;
|
||||
data->toffset = opx->offset;
|
||||
data->tsegment = opx->segment;
|
||||
data->twrt = opx->wrt;
|
||||
data->twrt = opx->wrt;
|
||||
/*
|
||||
* XXX: improve this if at some point in the future we can
|
||||
* distinguish the subtrahend in expressions like [foo - bar]
|
||||
@ -553,13 +548,13 @@ static void out_reladdr(struct out_data *data, const struct operand *opx,
|
||||
if (opx->opflags & OPFLAG_RELATIVE)
|
||||
nasm_nonfatal("invalid use of self-relative expression");
|
||||
|
||||
data->type = OUT_RELADDR;
|
||||
data->sign = OUT_SIGNED;
|
||||
data->size = size;
|
||||
data->toffset = opx->offset;
|
||||
data->type = OUT_RELADDR;
|
||||
data->flags = OUT_SIGNED;
|
||||
data->size = size;
|
||||
data->toffset = opx->offset;
|
||||
data->tsegment = opx->segment;
|
||||
data->twrt = opx->wrt;
|
||||
data->relbase = data->offset + (data->inslen - data->insoffs);
|
||||
data->twrt = opx->wrt;
|
||||
data->relbase = data->offset + (data->inslen - data->insoffs);
|
||||
out(data);
|
||||
}
|
||||
|
||||
@ -660,12 +655,12 @@ static void out_eops(struct out_data *data, const extop *e)
|
||||
data->relbase = 0;
|
||||
if (e->val.num.segment != NO_SEG &&
|
||||
(e->val.num.segment & 1)) {
|
||||
data->type = OUT_SEGMENT;
|
||||
data->sign = OUT_UNSIGNED;
|
||||
data->type = OUT_SEGMENT;
|
||||
data->flags = OUT_UNSIGNED;
|
||||
} else {
|
||||
data->type = e->val.num.relative
|
||||
? OUT_RELADDR : OUT_ADDRESS;
|
||||
data->sign = OUT_WRAP;
|
||||
data->flags = OUT_WRAP;
|
||||
}
|
||||
out(data);
|
||||
}
|
||||
|
@ -111,10 +111,11 @@ enum out_type {
|
||||
OUT_REL8ADR
|
||||
};
|
||||
|
||||
enum out_sign {
|
||||
OUT_WRAP, /* Undefined signedness (wraps) */
|
||||
OUT_SIGNED, /* Value is signed */
|
||||
OUT_UNSIGNED /* Value is unsigned */
|
||||
enum out_flags {
|
||||
OUT_WRAP = 0, /* Undefined signedness (wraps) */
|
||||
OUT_SIGNED = 1, /* Value is signed */
|
||||
OUT_UNSIGNED = 2, /* Value is unsigned */
|
||||
OUT_SIGNMASK = 3 /* Mask for signedness bits */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -126,7 +127,7 @@ struct out_data {
|
||||
int64_t offset; /* Offset within segment */
|
||||
int32_t segment; /* Segment written to */
|
||||
enum out_type type; /* See above */
|
||||
enum out_sign sign; /* See above */
|
||||
enum out_flags flags; /* See above */
|
||||
int inslen; /* Length of instruction */
|
||||
int insoffs; /* Offset inside instruction */
|
||||
int bits; /* Bits mode of compilation */
|
||||
@ -908,7 +909,7 @@ struct ofmt {
|
||||
* It is allowed to modify the string it is given a pointer to.
|
||||
*
|
||||
* It is also allowed to specify a default instruction size for
|
||||
* the segment, by setting `*bits' to 16 or 32. Or, if it
|
||||
* the segment, by setting `*bits' to 16, 32 or 64. Or, if it
|
||||
* doesn't wish to define a default, it can leave `bits' alone.
|
||||
*/
|
||||
int32_t (*section)(char *name, int *bits);
|
||||
|
@ -90,13 +90,13 @@ void nasm_do_legacy_output(const struct out_data *data)
|
||||
case OUT_SEGMENT:
|
||||
type = OUT_ADDRESS;
|
||||
dptr = zero_buffer;
|
||||
size = (data->sign == OUT_SIGNED) ? -data->size : data->size;
|
||||
size = (data->flags & OUT_SIGNED) ? -data->size : data->size;
|
||||
tsegment |= 1;
|
||||
break;
|
||||
|
||||
case OUT_ADDRESS:
|
||||
dptr = &data->toffset;
|
||||
size = (data->sign == OUT_SIGNED) ? -data->size : data->size;
|
||||
size = (data->flags & OUT_SIGNED) ? -data->size : data->size;
|
||||
break;
|
||||
|
||||
case OUT_RAWDATA:
|
||||
|
@ -181,30 +181,45 @@ static const char *out_type(enum out_type type)
|
||||
return out_types[type];
|
||||
}
|
||||
|
||||
static const char *out_sign(enum out_sign sign)
|
||||
static const char *out_flags(enum out_flags flags)
|
||||
{
|
||||
static const char *out_signs[] = {
|
||||
"wrap",
|
||||
static const char *out_flags[] = {
|
||||
"signed",
|
||||
"unsigned"
|
||||
};
|
||||
static char invalid_buf[64];
|
||||
static char flags_buf[1024];
|
||||
unsigned long flv = flags;
|
||||
size_t n;
|
||||
size_t left = sizeof flags_buf - 1;
|
||||
char *p = flags_buf;
|
||||
unsigned int i;
|
||||
|
||||
if (sign >= sizeof(out_signs)/sizeof(out_signs[0])) {
|
||||
sprintf(invalid_buf, "[invalid sign %d]", sign);
|
||||
return invalid_buf;
|
||||
for (i = 0; flv; flv >>= 1, i++) {
|
||||
if (flv & 1) {
|
||||
if (i < ARRAY_SIZE(out_flags))
|
||||
n = snprintf(p, left, "%s,", out_flags[i]);
|
||||
else
|
||||
n = snprintf(p, left, "%u,", i);
|
||||
if (n >= left)
|
||||
break;
|
||||
left -= n;
|
||||
p += n;
|
||||
}
|
||||
}
|
||||
if (p > flags_buf)
|
||||
p--; /* Delete final comma */
|
||||
*p = '\0';
|
||||
|
||||
return out_signs[sign];
|
||||
return flags_buf;
|
||||
}
|
||||
|
||||
static void dbg_out(const struct out_data *data)
|
||||
{
|
||||
fprintf(ofile,
|
||||
"out to %"PRIx32":%"PRIx64" %s %s bits %d insoffs %d/%d "
|
||||
"out to %"PRIx32":%"PRIx64" %s(%s) bits %d insoffs %d/%d "
|
||||
"size %"PRIu64,
|
||||
data->segment, data->offset,
|
||||
out_type(data->type), out_sign(data->sign),
|
||||
out_type(data->type), out_flags(data->flags),
|
||||
data->bits, data->insoffs, data->inslen, data->size);
|
||||
if (data->itemp) {
|
||||
fprintf(ofile, " ins %s(%d)",
|
||||
@ -521,7 +536,7 @@ const struct ofmt of_dbg = {
|
||||
"Trace of all info passed to output stage",
|
||||
"dbg",
|
||||
".dbg",
|
||||
OFMT_TEXT,
|
||||
OFMT_TEXT|OFMT_KEEP_ADDR,
|
||||
64,
|
||||
debug_debug_arr,
|
||||
&debug_debug_form,
|
||||
|
Loading…
x
Reference in New Issue
Block a user