bignum@math.keio.ac.jp (NIIMI Makoto) (05/28/90)
Posting-number: Volume 13, Issue 11 Submitted-by: bignum@math.keio.ac.jp (NIIMI Makoto) Archive-name: gcc-os9_68k/part07 Here is a documentation of GCC Version 1.37 for OSK. The distributed file is a compressed output from command `diff -rc2N'. Please decompress it and patch original files of gcc 1.37. It contains a new subdirectory `osksrc'. To boot and use GCC, you need OS-9/68000 (OSK) of Version 2.2 or later and MicroWare's C compiler of Version 3.0 or later. I would like to thank Takao Shinohara, Takeshi Yamada, Makoto Niimi, Akihiro Kosakada, Susumu Hara and Yoshinori Tanaka for their helpfull advices and bug reports. Without their supports, it was difficult for me to transport GCC to OSK. 90/05/07 Atsushi Seyama 5-7-20 HIGASHI MACHI, HOYA, TOKYO, JAPAN (Zip code 202) [I] Summary of system GCC for OSK is a system which uses gcc as a compiler driver, cccp as a preprocessor, cc1 as a compiler (all porting from GNU C), r68(020) as an assembler and l68 as a linker (these are standard Microware's commands). It also uses Microware's standard header files and libraries. Microware's OSK is distinguished from any other operating systems by unique position independent coding and modular structure . This nature of OSK required to introduce a new definition, DATA_REF referring to data area into GNU's compiler cc1 for transporting GCC system. The rest of work is concentrated to compromize the difference of the specifications of two OSs and to overcome the original bugs in OSK system itself. [II] Install GCC To compile GCC by Microware's C compiler (Version Version 3.0), you take following steps. 1) At first, copy files from directory config as shown below. $ copy config/m68osk.md md $ copy config/tm_osk.h tm.h $ copy config/out_osk.c aux_output.c $ copy config/xm_osk.h config.h 2) Next generate source file cexp.c from cexp.y using Bison. $ Bison -o cexp.c cexp.y We need GNU's cccp even when compiling GCC by Micrware C. Cexp.c is a one of source files of GNU's cccp. If you don't have Bison, you must port it. Changes are simple. a) change tmp_base in files.c for your system, and `unlink' temporary files after `fclose' it. b) #define bcopy via memcpy as in config/xm_osk.h. c) assemble osksrc/alloca.a and link it. d) change macro PARSERDIR in Makefile for your system. PARSERDIR is a directory in which Bison assumes bison.simple and bison.hairy to exist. 3) Change macros home_gcc and HOST_LIBDIR in Makefile.osk for your system. 4) Finally, execute shell script bootosk.sh. Then bootosk.sh performs three stages of compilation: stage0 to compile GCC via Microware's C. stage1 to compile GCC via GCC obtained by stage0. stage2 to compile GCC via GCC obtained by stage1. After the completion of the last stage, bootosk.sh compares objects created at stage1 and at stage2 to ensure the validity. If the objects coincide, bootsh.osk prints how to installe GCC. Bootosk.sh requires about 2MB of free area in memory and about 5MB of disk storage. [III] Implementation of compiler 1) Predefined macros Predefined macros of GCC for OSK are __GNUC__, __OSK__, __mc68000__. If you don't specify option `-ansi', OSK and mc68000 are also predefined. Macros __mc68020__ and mc68020 are not predefined although you specify option -mc68020 (or -m68020) to generate codes for 68020. 2) Size and format of fundamental data types They are the same as in Microware C. `long double' of ANSI standard C is the same as `double'. 64 bits integer `long long int' of GNU's extension has little endian format, i.e., high 4 bytes in lower address and low 4 bytes in higher address. Alignment of structure and union is the same as in Microware C at least those in standard header files are concerned. 3) Environment variables affecting the execution of GCC a) TMPDIR If an environment variable `TMPDIR' is defined, its value is regarded as a path of directory in which gcc makes temporary files. If not, gcc makes temporary files in the current working directory. Using gcc's option `-T', you can specify another directory for temporary files. b) GCCDEF If an environment variable GCCDEF is defined, its value is taken as a path of directory in which gcc searches header files. If it is not defined or if header files are not found in that directory, gcc examines directories /DD/DEFS, /H0/DEFS, /D0/DEFS in this order. You can use gcc's option `-I' to specify directories for searching header files prior to any of above directories. c) GCCLIB If an environment variable GCCLIB is defined, its value is taken as a path of directory in which gcc searches library files, e.g., system's standard library files, startup file `cstart.r' and files specified by -l option. If it is not defined or if library files are not found, gcc examines directories /DD/GNULIB, /H0/GNULIB, /D0/GNULIB in this order. You can use gcc's option `-L' to specify directories for searching library files prior to any of above directories. d) GCC_EXEC_PREFIX The effect of environment variable GCC_EXEC_PREFIX is same as original gcc. One exception is that if a module is in memory, gcc uses it. Standard prefixes are /D0/CMDS/gcc_ and /H0/CMDS/gcc_. 4) Misc. To define a variable, its definition is admitted only once regardless of the existence of initializer. [IV] Differences between GCC and Microware C 1) Register usages Microware C generates codes which use d2 and d3 as temporary registers. GCC generates codes which use d2 and d3 as registers being alive across function call. If you need compatibility, you can use gcc's options `-fcall-used-d2' and `-fcall-used-d3'. Then GCC treats d2 and d3 as temporary registers, and codes generated are less efficient. 2) Structure and union as function argument and return value To get structure/union value, Microware C generates codes that caller passes a pointer to static area, and callee sets the value on the area which pointer points. GCC uses similar mechanism, but passed pointer points automatic area, so that the callee is reentrant. Microware's convention is the same as that of PCC, and is not reentrant, but if you use gcc's option `-fpcc-struct-return', then GCC uses PCC's convention and you get the compatibility. In Microware C, structure/union arguments are always passed by stack, and once an argument is passed by stack, subsequent arguments are passed by stack. In contrast to the usual register calling convention, the convention is hardly to understand for most users. In GCC, structure/union arguments are also passed by registers if registers are available and if the size is small enough to fit into registers. So at this point, there is no compatibility between Microware C and GCC. 3) Variable number of parameters (stdarg.h) Function prototypes shall be declared before the use of functions with variable number of parameters, except library functions, printf, fprintf, sprintf, scanf, fscanf and sscanf. For these functions, function prototypes should not be declared. 4) Sizeof Sizeof of Microware C returns signed integer as described in K&R first edition. That of GCC returns unsigned integer as described in ANSI standard C. 5) Special extension of Microware C The special features of Microware C are not available in GCC except escape sequence `\l' representing linefeed character. 6) Float.h There are bugs in Microware's libraries, so that float.h isn't present. Bugs are that scanf reads floating points of small absolute value incorrectly. 7) GCC's extension for OSK Option `-mremote' allocates all data in `remote vsect'. It may help to port a program which uses big array. The default is `-mnoremote' and all data are allocated in `vsect'. Option `-mgss' defines additional global symbol for static function. The name of the global symbol is of the form function_name@file_name. It may help your symbolic debugging. The default is `-mnogss'. Option `-mnostack-check' inhibits to generate codes that checks stack overflow. The default is `-mstack-check'. Other new options may be clear, and probably no misunderstanding arises. You will find a brief description of options by `gcc -?'. Cccp also accepts option `-?'. [V] Changes and reason Three categories of works were done to transport GCC to OSK. 1) Exptension of GCC's data type to fulfill the separate data area access requirement of OSK. 2) To adapt the Microware OSK and C specification to that of GCC. 3) Detour the bugs of Microware C. In principle, all changes are conditionalized by macro definitions. Followings are new macros to be introduced for this perpose. a) MWC68 It is used to enclose bugs of Microware C. b) NO_BIT_FIELD If it is defined, source files of GCC never use bit-field. Microware C supports bit-field, but there are bugs, so that it is defined if MWC68 is defined. c) HAVE_SEPARATE_DATA_AREA DATA_REF takes effects only if this macro is defined. One exception against this principle is the common definition of variables. In this case, except one definition, I add `extern' silently to all other definitions of the variable. 1) Introduction of new DATA_REF Fundamental problem of porting GCC on OSK is that one can't use absolute addressing and one must use offset addressing from a6 to access the data. To represent assembler label, GCC use two RTL expressions, SYMBOL_REF and LABEL_REF. LABEL_REF represents assembler label which is a target of (conditional) branch instructions, and SYMBOL_REF is used to access the data. For OSK, Mr. Shinohara introduces DATA_REF to resolve the problem. He uses DATA_REF to access data in data area (vsect), and uses SYMBOL_REF only for accessing data in text area (psect) such as string literal. It is the only one major change for porting GCC on OSK. As described above, in source codes independent of target machine, changes concerning DATA_REF take effect only if macro HAVE_SEPARATE_DATA_AREA is defined. Folowings are the files containining DATA_REF and changes made; i) varasm.c Make_decl_rtl and output_constant_def generate RTL expressions SYMBOL_REF and DATA_REF. Constant data allocated in text area are string literal and arithmetic constants. No other constants are allocated in text area. For example, although a pointer is declared to be `const', it is allocated in data area. ii) combine.c, cse.c, emit_rtl.c, explow.c, expmed.c, final.c, flow.c, genconfig.c, genextract.c, integrate.c, jump.c, loop.c, recog.c, regclass.c, reload.c, reload1.c, rtl.c, rtl.def, rtl.h, rtlanal.c, stmt.c In rtl.def, DEF_RTL_EXPR of DATA_REF is added. In other files, codes for handling DATA_REF are added, those are almost all the same as for SYMBOL_REF. iii) m68osk.md, out_osk.c In out_osk.c, osk_data_ref_p, osk_data_addr_p, osk_symbol_ref_p and osk_symbol_addr_p are defined to detect SYMBOL_REF and DATA_REF in an insn. Another new function modify_memref is defined to convert %m in assembler output template to %p (resp. %v) if the corresponding operand is a memory reference via SYMBOL_REF (resp. DATA_REF). Modify_memref also supports code generation for the option `-mremote', and this is the real reason that the new function is needed. M68osk.md is a machine description for OSK based on original m68k.md. Almost all define-insn patterns are same as in m68k.md. Sun's fpa is not supported. In the constraint string of SImode (Pmode) operand, `s' and `i' which permit address calculations are replaced by `n'. One anonymous define-insn is added to calculate address. The C codes to generate assembler output template are changed as follows: if an insn uses SYMBOL_REF, it generates codes with pc-relative addressing mode. if an insn uses DATA_REF, it generates codes with constant offset addressing mode with base register a6. To write template easily, three output formats `%mN', `%pN' and `%vN' where N is a digit, are introduced. `%mN' indicates that the operand N may be a memory reference using SYMBOL_REF or DATA_REF. Such a template must be processed by modify_memref, and modify_memref converts `%m' to `%p' or `%v' appropriately. `%pN' is an abbreviation for `%N(pc)' and `%vN' is an abbreviation for `%N(a6)' or `(%N,a6)'. Note that direct references of a6 still remain in m68osk.md and in out_osk.c, and macro so called BASE_REGISTER_REGNO is not yet introduced. iv) rtl.h CONSTANT_P is true if CODE of an insn is DATA_REF. 2) For adapting GCC to the Microware OSK and C. First of all, character sets admitted for the file name are different between OSK and Un*x. The problem is that Un*x admits `-' but OSK does not admit `-'. So I replace all `-' in file names by `_', and names of include files are also changed in source files. i) xm_osk.h I don't use __builtin_alloca. Because size of memory alloca allocates is not predictable, for OSK which does not have virtual memory mechanism, an implementation of alloca that uses malloc as C-allcoa seems to be more flexible than __builtin_alloca that gets memory directory from the stack area. Incidentally, maximum size of memory allocated by alloca is about 25K when compiling GCC by GCC. ii) tm_m68k.h Since sun's fpa is not supported, `enum reg_class' is different from other systems. iii) tm_osk.h It is based on the original tm_m68k.h, but many macros were changed as follows; PREFERRED_RELOAD_CLASS, CONST_COSTS DATA_REF is taken into account. FIXED_REGISTERS, CALL_USED_REGISTER, CONDITIONAL_REGISTER_USAGE, FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM Fundamental usage of hardware registers is described. A6 and a7 are fixed-registers; d0, d1, a0, a1, a6 and a7 are call-used-registers; a5 is the frame-pointer and the argument-pointer. If you specify -mremote, CONDITIONAL_REGISTER_USAGE marks d2 and d3 as fixed registers and call-used registers. In this case, d2 and d3 are used for loading 32bit constant offset. LIBCALL_VALUE, FUNCTION_ARG_REGNO_P, FUNCTION_ARG, FUNCTION_ARG_PARTIAL_NREGS On GCC for OSK, function's arguments are passed by registers d0 and d1. No argument is passed partly in register and partly in stack. FUNCTION_PROLOGUE, FUNCTION_EPILOGUE Output codes are adapted for the use of r68. No support of fpa simplifies macros. In FUNCTION_PROLOGUE, __stack_check is called, which is a function to check stack overflow and is defined in gnulibosk.c. In FUNCTION_EPILOGUE, function free_allocaed is called if alloca is used in the function. It frees memory alloca allocates. FUNCTION_PROFILER, FUNCTION_BLOCK_PROFILER, BLOCK_PROFILER The profiling is based on basic block profiler. No standard profiler is present on OSK, so codes are my own. SDB_DEBUGGING_INFO, DBX_DEBUGGING_INFO These debugging information is useless in OSK, so flags are undefined. TARGET_NEWLINE, TARGET_LF TARGET_NEWLINE is defined to be 015. The code is the same as TARGET_CR, and there is no code for linefeed. TARGET_LF exists only for OSK, and its value is defined to be 012. TARGET_LF provides the value of the escape sequence `\l' representing linefeed character. CPP_PREDEFINES, LINK_SPEC, STARTFILE_SPEC, LIB_SPEC Predefined macros are `OSK' and `mc68000'. Other specs are defined appropriately. You can't use math trap handler from GCC. TARGET_SWITCHES OSK specific switches (no)remote, (no)stack-check and (no)gss are defined. For effects of these switches, see below. OVERRIDE_OPTIONS It forces `flag_shared_data' to be 1. DOLLARS_IN_IDENTIFIER It is defined to be 1. TARGET_MEM_FUNCTIONS It is defined to use memcpy memset and memcmp that are included in OSK libraries. ASM_FILE_START, ASM_FILE_END, ASM_IDENTIFY_GCC ASM_APP_ON, ASM_APP_OFF, TEXT_SECTION_ASM_OP, DATA_SECTION_ASM_OP, ASM_OUTPUT_LABELREF, ASM_OUTPUT_DOUBLE, ASM_OUTPUT_FLOAT, ASM_OUTPUT_INT, ASM_OUTPUT_SHORT, ASM_OUTPUT_CHAR, ASM_OUTPUT_BYTE, ASM_OUTPUT_REG_PUSH, ASM_OUTPUT_REG_POP, ASM_OUTPUT_ADDR_VEC_ELT, ASM_OUTPUT_ADDR_DIFF_ELT, ASM_OUTPUT_ALIGN, ASM_OUTPUT_SKIP, ASM_OUTPUT_LOCAL, ASM_OUTPUT_FLOAT_OPERAND, ASM_OUTPUT_DOUBLE_OPERAND, PRINT_OPERAND_ADDRESS These macros are changed so as to output a text suitable for r68(020), Microware's standard relocatable assembler. ASM_OUTPUT_LABEL, ASM_GLOBALIZE_LABEL For a label to be global, r68 requires that the label name in definition ends with `:'. The convention is different from Unix, and original ASM_OUTPUT_LABEL/ASM_GLOBALIZE_LABEL do not work well. A global variable label_is_global defined in varasm.c is introduced to recover the difference. ASM_DECLARE_FUNCTION_NAME It is defined to support the option `-mgss'. ASM_OUTPUT_INTERNAL_LABEL, ASM_GENERATE_INTERNAL_LABEL To avoid the name conflicts, internal labels generated by the compiler end with `.'. PRINT_OPERAND It processes new output formats %pN and %vN. It does not support %d for absolute addressing. Also it does not support sun's fpa. ASM_OUTPUT_ASCII It outputs strings for the use of r68. It is never defined in tm_m68k.h. TARGET_FPA, REGNO_OSK_FOR_FPA_P, FPA_REG_P Because sun's fpa is not supported, these macros are undefined. FIRST_PSEUDO_REGISTER, HARD_REGNO_MODE_OK, REG_CLASS_NAMES, REG_CLASS_CONTENTS, REGNO_REG_CLASS, REG_CLASS_FROM_LETTER, CONST_DOUBLE_OK_FOR_LETTER_P, CLASS_MAX_NREGS, NOTICE_UPDATE_CC, REGISTER_NAMES Because sun's fpa is not supported, these macros are simplified. iv) c_parse.y, c_exp.y Parse_escape in c_exp.y and skip_white_space, readescape, yylex in c_parse.y support special escape sequence `\l' which represents linefeed. The code is taken from the macro TARGET_LF defined in tm_osk.h. v) expr.c, stmt.c Stack check codes are generated at three points; at the entry of function; at the entry of a block in which array of dynamic size is defined; and at the call of __builtin_alloca. FUNCTION_PROLOGUE generates stack check codes at the entry of function. In stmt.c, expand_decl generates stack check insns at the entry of a block. In expr.c, expand_builtin generates stack check insns at the call of __builtin_alloca. Note that gen_probe is not suitable because it is called after stack grows. vi) gccosk.c It is a source file of compiler driver gcc for OSK. It is provided only for the use of OSK, because there are many changes as follows. As a first difference, OSK's system call fork is something like Un*x's fork plus exec, so that gcc's codes to create process are changed. Similarly usage of pipe in OSK is different from Un*x, and corresponding codes are changed. Next, OSK's syntax of option with an argument looks like -o=output and it is different from Un*x's style. So gcc is changed to generate both style of options. Other changes are OSK specific. At first, OSK's gcc removes temporary files as soon as possible. Secondarily, OSK's linker lacks option to specify directories to be searched for libraries, so OSK's gcc processes the option `-LDIR' for users' sake. Thirdly, linker l68 sometimes aborts by stack overflow, so an option `-F' is added to specify additional stack size of processes forked by OSK's gcc. By this option you can specify also their priority. vii) cccp.c Microware's preprocessor can't expand long macro, and Microware C compiler c68 can't process long lines. Thus Microware C compiler system can't compile GCC by itself, and we use additionally GNU's cccp to compile GCC. A special option `-K' is added to cccp, and under `-K', cccp outputs text suitable for the input of c68. viii) gnulibosk.c It is a gnulib.c for OSK. New function __stack_check is added, which detects runtime stack overflow. Other functions are the same as in the original gnulib.c. The reason of rewriting is as follows. 1) GCC's register usage is different from Microware C. Microware C generates codes that use d2 and d3 as temporary registers, but GCC for OSK generates codes that use d2 and d3 as register to live across function call. So gnulib.c compiled by Microware C may clobber d2 and d3, and it must be rewritten. 2) GCC's argument passing convention is different from Microware C. Although Microware C generates codes which use registers to pass arguments, structure/union arguments are passed by stack and once an argument is passed by stack, subsequent arguments are also passed by stack. On the other hand, GCC generates codes which use registers to pass structure/union arguments if its sizeof is small enough. Since original gnulib.c use arguments of union type, it must be rewritten. ix) final.c It supports profile code generation. Because OSK does not provide OS level profiling, Un*x's style of profiler is not supported. Option `-p' generates profile codes to count the number of function calls. It is implemented as a part basic block profiler. The basic block profiler is now in stage of experiment, and no report command nor libraries for profiling are included in the distribution. x) bootosk.sh, Makefile.osk These are Shell script and makefile to boot GCC. Makefile got dirty because it supports both Un*x style options and those of OSK. xi) osksrc/ It is a new directory used to boot GCC for OSK. It contains source file of library functions, and a makefile to make cccp and cppcccp. xi-1) osksrc/Makefile It is a makefile to make objects cppcccp, cccp, move_if_change and really_new. Cppcccp and cccp are used in stage0 booting, where cccp helps Microware C to compile GCC. Other objects move_if_change and really_new are used in all stages of booting GCC. (Do you believe me if I say Microware's make needs "really_new"? Oh! trust me, please.) xi-2) osksrc/cppcccp.c Cppcccp is a name of an executable file, which contains executable module named cpp. When compiling GCC by Microware C, it is loaded into memory. Then Microware cc forks cpp and cpp forks GNU's cccp to preprocess source files. xi-3) osksrc/config.h It is needed to compile cccp by pure Microware C compiler. As stated before, Microware's preprocessor does not expand long macros, so the proper config.h can't be used. It contains minimum number of #defines for compiling cccp. xi-4) osksrc/alloca.a It is an alloca based on alloca.c and adapted to OSK. The reason that original alloca.c is not adequate to OSK is as follows. Codes generated by Microware C use the stack-pointer as base register to access local variables, and local variables in a block are allocated dynamically. So a call of alloca in a block of a function may free a memory segment allocated by alloca in an inner block of the same function. It is undesirable since memory allocated by alloca must be alive until the function returns. The adaptaion is done by using frame-pointer a5 instead of stack-pointer a7 to mark level of alloca to be called, so it is safe to use both in Microware C and GCC. xi-5) osksrc/getcd.c It is a replacement of getwd. Getcd is a function returning current working/execution directory. xi-6) osksrc/move_if_change.c OSK's shell is so poor and it can't execute original move-if-change. Move_if_change.c is a substitution of move-if-change written by C. xi-7) osksrc/really_new.c Really_new is a command used in Makefile.osk. Function is self-explanatory from its name. It is worth nothing to try to understand why such command is needed in a makefile. So please simply accept it. I have nothing to say about brain-damaged Microware's make. xi-8) osksrc/ldexp.c, osksrc/perror.c, osksrc/qsort.c, osksrc/stat.c, osksrc/stat.h, osksrc/varargs.h These are OSK specific standard Un*x library functions and header file. Qsort.c is taken from tahoe library. Qsort.c is needed because register usage is different between Microware C and GCC. You can use varargs.h both in Microware C and GCC. 3) To avoid bugs of Microware C and OSK i) tm_osk.h (ASM_OUTPUT_COMMON) Microware's assembler and linker support `com.b' for common definition, but there are bugs, so it can't be used. Instead, `ds.b' is used. ii) genoutput.c There is a bug in kernel (Version 2.2) which does not allow to execute modules with data size beyond 64KB. If you compile GCC Version 1.37 without changes, its data size exceeds 64KB, and you can't execute cc1. Thus the types of elements of tables which genoutput generates are changed to `short' where it is possible. iii) recog.h Corresponding to the change of types of elements of tables described above, declarations of tables are changed.