Add tool for generating assembler offset definition file.

Replace __call16 hardcoded offsets with auto generated struct offsets.
Also, load/save %ds register in __call16().
diff --git a/Makefile b/Makefile
index 7bfb345..2c30945 100644
--- a/Makefile
+++ b/Makefile
@@ -86,11 +86,14 @@
 	@echo "  Precompiling $<"
 	$(Q)$(CPP) -P -D__ASSEMBLY__ $< -o $@
 
+$(OUT)asm-offsets.h: $(OUT)asm-offsets.16.s
+	@echo "  Generating offset file $@"
+	$(Q)./tools/gen-offsets.sh $< $@
 
 $(OUT)blob.16.s: ; $(call whole-compile, $(CFLAGS16) -S, $(addprefix src/, $(SRC16)),$@)
 
 TABLEASM=$(addprefix $(OUT), $(patsubst %.c,%.proc.16.s,$(TABLESRC)))
-$(OUT)romlayout16.o: romlayout.S $(OUT)blob.16.s $(TABLEASM)
+$(OUT)romlayout16.o: romlayout.S $(OUT)blob.16.s $(OUT)asm-offsets.h $(TABLEASM)
 	@echo "  Generating 16bit layout of $@"
 	$(Q)$(CC) $(CFLAGS16) -c -D__ASSEMBLY__ $< -o $@
 
diff --git a/src/asm-offsets.c b/src/asm-offsets.c
new file mode 100644
index 0000000..8f17c04
--- /dev/null
+++ b/src/asm-offsets.c
@@ -0,0 +1,21 @@
+// Generate assembler offsets.
+
+#include "gen-defs.h"
+#include "bregs.h"
+
+/* workaround for a warning with -Wmissing-prototypes */
+void foo(void) VISIBLE16;
+
+void foo(void)
+{
+    OFFSET(BREGS_es, bregs, es);
+    OFFSET(BREGS_ds, bregs, ds);
+    OFFSET(BREGS_eax, bregs, eax);
+    OFFSET(BREGS_ebx, bregs, ebx);
+    OFFSET(BREGS_ecx, bregs, ecx);
+    OFFSET(BREGS_edx, bregs, edx);
+    OFFSET(BREGS_esi, bregs, esi);
+    OFFSET(BREGS_edi, bregs, edi);
+    OFFSET(BREGS_flags, bregs, flags);
+    OFFSET(BREGS_ip, bregs, ip);
+}
diff --git a/src/gen-defs.h b/src/gen-defs.h
new file mode 100644
index 0000000..dabf64c
--- /dev/null
+++ b/src/gen-defs.h
@@ -0,0 +1,19 @@
+// Tool for building defintions accessible from assembler code.  This
+// is based on code from the Linux Kernel.
+#ifndef __GEN_DEFS_H
+#define __GEN_DEFS_H
+
+
+#define DEFINE(sym, val) \
+    asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+#define BLANK() \
+    asm volatile("\n->" : : )
+
+#define OFFSET(sym, str, mem) \
+    DEFINE(sym, offsetof(struct str, mem))
+
+#define COMMENT(x) \
+    asm volatile("\n->#" x)
+
+#endif // gen-defs.h
diff --git a/src/romlayout.S b/src/romlayout.S
index c1148ac..a6bad45 100644
--- a/src/romlayout.S
+++ b/src/romlayout.S
@@ -8,6 +8,7 @@
 #include "config.h" // CONFIG_*
 #include "ioport.h" // PORT_A20
 #include "bregs.h" // CR0_*
+#include "../out/asm-offsets.h" // BREGS_*
 
 
 /****************************************************************
@@ -240,17 +241,18 @@
         // Setup for iretw call
         pushw $SEG_BIOS
         pushw $1f               // return point
-        pushw 0x20(%eax)        // flags
-        pushl 0x1c(%eax)        // CS:IP
+        pushw BREGS_flags(%eax) // flags
+        pushl BREGS_ip(%eax)    // CS:IP
 
         // Load calling registers.
-        movl 0x04(%eax), %edi
-        movl 0x08(%eax), %esi
-        movl 0x0c(%eax), %ebx
-        movl 0x10(%eax), %edx
-        movl 0x14(%eax), %ecx
-        movw 0x02(%eax), %es    // XXX - should load %ds too
-        movl 0x18(%eax), %eax
+        movl BREGS_edi(%eax), %edi
+        movl BREGS_esi(%eax), %esi
+        movl BREGS_ebx(%eax), %ebx
+        movl BREGS_edx(%eax), %edx
+        movl BREGS_ecx(%eax), %ecx
+        movw BREGS_es(%eax), %es
+        movw BREGS_ds(%eax), %ds
+        movl %ss:BREGS_eax(%eax), %eax
 
         // Invoke call
         iretw                   // XXX - just do a lcalll
@@ -259,20 +261,21 @@
         pushfw
         pushl %eax
         movl 0x06(%esp), %eax
-        movl %ecx, %ss:0x14(%eax)       // Save %ecx
+        movl %ecx, %ss:BREGS_ecx(%eax)
+        movw %ds, %ss:BREGS_ds(%eax)
         movw %ss, %cx
-        movw %cx, %ds                   // Restore %ds == %ss
+        movw %cx, %ds           // Restore %ds == %ss
         popl %ecx
-        movl %ecx, 0x18(%eax)           // Save %eax
+        movl %ecx, BREGS_eax(%eax)
         popw %cx
-        movw %cx, 0x20(%eax)            // Save flags
+        movw %cx, BREGS_flags(%eax)
 
         // Store remaining registers
-        movw %es, 0x02(%eax)
-        movl %edi, 0x04(%eax)
-        movl %esi, 0x08(%eax)
-        movl %ebx, 0x0c(%eax)
-        movl %edx, 0x10(%eax)
+        movw %es, BREGS_es(%eax)
+        movl %edi, BREGS_edi(%eax)
+        movl %esi, BREGS_esi(%eax)
+        movl %ebx, BREGS_ebx(%eax)
+        movl %edx, BREGS_edx(%eax)
 
         // Remove %eax
         popl %eax
diff --git a/tools/gen-offsets.sh b/tools/gen-offsets.sh
new file mode 100755
index 0000000..99fdc53
--- /dev/null
+++ b/tools/gen-offsets.sh
@@ -0,0 +1,17 @@
+:
+# Extract definitions from an assembler file.  This is based on code
+# from the Linux Kernel.
+INFILE=$1
+OUTFILE=$2
+cat > "$OUTFILE" <<EOF
+// This is an auto-generated file.  DO NOT EDIT!
+// Generated with "$0 $@"
+#ifndef __ASM_OFFSETS_H
+#define __ASM_OFFSETS_H
+EOF
+sed -ne "/^->/{s:->#\(.*\):/* \1 */:; \
+        s:^->\([^ ]*\) [\$\#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
+        s:->::; p;}" < "$INFILE" >> "$OUTFILE"
+cat >> "$OUTFILE" <<EOF
+#endif // asm-offsets.h
+EOF