diff options
-rw-r--r-- | Makefile | 25 | ||||
-rw-r--r-- | README | 43 | ||||
-rw-r--r-- | src/boot.c | 4 | ||||
-rw-r--r-- | src/post.c | 5 | ||||
-rw-r--r-- | src/resume.c | 4 | ||||
-rwxr-xr-x | tools/test-gcc.sh | 31 |
6 files changed, 44 insertions, 68 deletions
@@ -22,10 +22,9 @@ cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \ # Default compiler flags COMMONCFLAGS = -Wall -Os -MD -m32 -march=i386 -mregparm=3 \ -mpreferred-stack-boundary=2 -mrtd -freg-struct-return \ - $(call cc-option,$(CC),-fwhole-program -DWHOLE_PROGRAM,) \ -ffreestanding -fomit-frame-pointer \ -fno-delete-null-pointer-checks -Wno-strict-aliasing \ - -ffunction-sections -fdata-sections \ + -ffunction-sections -fdata-sections -fno-common \ -minline-all-stringops COMMONCFLAGS += $(call cc-option,$(CC),-nopie,) COMMONCFLAGS += $(call cc-option,$(CC),-fno-stack-protector,) @@ -59,28 +58,36 @@ vpath %.S src vgasrc ################ Build rules +# Verify the gcc configuration and test if -fwhole-program works. TESTGCC:=$(shell CC=$(CC) tools/test-gcc.sh) ifeq "$(TESTGCC)" "-1" $(error "Please upgrade GCC") endif -ifndef AVOIDCOMBINE -AVOIDCOMBINE=$(TESTGCC) +ifndef COMPSTRAT +COMPSTRAT=$(TESTGCC) endif -# Do a whole file compile - two methods are supported. The first -# involves including all the content textually via #include -# directives. The second method uses gcc's "-combine" option. -ifeq "$(AVOIDCOMBINE)" "1" +# Do a whole file compile - three methods are supported. +ifeq "$(COMPSTRAT)" "1" +# First method - use -fwhole-program without -combine. +define whole-compile +@echo " Compiling whole program $3" +$(Q)printf '$(foreach i,$2,#include "../$i"\n)' > $3.tmp.c +$(Q)$(CC) $1 -fwhole-program -DWHOLE_PROGRAM -c $3.tmp.c -o $3 +endef +else ifeq "$(COMPSTRAT)" "2" +# Second menthod - don't use -fwhole-program at all. define whole-compile @echo " Compiling whole program $3" $(Q)printf '$(foreach i,$2,#include "../$i"\n)' > $3.tmp.c $(Q)$(CC) $1 -c $3.tmp.c -o $3 endef else +# Third (and preferred) method - use -fwhole-program with -combine define whole-compile @echo " Compiling whole program $3" -$(Q)$(CC) $1 -combine -c $2 -o $3 +$(Q)$(CC) $1 -fwhole-program -DWHOLE_PROGRAM -combine -c $2 -o $3 endef endif @@ -4,11 +4,6 @@ compiled using standard gnu tools (eg, gas and gcc). To build, one should be able to run "make" in the main directory. The resulting file "out/bios.bin" contains the processed bios image. -The build requires gcc v4.1 or later. Some buggy versions of gcc have -issues with the '-combine' compiler option - in particular, recent -versions of Ubuntu are affected. One can use "make AVOIDCOMBINE=1" to -get around this. - Testing of images: @@ -51,8 +46,8 @@ Overview of files: The src/ directory contains the bios source code. Several of the files are compiled twice - once for 16bit mode and once for 32bit -mode. (The gcc compile option '-fwhole-program' is used to remove -code that is not needed for a particular mode.) +mode. (The build system will remove code that is not needed for a +particular mode.) The tools/ directory contains helper utilities for manipulating and building the final rom. @@ -64,10 +59,11 @@ temporary and final files. Build overview: The 16bit code is compiled via gcc to assembler (file out/ccode.16.s). -The gcc "-fwhole-program" option is used to optimize the process so -that gcc can efficiently compile and discard unneeded code. (In the -code, one can use the macros 'VISIBLE16' and 'VISIBLE32' to instruct a -symbol to be outputted in 16bit and 32bit mode respectively.) +The gcc "-fwhole-program" and "-ffunction-sections -fdata-sections" +options are used to optimize the process so that gcc can efficiently +compile and discard unneeded code. (In the code, one can use the +macros 'VISIBLE16' and 'VISIBLE32' to instruct a symbol to be +outputted in 16bit and 32bit mode respectively.) This resulting assembler code is pulled into romlayout.S. The gas option ".code16gcc" is used prior to including the gcc generated @@ -122,16 +118,17 @@ macros (GET/SET_GLOBAL, GET/SET_BDA, and GET/SET_EBDA) are available to simplify these accesses. Global variables defined in the C code can be read in 16bit mode if -the variable declaration is marked with VAR16 or VAR16_32. The -GET_GLOBAL macro will then allow read access to the variable. Global -variables are stored in the 0xf000 segment, and their values are -persistent across soft resets. Because the f-segment is marked -read-only during run-time, the 16bit code is not permitted to change -the value of 16bit variables (use of the SET_GLOBAL macro from 16bit -mode will cause a link error). Code running in 32bit mode can not -access variables with VAR16, but can access variables marked with -VAR16_32 or with no marking at all. The 32bit code can use the -GET/SET_GLOBAL macros, but they are not required. +the variable declaration is marked with VAR16, VAR16_32, VAR16EXPORT, +or VAR16FIXED. The GET_GLOBAL macro will then allow read access to +the variable. Global variables are stored in the 0xf000 segment, and +their values are persistent across soft resets. Because the f-segment +is marked read-only during run-time, the 16bit code is not permitted +to change the value of 16bit variables (use of the SET_GLOBAL macro +from 16bit mode will cause a link error). Code running in 32bit mode +can not access variables with VAR16, but can access variables marked +with VAR16_32, VAR16EXPORT, VAR16FIXED, or with no marking at all. +The 32bit code can use the GET/SET_GLOBAL macros, but they are not +required. GCC 16 bit stack limitations: @@ -158,8 +155,8 @@ structures can also help. It is also possible to transition to/from an extra stack stored in the EBDA using the stack_hop helper function. Some useful stats: the overhead for the entry to a bios handler that -takes a 'struct bregs' is 38 bytes of stack space (6 bytes from -interrupt insn, 28 bytes to store registers, and 4 bytes for call +takes a 'struct bregs' is 42 bytes of stack space (6 bytes from +interrupt insn, 32 bytes to store registers, and 4 bytes for call insn). An entry to an ISR handler without args takes 30 bytes (6 + 20 + 4). @@ -463,7 +463,3 @@ handle_19() SET_EBDA(boot_sequence, 0); do_boot(0); } - -// Ughh - some older gcc compilers have a bug which causes VISIBLE32 -// functions to not be exported as global variables. -asm(".global handle_18, handle_19"); @@ -220,8 +220,3 @@ _start() memset(&br, 0, sizeof(br)); call16_int(0x19, &br); } - -// Ughh - some older gcc compilers have a bug which causes VISIBLE32 -// functions to not be exported as a global variable - force _start -// to be global here. -asm(".global _start"); diff --git a/src/resume.c b/src/resume.c index 6db6b71..e7d4101 100644 --- a/src/resume.c +++ b/src/resume.c @@ -125,7 +125,3 @@ s3_resume() call16big(&br); } #endif - -// Ughh - some older gcc compilers have a bug which causes VISIBLE32 -// functions to not be exported as global variables. -asm(".global s3_resume"); diff --git a/tools/test-gcc.sh b/tools/test-gcc.sh index 55f359f..5b2d4a9 100755 --- a/tools/test-gcc.sh +++ b/tools/test-gcc.sh @@ -12,42 +12,27 @@ TMPFILE3o=out/tmp_testcompile3.o $CC -fwhole-program -S -o /dev/null -xc /dev/null > /dev/null 2>&1 if [ $? -ne 0 ]; then echo " Working around no -fwhole-program" > /dev/fd/2 - echo 1 + echo 2 exit 0 fi -# Test if "visible" variables are marked global. -cat - > $TMPFILE1 <<EOF -unsigned char t1 __attribute__((section(".data16.foo.19"))) __attribute__((externally_visible)); -EOF -$CC -Os -c -fwhole-program $TMPFILE1 -o $TMPFILE1o > /dev/null 2>&1 -cat - > $TMPFILE2 <<EOF -extern unsigned char t1; -int __attribute__((externally_visible)) main() { return t1; } -EOF -$CC -Os -c -fwhole-program $TMPFILE2 -o $TMPFILE2o > /dev/null 2>&1 -$CC -nostdlib -Os $TMPFILE1o $TMPFILE2o -o $TMPFILE3o > /dev/null 2>&1 -if [ $? -ne 0 ]; then - echo "This version of gcc does not properly handle" > /dev/fd/2 - echo " global variables in -fwhole-program mode." > /dev/fd/2 - echo "Please upgrade to a newer gcc (eg, v4.3 or later)" > /dev/fd/2 - echo -1 - exit 1 -fi - -# Test if "visible" functions are marked global. +# Test if "visible" variables and functions are marked global. cat - > $TMPFILE1 <<EOF void __attribute__((externally_visible)) t1() { } +unsigned char v1 __attribute__((section(".data16.foo.19"))) __attribute__((externally_visible)); EOF $CC -Os -c -fwhole-program $TMPFILE1 -o $TMPFILE1o > /dev/null 2>&1 cat - > $TMPFILE2 <<EOF void t1(); -void __attribute__((externally_visible)) main() { t1(); } +extern unsigned char v1; +int __attribute__((externally_visible)) main() { t1(); return v1; } EOF $CC -Os -c -fwhole-program $TMPFILE2 -o $TMPFILE2o > /dev/null 2>&1 $CC -nostdlib -Os $TMPFILE1o $TMPFILE2o -o $TMPFILE3o > /dev/null 2>&1 if [ $? -ne 0 ]; then - echo " Working around non-global functions in -fwhole-program" > /dev/fd/2 + echo " Working around non-functional -fwhole-program" > /dev/fd/2 + echo 2 + exit 0 fi # Test if "-combine" works |