It occurred to me that reserving %ebx is unnecessary because gcc can calculate the code offset when it needs it.
This patch is on top of the 32bit PCI BIOS series.
-Kevin
diff --git a/Makefile b/Makefile index a5fd63d..b71d1a1 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ CFLAGS32FLAT = $(COMMONCFLAGS) -g -DMODE16=0 -DMODESEGMENT=0 CFLAGSSEG = $(COMMONCFLAGS) -DMODESEGMENT=1 -fno-defer-pop \ $(call cc-option,$(CC),-fno-jump-tables,-DMANUAL_NO_JUMP_TABLE) \ $(call cc-option,$(CC),-fno-tree-switch-conversion,) -CFLAGS32SEG = $(CFLAGSSEG) -DMODE16=0 +CFLAGS32SEG = $(CFLAGSSEG) -DMODE16=0 -g CFLAGS16INC = $(CFLAGSSEG) -DMODE16=1 \ $(call cc-option,$(CC),--param large-stack-frame=4,) CFLAGS16 = $(CFLAGS16INC) -g diff --git a/src/biosvar.h b/src/biosvar.h index eb34286..db6783e 100644 --- a/src/biosvar.h +++ b/src/biosvar.h @@ -263,18 +263,28 @@ get_ebda_ptr() #if MODE16 == 0 && MODESEGMENT == 1 // In 32bit segmented mode %cs may not be readable and the code may be // relocated. The entry code sets up %gs with a readable segment and -// %ebx with the base code offset. +// the code offset can be determined by get_global_offset(). #define GLOBAL_SEGREG GS -#define GLOBAL_OFFSET __CodeOffset +static inline u32 __attribute_const get_global_offset(void) { + u32 ret; + asm(" calll 1f\n" + "1:popl %0\n" + " subl $1b, %0" + : "=r"(ret)); + return ret; +} #else #define GLOBAL_SEGREG CS -#define GLOBAL_OFFSET 0 +static inline u32 __attribute_const get_global_offset(void) { + return 0; +} #endif static inline u16 get_global_seg() { return GET_SEG(GLOBAL_SEGREG); } -#define GET_GLOBAL(var) \ - GET_VAR(GLOBAL_SEGREG, *(typeof(&(var)))((void*)&(var) + GLOBAL_OFFSET)) +#define GET_GLOBAL(var) \ + GET_VAR(GLOBAL_SEGREG, *(typeof(&(var)))((void*)&(var) \ + + get_global_offset())) #define SET_GLOBAL(var, val) do { \ ASSERT32FLAT(); \ (var) = (val); \ diff --git a/src/pcibios.c b/src/pcibios.c index 91b7655..2425a65 100644 --- a/src/pcibios.c +++ b/src/pcibios.c @@ -157,7 +157,8 @@ handle_1ab10e(struct bregs *regs)
// Memcpy pir table slots to dest buffer. memcpy_far(buf_seg, buf_far - , get_global_seg(), (void*)(pirtable_g->slots) + GLOBAL_OFFSET + , get_global_seg() + , (void*)(pirtable_g->slots) + get_global_offset() , pirsize);
// XXX - bochs bios sets bx to (1 << 9) | (1 << 11) diff --git a/src/romlayout.S b/src/romlayout.S index afdefed..43af112 100644 --- a/src/romlayout.S +++ b/src/romlayout.S @@ -390,9 +390,6 @@ pcibios32_entry: pushl %edi pushw %es pushw %ds - calll 1f // Setup %ebx to be code base -1: popl %ebx - subl $1b, %ebx movl %ds, %eax // Move %ds to %gs movl %eax, %gs movl %ss, %eax // Move %ss to %ds diff --git a/src/types.h b/src/types.h index cc64cba..cfa47fe 100644 --- a/src/types.h +++ b/src/types.h @@ -65,7 +65,6 @@ extern void __force_link_error__only_in_16bit() __attribute__ ((noreturn)); #define ASSERT16() do { } while (0) #define ASSERT32FLAT() __force_link_error__only_in_32bit_flat() #elif MODESEGMENT == 1 -register u32 __CodeOffset asm ("ebx") __VISIBLE; # define VISIBLE16 # define VISIBLE32FLAT # define VISIBLE32SEG __VISIBLE @@ -122,6 +121,7 @@ register u32 __CodeOffset asm ("ebx") __VISIBLE;
#define noinline __attribute__((noinline)) #define __always_inline inline __attribute__((always_inline)) +#define __attribute_const __attribute__((__const__))
#define __stringify_1(x) #x #define __stringify(x) __stringify_1(x)