-#define READ8_SEG(SEG, var) ({ \
- u8 __value; \
- __asm__ __volatile__("movb %%" #SEG ":%1, %b0" \
- : "=Qi"(__value) : "m"(var)); \
- __value; })
-#define READ16_SEG(SEG, var) ({ \
- u16 __value; \
- __asm__ __volatile__("movw %%" #SEG ":%1, %w0" \
- : "=ri"(__value) : "m"(var)); \
- __value; })
-#define READ32_SEG(SEG, var) ({ \
- u32 __value; \
- __asm__ __volatile__("movl %%" #SEG ":%1, %0" \
- : "=ri"(__value) : "m"(var)); \
- __value; })
-#define WRITE8_SEG(SEG, var, value) \
- __asm__ __volatile__("movb %b0, %%" #SEG ":%1" \
- : : "Q"(value), "m"(var))
-#define WRITE16_SEG(SEG, var, value) \
- __asm__ __volatile__("movw %w0, %%" #SEG ":%1" \
- : : "r"(value), "m"(var))
-#define WRITE32_SEG(SEG, var, value) \
- __asm__ __volatile__("movl %0, %%" #SEG ":%1" \
- : : "r"(value), "m"(var))
-
-extern void __force_link_error__unknown_type();
-
-#define __GET_VAR(seg, var) ({ \
- typeof(var) __val; \
- if (__builtin_types_compatible_p(typeof(__val), u8)) \
- __val = READ8_SEG(seg, var); \
- else if (__builtin_types_compatible_p(typeof(__val), u16)) \
- __val = READ16_SEG(seg, var); \
- else if (__builtin_types_compatible_p(typeof(__val), u32)) \
- __val = READ32_SEG(seg, var); \
- else \
- __force_link_error__unknown_type(); \
+// Dummy definitions used to make sure gcc understands dependencies
+// between SET_SEG and GET/READ/WRITE_SEG macros.
+extern u16 __segment_ES, __segment_CS, __segment_DS, __segment_SS;
+extern u16 __segment_FS, __segment_GS;
+
+// Low level macros for reading/writing memory via a segment selector.
+#define READ8_SEG(prefix, SEG, value, var) \
+ __asm__(prefix "movb %%" #SEG ":%1, %b0" : "=Qi"(value) \
+ : "m"(var), "m"(__segment_ ## SEG))
+#define READ16_SEG(prefix, SEG, value, var) \
+ __asm__(prefix "movw %%" #SEG ":%1, %w0" : "=ri"(value) \
+ : "m"(var), "m"(__segment_ ## SEG))
+#define READ32_SEG(prefix, SEG, value, var) \
+ __asm__(prefix "movl %%" #SEG ":%1, %0" : "=ri"(value) \
+ : "m"(var), "m"(__segment_ ## SEG))
+#define READ64_SEG(prefix, SEG, value, var) do { \
+ union u64_u32_u __value; \
+ union u64_u32_u *__r64_ptr = (union u64_u32_u *)&(var); \
+ READ32_SEG(prefix, SEG, __value.hi, __r64_ptr->hi); \
+ READ32_SEG(prefix, SEG, __value.lo, __r64_ptr->lo); \
+ *(u64*)&(value) = __value.val; \
+ } while (0)
+#define WRITE8_SEG(prefix, SEG, var, value) \
+ __asm__(prefix "movb %b1, %%" #SEG ":%0" : "=m"(var) \
+ : "Q"(value), "m"(__segment_ ## SEG))
+#define WRITE16_SEG(prefix, SEG, var, value) \
+ __asm__(prefix "movw %w1, %%" #SEG ":%0" : "=m"(var) \
+ : "r"(value), "m"(__segment_ ## SEG))
+#define WRITE32_SEG(prefix, SEG, var, value) \
+ __asm__(prefix "movl %1, %%" #SEG ":%0" : "=m"(var) \
+ : "r"(value), "m"(__segment_ ## SEG))
+#define WRITE64_SEG(prefix, SEG, var, value) do { \
+ union u64_u32_u __value; \
+ union u64_u32_u *__w64_ptr = (union u64_u32_u *)&(var); \
+ typeof(var) __value_tmp = (value); \
+ __value.val = *(u64*)&__value_tmp; \
+ WRITE32_SEG(prefix, SEG, __w64_ptr->hi, __value.hi); \
+ WRITE32_SEG(prefix, SEG, __w64_ptr->lo, __value.lo); \
+ } while (0)
+
+// Macros for automatically choosing the appropriate memory size
+// access method.
+extern void __force_link_error__unknown_type(void);
+
+#define __GET_VAR(prefix, seg, var) ({ \
+ typeof(var) __val; \
+ if (sizeof(__val) == 1) \
+ READ8_SEG(prefix, seg, __val, var); \
+ else if (sizeof(__val) == 2) \
+ READ16_SEG(prefix, seg, __val, var); \
+ else if (sizeof(__val) == 4) \
+ READ32_SEG(prefix, seg, __val, var); \
+ else if (sizeof(__val) == 8) \
+ READ64_SEG(prefix, seg, __val, var); \
+ else \
+ __force_link_error__unknown_type(); \