Remove the --allow-64-bits option and make it a warning

Remove the --allow-64-bits relocation, and instead make it a
suppressible warning in the case of a zero-extended relocation, and an
error in the case of a sign-extended relocation.

Relocations which can be losslessly represented in the output format
do not issue any diagnostic at all, as there is no problem in that
case.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
diff --git a/assemble.c b/assemble.c
index 4976c46..8382b89 100644
--- a/assemble.c
+++ b/assemble.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 1996-2014 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2016 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -308,7 +308,8 @@
 /*
  * This routine wrappers the real output format's output routine,
  * in order to pass a copy of the data off to the listing file
- * generator at the same time.
+ * generator at the same time, flatten unnecessary relocations,
+ * and verify backend compatibility.
  */
 static void out(int64_t offset, int32_t segto, const void *data,
                 enum out_type type, uint64_t size,
@@ -317,6 +318,9 @@
     static int32_t lineno = 0;     /* static!!! */
     static char *lnfname = NULL;
     uint8_t p[8];
+    const int asize = abs((int)size); /* True address size */
+    const int abits = asize << 3;   /* Address size in bits */
+    const int amax  = maxbits >> 3; /* Maximum address size in bytes */
 
     if (type == OUT_ADDRESS && segment == NO_SEG && wrt == NO_SEG) {
         /*
@@ -325,13 +329,12 @@
          */
         uint8_t *q = p;
         
-        size = abs((int)size);
-        if (size > 8) {
+        if (asize > 8) {
             errfunc(ERR_PANIC, "OUT_ADDRESS with size > 8");
             return;
         }
 
-        WRITEADDR(q, *(int64_t *)data, size);
+        WRITEADDR(q, *(int64_t *)data, asize);
         data = p;
         type = OUT_RAWDATA;
     }
@@ -350,6 +353,22 @@
     if (src_get(&lineno, &lnfname))
         outfmt->current_dfmt->linenum(lnfname, lineno, segto);
 
+    if (type == OUT_ADDRESS && abits > maxbits) {
+        if (asize < 0) {
+            errfunc(ERR_NONFATAL,
+                    "%d-bit signed relocation unsupported by output format %s\n",
+                    abits, outfmt->shortname);
+        } else {
+            errfunc(ERR_WARNING | ERR_WARN_ZEXTRELOC,
+                    "%d-bit unsigned relocation zeroq-padded from %d bits\n",
+                    abits, maxbits);
+            outfmt->output(segto, data, type, amax, segment, wrt);
+            size -= amax;
+        }
+        data = zero_buffer;
+        type = OUT_RAWDATA;
+    }
+
     outfmt->output(segto, data, type, size, segment, wrt);
 }
 
diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src
index ec0cfcc..4b5078a 100644
--- a/doc/nasmdoc.src
+++ b/doc/nasmdoc.src
@@ -1010,16 +1010,6 @@
 some, but not all, system calling conventions.
 
 
-\S{opt-allow64bit} The \i\c{--allow-64-bit} Option.
-
-The \c{--allow-64-bit} option allows using 64-bit instructions in a
-32-bit or 16-bit output format.  This is useful in a few situations,
-such as when writing code switching from 32-bit to 64-bit mode and
-linking into a 32-bit module.  However, it is important to be aware of
-the restriction the output format poses on you in terms of
-relocations.  Use with caution!
-
-
 \S{nasmenv} The \i\c{NASMENV} \i{Environment} Variable
 
 If you define an environment variable called \c{NASMENV}, the program
diff --git a/nasm.c b/nasm.c
index 17ee553..e48f0a9 100644
--- a/nasm.c
+++ b/nasm.c
@@ -88,7 +88,6 @@
 bool tasm_compatible_mode = false;
 int pass0, passn;
 int maxbits = 0;
-static bool allow_64_bit = false;
 int globalrel = 0;
 int globalbnd = 0;
 
@@ -169,6 +168,7 @@
     {"lock", "lock prefix on unlockable instructions", true},
     {"hle", "invalid hle prefixes", true},
     {"bnd", "invalid bnd prefixes", true},
+    {"zero-reloc", "relocation zero-extended to match output format", true},
 };
 
 static bool want_usage;
@@ -618,12 +618,10 @@
 enum text_options {
     OPT_PREFIX,
     OPT_POSTFIX,
-    OPT_ALLOW_64_BIT
 };
 struct textargs textopts[] = {
     {"prefix", OPT_PREFIX},
     {"postfix", OPT_POSTFIX},
-    {"allow-64-bit", OPT_ALLOW_64_BIT},
     {NULL, 0}
 };
 
@@ -981,9 +979,7 @@
                         }
                         break;
                     }
-                case OPT_ALLOW_64_BIT:
-                    allow_64_bit = true;
-                    break;
+
                 default:
                     {
                         nasm_error(ERR_NONFATAL | ERR_NOFILE | ERR_USAGE,
@@ -2101,12 +2097,6 @@
                          "cannot specify 64-bit segment on processor below an x86-64");
             i = 16;
         }
-        if (i != maxbits && !allow_64_bit) {
-            nasm_error(ERR_NONFATAL,
-                         "%s output format does not support 64-bit code",
-                         ofmt->shortname);
-            i = 16;
-        }
     } else {
         nasm_error(pass0 < 2 ? ERR_NONFATAL : ERR_FATAL,
                      "`%s' is not a valid segment size; must be 16, 32 or 64",
diff --git a/nasm.h b/nasm.h
index 8bc2571..bd1f290 100644
--- a/nasm.h
+++ b/nasm.h
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *   
- *   Copyright 1996-2014 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2016 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
diff --git a/nasmlib.h b/nasmlib.h
index 24db573..47e9a0a 100644
--- a/nasmlib.h
+++ b/nasmlib.h
@@ -125,7 +125,8 @@
 #define ERR_WARN_LOCK		WARN(12) /* bad LOCK prefixes */
 #define ERR_WARN_HLE		WARN(13) /* bad HLE prefixes */
 #define ERR_WARN_BND		WARN(14) /* bad BND prefixes */
-#define ERR_WARN_MAX            14       /* the highest numbered one */
+#define ERR_WARN_ZEXTRELOC	WARN(15) /* relocation zero-extended */
+#define ERR_WARN_MAX            15       /* the highest numbered one */
 
 /*
  * Wrappers around malloc, realloc and free. nasm_malloc will