diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2012-05-24 22:06:39 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2012-05-24 22:06:39 -0400 |
commit | b54ee404d7fc439ddbbd8cdf29404c6517ad8abd (patch) | |
tree | 81cdb2d43be5e75fd58674121799c5a8c92a186a /src/farptr.h | |
parent | 33d5118d4482bc6e7ec08680c1fe343bd2c73d1f (diff) | |
download | seabios-b54ee404d7fc439ddbbd8cdf29404c6517ad8abd.tar.gz |
Use inline functions instead of macros for GET/SET_SEG segment manipulation.
It appears that gcc does a better job of optimization when the
SET_SEG() segment assignment assembler code is contained in an inline
function. With the code in a function gcc appears to be able to
optimize out many redundant segment register loads. Removing some of
these unnecessarily loads makes the code both smaller and faster.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/farptr.h')
-rw-r--r-- | src/farptr.h | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/src/farptr.h b/src/farptr.h index 3dbf545c..3a85c6b8 100644 --- a/src/farptr.h +++ b/src/farptr.h @@ -79,15 +79,29 @@ extern void __force_link_error__unknown_type(void); __force_link_error__unknown_type(); \ } while (0) +#define DECL_SEGFUNCS(SEG) \ +static inline void __set_seg_##SEG(u16 seg) { \ + __asm__("movw %w1, %%" #SEG : "=m"(__segment_##SEG) \ + : "rm"(seg)); \ +} \ +static inline u16 __get_seg_##SEG(void) { \ + u16 res; \ + __asm__("movw %%" #SEG ", %w0" : "=rm"(res) \ + : "m"(__segment_##SEG)); \ + return res; \ +} +DECL_SEGFUNCS(CS) +DECL_SEGFUNCS(DS) +DECL_SEGFUNCS(ES) +DECL_SEGFUNCS(FS) +DECL_SEGFUNCS(GS) +DECL_SEGFUNCS(SS) + // Low level macros for getting/setting a segment register. -#define __SET_SEG(SEG, value) \ - __asm__("movw %w1, %%" #SEG : "=m"(__segment_ ## SEG) \ - : "rm"(value)) -#define __GET_SEG(SEG) ({ \ - u16 __seg; \ - __asm__("movw %%" #SEG ", %w0" : "=rm"(__seg) \ - : "m"(__segment_ ## SEG)); \ - __seg;}) +#define __SET_SEG(SEG, value) \ + __set_seg_##SEG(value) +#define __GET_SEG(SEG) \ + __get_seg_##SEG() // Macros for accessing a variable in another segment. (They // automatically update the %es segment and then make the appropriate |