diff --git a/asm/assemble.c b/asm/assemble.c index d45fc329..cd58723b 100644 --- a/asm/assemble.c +++ b/asm/assemble.c @@ -1748,28 +1748,34 @@ static void gencode(struct out_data *data, insn *ins) case4(0274): { - int64_t uv; + uint64_t uv, um; int s; - if (absolute_op(opx)) { - if (ins->rex & REX_W) - s = 64; - else if (ins->prefixes[PPS_OSIZE] == P_O16) - s = 16; - else if (ins->prefixes[PPS_OSIZE] == P_O32) - s = 32; - else - s = bits; + if (ins->rex & REX_W) + s = 64; + else if (ins->prefixes[PPS_OSIZE] == P_O16) + s = 16; + else if (ins->prefixes[PPS_OSIZE] == P_O32) + s = 32; + else + s = bits; - /* - * Forcibly discard bits irrelevant for our needs, to - * prevent bogus warnings. + um = (uint64_t)2 << (s-1); + uv = opx->offset; + + if (uv > 127 && uv < (uint64_t)-128 && + (uv < um-128 || uv > um-1)) { + /* If this wasn't explicitly byte-sized, warn as though we + * had fallen through to the imm16/32/64 case. */ - uv = opx->offset; - uv = (uv << (64-s)) >> (64-s); - opx->offset = uv; + nasm_error(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV, + "%s value exceeds bounds", + (opx->type & BITS8) ? "signed byte" : + s == 16 ? "word" : + s == 32 ? "dword" : + "signed dword"); } - out_imm(data, opx, 1, OUT_SIGNED); + out_imm(data, opx, 1, OUT_WRAP); /* XXX: OUT_SIGNED? */ break; }