vbcc - C compiler (c) in 1995 by Volker Barthelmann INTRODUCTION vbcc shall be a free portable ANSI compliant C compiler. It is clearly split into a machine independant and a machine dependant part and supports emulating datatypes of the target machine on any other machine so that it is possible to e.g. make a crosscompiler for a 64bit machine on a 32bit machine. This document only deals with the machine dependant parts of the Amiga68k version. LEGAL vbcc is (c) in 1995 by Volker Barthelmann. All code is written by me and may be freely redistributed as long as no modifications are made and nothing is charged for it. Non-commercial usage of vbcc is allowed without any restrictions. Commercial usage needs my written consent. Sending me money, gifts, postcards etc. would of course be very nice and may encourage further development of vbcc, but is not legally or morally necessary to use vbcc. INSTALLATION Look at vc.doc. ADDITIONAL OPTIONS FOR THIS VERSION -cpu=n generates code for cpu n (e.g. -cpu=68020), default: 68000 -fpu=n generates code for fpu n (e.g. -fpu=68881), default: 0 -sd use small data model -sc use small code model -d2scratch use d2 as scratch register (for testing with certain C libraries) -noa4 don't use register a4 (for testing with certain C libraries) SOME INTERNALS The current version generates assembler output for use with the PhxAss assembler (c) by Frank Wille. Most peephole optimizations are done by the assembler so vbcc only does some that the assembler cannot make. The generated executables will probably only work with OS2.0 or higher. The registers d0, d1, a0, a1, fp0 and fp1 are used as scratch registers (i.e. they can be destroyed in function calls), all other registers are preserved. All elementary types up to 4 bytes are returned in register d0 like common on the Amiga (although I think pointers should better be returned in a0). If compiled for an fpu, floating point values are returned in fp0. All other types are returned by passing a pointer to a static object in d0 (may have to be changed). vbcc uses d0-d7 and a0-a6 for temporary results and register variables (a4 is used as small data pointer if -sd is used). a5 can be used as frame pointer for automatic variables (but this is not necessary - they can be accessed through a7, too). At the moment all local variables are addressed via (dist,ax), so a function may have only 32k of local variables if code for <=68000 is generated. The elementary data types are represented like: type size in bits alignment in bytes char 8 1 short 16 2 int 32 2 all pointers 32 2 float(fpu) 32 2 see below double(fpu) 64 2 see below Although it would be better to have all 32bit+ types aligned to 4 bytes I chose 2 bytes to be compatible with the Amiga system structures which unfortunately have longwords aligned to 4n+2-addresses. The amiga68k code generator at the moment only works on systems that store floats and doubles in the same way (IEEE) like the Amiga. SMALL DATA vbcc can access static data in two ways. By default all such data will be accessed with full 32bit addresses (large data model). However there is a second way. You can set up an address register (a4) to point into Your data segment and then address data with a 16bit offset through this register. The advantages of the small data model are that Your program will usually be smaller (because the 16bit offsets use less space and no relocation information is needed) and faster. The disadvantages are that one address register cannot be used by the compiler and that You can use it only if all Your static data occupies less than 64kb. Also You may not mix object modules and libraries that have been compiled with different data models (You can call functions compiled with large data model from object files compiled with small data model, but not vice versa and only functions can be called that way - other data cannot be accessed) and You probably have to use PhxLnk then. SMALL CODE If You use the small code model calls to external functions (i.e. from libraries or other object files) are done with 16bit offsets over the program counter rather than with absolute 32bit addresses. The advantage is slightly smaller and faster code. The disadvantages are that all the code (including library functions) must be small enough and that You may have to use PhxLnk. However You can link objects/libraries together if they have been compiled with different code models. CPUs At the moment the values of -cpu=n have those effects: n>=68020: - 32bit multiplication/division/modulo is done with the mul?.l, div?.l and div?l.l instructions - tst.l ax is used - extb.l dx is used - 16/32bit offsets are used in certain addressing modes - link.l is used - addressing modes with scaling are used - (dx) is used if no address register is available (not yet) FPUs At the moment the values of -fpu=n have those effects: n>68000: - floating point calculations are done using the fpu n=68040: n=68060: - instructions that have to be emulated on these fpus will not be used; at the moment this only includes the fintrz instruction MATH Integer math hopefully works without problems on all cpus. Long multiply on cpus <68020 uses inline routines. This may increase code size a bit, but it should be significantly faster, because function call overhead is not necessary and the compiler can use the registers which already contain the sources and/or need the result. However if anyone really wants an option for using library routines for multiply, this can easily be implemented. Long division and modulo is handled by calls to library functions. At the moment standard library calls with parameter passing via stack are used. This is rather slow, but division takes quite some time anyway. (mult/div/mod with constant powers of two are replaced by corresponding bitwise operations (mod only if the other operand is unsigned), but sums of powers of two not yet). If no FPU is specified floating point math is done using the C= math libraries. 32 bit IEEE format is used for float and 64 bit IEEE for double. Float return values are passed in d0 and double is passed via pointers. This is rather slow, so if You need good floating point performance specify an FPU. Floating point math is done with the FPU if one is specified (see above). Floating point values are kept in registers then and therefore may have extended precision sometimes, which is not ANSI compliant (but will usually cause no harm). When floating point values are stored in memory they use the same IEEE formats as without FPU. Float or double return values are passed in fp0. Note that You must not link object files together if they were not compiled with the same -fpu settings and that You have to link with the proper math library (see vclib.doc). OPTIMIZATION Bit 7 (128) The intermediate code does not contain any of the 68k addressing modes, so if they are to be used an extra pass over the intermediate code is necessary to recognize certain patterns that can be expressed using a 68k addresing mode. When bit 7 (128) is set with the -O=n option (or -O2 with vc), vbcc tries to use some 68k addressing modes. Currently (ax)+ and subsets of (displ,ax,dy*skal) are used. However not all cases where those addressing modes could be used are recognized. During this pass some other minor optimizations may be done. Compile time increases slightly if this optimization is turned on. Bit 8 (256) Automatic variables are addressed through a7 instead of a5. This generates slightly better code, because the function entry and exit overhead is reduced and a5 can be used as register variable etc. However this may be a bit confusing when debugging. Also arguments of function calls are not always popped immediately after the call, so that the arguments of several calls may be popped at once. This optimization should have no effect on compile time. KNOWN PROBLEMS - Converting between unsigned integers and floating point values is not always correct. - Under certain circumstances incorrect code for comparisons may be generated - You should get an internal error then. (should be fixed) Volker Barthelmann volker@vb.franken.de Kennedy-Ring 39 91301 Forchheim Germany