Add linker magic to ensure 16bit variables aren't repeated in 32bit code.

Add VAR16 macro to enable a variable to be available in both 32bit and
    16bit code.  This reduces the occurrences of "#if MODE16".
Also add ASM16 macro to reduce occurrences of "#if MODE16".
diff --git a/src/clock.c b/src/clock.c
index 43b8379..4590adc 100644
--- a/src/clock.c
+++ b/src/clock.c
@@ -51,10 +51,7 @@
 #define PIT_TICK_RATE 1193182 // Underlying HZ of PIT
 #define CALIBRATE_COUNT 0x800 // Approx 1.7ms
 
-extern u32 cpu_khz;
-#if MODE16
-u32 cpu_khz VISIBLE16;
-#endif
+u32 cpu_khz VAR16;
 
 static void
 calibrate_tsc()
diff --git a/src/floppy.c b/src/floppy.c
index c880478..6354bd8 100644
--- a/src/floppy.c
+++ b/src/floppy.c
@@ -20,8 +20,7 @@
 // Since no provisions are made for multiple drive types, most
 // values in this table are ignored.  I set parameters for 1.44M
 // floppy here
-#if MODE16 == 1
-struct floppy_ext_dbt_s diskette_param_table2 VISIBLE16 = {
+struct floppy_ext_dbt_s diskette_param_table2 VAR16 = {
     .dbt = {
         .specify1       = 0xAF,
         .specify2       = 0x02, // head load time 0000001, DMA used
@@ -39,7 +38,6 @@
     .data_rate      = 0,    // data transfer rate
     .drive_type     = 4,    // drive type in cmos
 };
-#endif
 
 void
 floppy_drive_setup()
diff --git a/src/floppy_dbt.c b/src/floppy_dbt.c
index c04d222..c391d9e 100644
--- a/src/floppy_dbt.c
+++ b/src/floppy_dbt.c
@@ -9,7 +9,7 @@
 // Since no provisions are made for multiple drive types, most
 // values in this table are ignored.  I set parameters for 1.44M
 // floppy here
-struct floppy_dbt_s diskette_param_table __aligned(1) VISIBLE16 = {
+struct floppy_dbt_s diskette_param_table __aligned(1) VAR16 = {
     .specify1       = 0xAF,
     .specify2       = 0x02, // head load time 0000001, DMA used
     .shutoff_ticks  = 0x25,
diff --git a/src/pnpbios.c b/src/pnpbios.c
index 6f36a4a..21d140a 100644
--- a/src/pnpbios.c
+++ b/src/pnpbios.c
@@ -27,9 +27,8 @@
 extern struct pnpheader PNPHEADER;
 extern const char pnp_string[];
 
-#if MODE16
-# if CONFIG_PNPBIOS
-struct pnpheader PNPHEADER __aligned(16) VISIBLE16 = {
+#if CONFIG_PNPBIOS
+struct pnpheader PNPHEADER __aligned(16) VAR16 = {
     .signature = PNP_SIGNATURE,
     .version = 0x10,
     .length = sizeof(PNPHEADER),
@@ -38,12 +37,11 @@
     .real_ds = SEG_BIOS,
     .prot_database = BUILD_BIOS_ADDR,
 };
-# else
+#else
 // We need a copy of this string in the 0xf000 segment, but we are not
 // actually a PnP BIOS, so make sure it is *not* aligned, so OSes will
 // not see it if they scan.
-const char pnp_string[] __aligned(2) VISIBLE16 = " $PnP";
-# endif
+const char pnp_string[] __aligned(2) VAR16 = " $PnP";
 #endif
 
 #define FUNCTION_NOT_SUPPORTED 0x82
diff --git a/src/rombios.lds.S b/src/rombios.lds.S
index e3527ac..1305c40 100644
--- a/src/rombios.lds.S
+++ b/src/rombios.lds.S
@@ -22,4 +22,5 @@
                 final_code16_fixed_start = . ;
                 *(.text16.fixed.addr)
                 }
+        /DISCARD/ : { *(.discard.var16) }
 }
diff --git a/src/smpdetect.c b/src/smpdetect.c
index 0274026..202a82a 100644
--- a/src/smpdetect.c
+++ b/src/smpdetect.c
@@ -46,11 +46,9 @@
     return *(volatile const u8 *)addr;
 }
 
+u32 smp_cpus VAR16;
 extern void smp_ap_boot_code();
-extern u32 smp_cpus;
-#if MODE16
-u32 smp_cpus VISIBLE16;
-asm(
+ASM16(
     "  .global smp_ap_boot_code\n"
     "smp_ap_boot_code:\n"
     // Increment the cpu counter
@@ -60,7 +58,6 @@
     // Halt the processor.
     "  jmp permanent_halt\n"
     );
-#endif
 
 /* find the number of CPUs by launching a SIPI to them */
 int
diff --git a/src/system.c b/src/system.c
index 6615b31..fcbbaf6 100644
--- a/src/system.c
+++ b/src/system.c
@@ -266,11 +266,9 @@
     set_success(regs);
 }
 
-#if MODE16
 // Info on e820 map location and size.
-struct e820entry *e820_list VISIBLE16;
-int e820_count VISIBLE16;
-#endif
+struct e820entry *e820_list VAR16;
+int e820_count VAR16;
 
 static void
 handle_15e820(struct bregs *regs)
diff --git a/src/types.h b/src/types.h
index 8dd1a3b..f7a0e9a 100644
--- a/src/types.h
+++ b/src/types.h
@@ -22,14 +22,21 @@
 };
 
 #define __VISIBLE __attribute__((externally_visible))
+
 #if MODE16 == 1
 // Notes a function as externally visible in the 16bit code chunk.
-#define VISIBLE16 __VISIBLE
+# define VISIBLE16 __VISIBLE
 // Notes a function as externally visible in the 32bit code chunk.
-#define VISIBLE32
+# define VISIBLE32
+// Designate a variable as visible to both 32bit and 16bit code.
+# define VAR16 __VISIBLE
+// Designate top-level assembler as 16bit only.
+# define ASM16(code) asm(code)
 #else
-#define VISIBLE16
-#define VISIBLE32 __VISIBLE
+# define VISIBLE16
+# define VISIBLE32 __VISIBLE
+# define VAR16 __VISIBLE __attribute__((section(".discard.var16"))) __attribute__((weak))
+# define ASM16(code)
 #endif
 
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)