Added methods for efficiently declaring and accessing variables in
authorMichael Brown <mcb30@etherboot.org>
Thu, 4 May 2006 17:00:20 +0000 (17:00 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 4 May 2006 17:00:20 +0000 (17:00 +0000)
.data16.  librm will need to supply "char *data16", i.e. the virtual
address of the start of .data16.

src/arch/i386/include/libkir.h
src/arch/i386/include/librm.h
src/arch/i386/include/realmode.h

index 144ea79..44cb75e 100644 (file)
  *
  */
 
+/* Access to variables in .data16, in a way compatible with librm */
+#define __data16( variable ) variable
+#define __use_data16( variable ) variable
+
 /* Copy to/from base memory */
 
 static inline void copy_to_real_libkir ( uint16_t dest_seg, uint16_t dest_off,
index 76ef8d6..b4970c0 100644 (file)
  *
  */
 
+/* Access to variables in .data16 */
+extern char *data16;
+
+#define __data16( variable )                                           \
+       _data16_ ## variable __asm__ ( #variable )                      \
+       __attribute__ (( section ( ".data16" ) ))
+
+#define __use_data16( variable )                                       \
+       ( * ( ( typeof ( _data16_ ## variable ) * )                     \
+             & ( data16 [ ( size_t ) & ( _data16_ ## variable ) ] ) ) )
+
 /* Variables in librm.S, present in the normal data segment */
 extern uint16_t rm_sp;
 extern uint16_t rm_ss;
index f14aae2..b7f0dc9 100644 (file)
@@ -38,6 +38,50 @@ typedef struct {
  *
  */
 
+/*
+ * Declaration of variables in .data16
+ *
+ * To place a variable in the .data16 segment, declare it using the
+ * pattern:
+ *
+ *   int __data16 ( foo );
+ *   #define foo __use_data16 ( foo );
+ *
+ *   extern uint32_t __data16 ( bar );
+ *   #define bar __use_data16 ( bar );
+ *
+ *   extern long __data16 ( baz ) = 0xff000000UL;
+ *   #define bar __use_data16 ( baz );
+ *
+ * i.e. take a normal declaration, add __data16() around the variable
+ * name, and add a line saying "#define <name> __use_data16 ( <name> )
+ *
+ * You can then access them just like any other variable, for example
+ *
+ *   int x = foo + bar;
+ *
+ * This magic is achieved at a cost of only around 7 extra bytes per
+ * group of accesses to .data16 variables.  When using KEEP_IT_REAL,
+ * there is no extra cost.
+ *
+ * You should place variables in .data16 when they need to be accessed
+ * by real-mode code.  Real-mode assembly (e.g. as created by
+ * REAL_EXEC()) can access these variables via the usual data segment.
+ * You can therefore write something like
+ *
+ *   static uint16_t __data16 ( foo );
+ *   #define foo __use_data16 ( foo )
+ *
+ *   int bar ( void ) {
+ *     REAL_EXEC ( baz,
+ *                 "int $0xff\n\t"
+ *                 "movw %ax, foo",
+ *                 ... );
+ *     return foo;
+ *   }
+ *
+ */
+
 /*
  * void copy_to_real ( uint16_t dest_seg, uint16_t dest_off,
  *                    void *src, size_t n )