Version 0.1.1
[seabios.git] / src / farptr.h
1 // Code to access multiple segments within gcc.
2 //
3 // Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU GPLv3 license.
6
7 #define READ8_SEG(SEG, var) ({                                          \
8     u8 __value;                                                         \
9     __asm__ __volatile__("movb %%" #SEG ":%1, %b0"                      \
10                          : "=Qi"(__value) : "m"(var));                  \
11     __value; })
12 #define READ16_SEG(SEG, var) ({                                         \
13     u16 __value;                                                        \
14     __asm__ __volatile__("movw %%" #SEG ":%1, %w0"                      \
15                          : "=ri"(__value) : "m"(var));                  \
16     __value; })
17 #define READ32_SEG(SEG, var) ({                                         \
18     u32 __value;                                                        \
19     __asm__ __volatile__("movl %%" #SEG ":%1, %0"                       \
20                          : "=ri"(__value) : "m"(var));                  \
21     __value; })
22 #define WRITE8_SEG(SEG, var, value)                     \
23     __asm__ __volatile__("movb %b0, %%" #SEG ":%1"      \
24                          : : "Q"(value), "m"(var))
25 #define WRITE16_SEG(SEG, var, value)                    \
26     __asm__ __volatile__("movw %w0, %%" #SEG ":%1"      \
27                          : : "r"(value), "m"(var))
28 #define WRITE32_SEG(SEG, var, value)                    \
29     __asm__ __volatile__("movl %0, %%" #SEG ":%1"       \
30                          : : "r"(value), "m"(var))
31
32 #define __GET_VAR(seg, var) ({                                  \
33     typeof(var) __val;                                          \
34     if (__builtin_types_compatible_p(typeof(__val), u8))        \
35         __val = READ8_SEG(seg, var);                            \
36     else if (__builtin_types_compatible_p(typeof(__val), u16))  \
37         __val = READ16_SEG(seg, var);                           \
38     else if (__builtin_types_compatible_p(typeof(__val), u32))  \
39         __val = READ32_SEG(seg, var);                           \
40     __val; })
41
42 #define __SET_VAR(seg, var, val) do {                             \
43         if (__builtin_types_compatible_p(typeof(var), u8))        \
44             WRITE8_SEG(seg, var, (val));                          \
45         else if (__builtin_types_compatible_p(typeof(var), u16))  \
46             WRITE16_SEG(seg, var, (val));                         \
47         else if (__builtin_types_compatible_p(typeof(var), u32))  \
48             WRITE32_SEG(seg, var, (val));                         \
49     } while (0)
50
51 #define __SET_SEG(SEG, value)                                   \
52     __asm__ __volatile__("movw %w0, %%" #SEG : : "r"(value))
53 #define __GET_SEG(SEG) ({                                       \
54     u16 __seg;                                                  \
55     __asm__ __volatile__("movw %%" #SEG ", %w0" : "=r"(__seg)); \
56     __seg;})
57
58 #ifdef MODE16
59 #define GET_VAR(seg, var) __GET_VAR(seg, var)
60 #define SET_VAR(seg, var, val) __SET_VAR(seg, var, val)
61 #define SET_SEG(SEG, value) __SET_SEG(SEG, value)
62 #define GET_SEG(SEG) __GET_SEG(SEG)
63 #else
64 // In 32-bit mode there is no need to mess with the segments.
65 #define GET_VAR(seg, var) (var)
66 #define SET_VAR(seg, var, val) (var) = (val)
67 #define SET_SEG(SEG, value) ((void)(value))
68 #define GET_SEG(SEG) 0
69 #endif
70
71 #define GET_FARVAR(seg, var) ({                 \
72     SET_SEG(ES, (seg));                         \
73     GET_VAR(ES, (var)); })
74 #define SET_FARVAR(seg, var, val) do {          \
75         SET_SEG(ES, (seg));                     \
76         SET_VAR(ES, (var), val);                \
77     } while (0)