Porting GCC to 32bit OS/2

I know what you are going to think, that it was already done, and it was called EMX. Or was it GCC/2? Well sure but what if you are not running the GA (General availability) version of OS/2. For example, years ago I had managed to get Citrix Multiuser 2.0, and it’s not at the GA level. All that is available is some ancient beta version of Microsoft C 5.2 from 1989?!

A little while back I had worked on getting GCC to build and run on the FPU enabled versions of Windows NT from 1991. I had mentioned that it turns out thanks to the Xenix assembler, that GCC had been basically available the entire time Windows NT had been available, but lamented that since the OS/2 compiler is 16/32bit, the 5.2 compiler couldn’t handle compiling GCC without blowing it’s heap. 16bit issues in a 64bit world.

However after doing some research on all the early cl386 compilers I could get my hands on, including the Windows NT Pre-release ones, I’d noticed that if I built CC1.EXE (the actual compiler) first for Win32, then rebuilt those object files with the December NT Pre-release compiler, that some versions of LINK386 from the OS/2 2.1 DDK would actually link with them. And sure enough it worked!

First life of GCC on OS/2

I have to admit I was pretty amazed, I had managed to ‘cross compile’ GCC using quite the tool chain.

First the compiler from the December NT Pre-release CD-ROM is shipped as a 16bit OS/2 compiler, but I’m using Windows 11. First I use the MS-DOS player with a quick fix from crazyc to allow Phar Lap 286|Dos Extender to run, which provides a basic enough OS/2 emulation to allow the compiler to run under ‘dos’. The linker on the DDK suffers the same fate as far as it also being 16bit. However the combination of MS-DOS player & Phar Lap gets stuff working! The only weird catch is that the 386 emulator causes strange floating point related crashes, while the 286 or 486 emulators work fine.

Now targeting OS/2 or running on OS/2 isn’t all that new, but building it from a Microsoft C compiler is. And now of course you’ll ask yourself, who cares? why is it interesting?

Well, the vast majority of the GCC ports to OS/2 don’t support the OMF object file binary standard, instead they used the much outdated a.out format, and rely on tools to convert the objects if needed. Additionally, they have DLL dependencies, and other startup issues with things needing to be setup. And of course they rely on a binary standard that is ‘GA’. *HOWEVER* by using a Microsoft compiler, I have OMF object files that the OS/2 built in system linker LINK386 can understand. So in plain English I can just relink the compiler and it’ll run on a new ‘version’ of unsupported OS/2.

I made a diskette image with my objects & a linker script and in a few moments I had it running!

GCC running on OS/2 2.00 6.123

The substantial thing here is that the binary format for OS/2 changed twice, and each release introduced changes that broke binary compatibility, in an effort to force people onto the new tools. So there is no way that the old ‘LE’ format would ever work. And you can see it’s running! In addition I could take the same object files, and copy them to my Citrix server, and likewise it was just a matter of linking, and it too now has GCC!

Converting a.out to OMF via emxomf

One annoying thing is that the LINK386 that ships with OS/2 2.00 GA doesn’t like the output of the Xenix assembler, so I built the a.out traditional assembler, and the emxomf tool to convert the a.out to OMF, and that worked well.

I still have much to mess with, including the pre-processor & main ‘gcc’ program. I have not built anything beyond a trivial program, so there is indeed much more work to be done before I can even try anything challenging. Some programs like emxomf have portions in the debug support that require the ‘long long’ type, which obviously Microsoft compilers from 1989-1991 don’t have, so I’ll have to re-build them with GCC.

Ive been putting my ports onto github (cl386-research) as it handles the rapid changes well enough. It’s a bit of a complex setup and it involves using a build system that I’ve put over on archive.org here: cl386-research-v2.

Not that I can imagine anyone wanting to try but I’ve uploaded some disks with the objects. Copy them to a hard drive, and run the ‘build.cmd’ command and it’ll link to a native freestanding executable.

I’ll explain it more with a post later, along with going over all the versions of cl386 I’ve acquired, over the years in more of a part 2: Targeting OS/2 with Visual Studio 2003!

Fun with Windows ePDK NT 3.1 build 196 & Some Xenix fun!

I’m not sure if I covered the Windows NT 3.1 build 196 before. First the most obvious is that as of this moment it’s the earliest version of Windows NT available.

So let’s do some obligatory scratch of the surface. Like all the other 1991 pre-releases there really is just a text mode setup install script. Choosing the lesser amount of pain, I went with a MS-DOS hosted install. However, using MS-DOS 6.22 resulted in a broken dual boot system. But we live in the era of virtual machines, so it really doesn’t matter. I’m using Qemu 0.14-rc2, something that is ‘era correct’ for when the first avalanche broke on early Windows NT pre-releases. I’ve had issues with more modern versions of Qemu, and I felt that if we’re using vintage software may as well go in all the way.

The boot loader identifies itself as being 1990 vintage. Pretty sure it doesn’t mean anything, but we haven’t been blessed with the “blue screen” of ARC yet.

The login screen and desktop have a very strong Windows 3.1 beta feel to them. And that would land this where it was, Windows was such a big seller that Maritz had been trying to convince Gates & Balmer to ‘switch to the Windows horse’ in the spring/summer of 1990, culminating in Gate’s July decision to walk away from NT/OS2 and rebrand the new OS as Windows NT. Oddly enough it was Balmer who was in favour of OS/2 & IBM. (Showstopper 89-90)

At first glance the opening window isn’t all that interesting. It’s just very. Windows.

Rest assured Reversi, of course made the this Win32 cut. And it’s full of weird easter eggs, oddly enough in the OS/2 surviving bits.

type OS2LDR.DOS
OS2LDR 01.00.01
by KeithMo 01/08/91

On the Discord there had been a big discussion about early NT executable formats, and the whole COFF vs ECOFF vs PE/PEI. I had tried to hunt down the specific version of GCC I used ages to to build a so called Dec Alpha GCC cross compiler, but the short version is that it didn’t work as we don’t have any assembler/linker for anything GNU targets. There had been a cygwin port and an OpenNT on Alpha, but all that is lost to the winds, minus what few scraps I had saved. I did try building some cross tools to elf hoping to just objcopy out the data and get linkable objects, but that didn’t work either.

So I though this was a perfect opportunity to take a look at this early pre-release version of NT, and although I do know that you have to convert your objects into something the ‘COFF’ linker will accept:

And I never really paid that much attention to the object files. I do know that you can link them with Link386 for OS/2, but the NT object files themselves report:

wsl file SIMPLE.OBJ
SIMPLE.OBJ: Intel 80386 COFF object file, not stripped, 4 sections, symbol offset=0x102, 20 symbols, created Thu Jun  1 14:13:50 2023, 1st section name ".text"

Well, now that is interesting. And of course the COFF thing reminded me of Xenix! And sure enough ages ago I had found the source to a modified version of GNU GAS that outputs COFF. Once more again this is an indication that all 386 roads in Microsoft really did originate with Xenix. It’s too bad there never was a Windows/386 on Xenix/386. What an incredible OS that would have been! There must be some incredible stories from the tool teams that worked on Microsoft C/386 along with other projects. Oddly enough they never get anywhere near as much exposure as Office or OS.

Now this is fun, but nothing takes in these ancient COFF objects, do they? I tried to run LINK 1.0 from Win32s SDK and surprisingly it didn’t complain about the object, rather, it auto converted it in memory:

Microsoft (R) 32-Bit Executable Linker Version 1.00
Copyright (C) Microsoft Corp 1992-93. All rights reserved.

SIMPLE.OBJ : warning LNK4016: unresolved external symbol "__chkstk"
LINK : warning LNK4016: unresolved external symbol "_mainCRTStartup"
SIMPLE.OBJ : warning LNK4016: unresolved external symbol "_printf"
SIMPLE.exe : error LNK1120: 3 unresolved externals

Does this mean that if I give it some libraries it will actually link?

LINK.EXE SIMPLE.OBJ /SUBSYSTEM:CONSOLE /MACHINE:i386 -entry:mainCRTStartup -out:simple.exe libc.lib kernel32.lib
Microsoft (R) 32-Bit Executable Linker Version 1.00
Copyright (C) Microsoft Corp 1992-93. All rights reserved.


C:\temp\nt196\x\dec\x>simple
Win32, it's happenin'!

This was. VERY unexpected.

So I had this crazy idea, what if the Xenix assembler could in fact build objects that are also compaible in this manner? I used the a.out GCC / Linux porting tools I had built so I could compile Linux on Windows NT using the vintage tools as a starting point. I guess I should also add that when people always say ‘use newer version of THING’ this is how you miss out on old stuff like this. If I had been obsessed with using modern tools and modern operating systems, I’d have missed out on this Xenix filled window.

I took the gcc driver & the cc1 compiler from 1.40 and the c pre-processor from 2.5.8 as it can understand C++ comments. First I manually compiled the ‘simple’ example to assembly:

gcc -v -nostdinc -I/xenixnt/h -S SIMPLE.c -O simple.S
gcc version 1.40
 cpp -nostdinc -v -I/xenixnt/h -undef -D__GNUC__ -Dunix -Di386 -D__unix__ -D__i386__ -D__OPTIMIZE__ SIMPLE.c C:/Users/jsteve/AppData/Local/Temp/cca2_048.cpp
GNU CPP version 2.5.8 (80386, BSD syntax)
#include "..." search starts here:
#include <...> search starts here:
 /xenixnt/h
End of search list.
 cc1 C:/Users/jsteve/AppData/Local/Temp/cca2_048.cpp -quiet -dumpbase SIMPLE.c -O -version -o SIMPLE.s
GNU C version 1.40 (80386, BSD syntax) compiled by GNU C version 5.1.0.
default target switches: -m80387
 cpp -nostdinc -v -I/xenixnt/h -undef -D__GNUC__ -$ -Dunix -Di386 -D__unix__ -D__i386__ -D__OPTIMIZE__ simple.S C:/Users/jsteve/AppData/Local/Temp/cca2_048.s
GNU CPP version 2.5.8 (80386, BSD syntax)
#include "..." search starts here:
#include <...> search starts here:
 /xenixnt/h
End of search list.

Which gave me the following assembly:

        .file   "SIMPLE.c"
gcc_compiled.:
.text
LC0:
        .ascii "Win32, it's happenin'!\0"
        .align 2
.globl _main
_main:
        pushl %ebp
        movl %esp,%ebp
        pushl $LC0
        call _printf
        leave
        ret

Now to assemble with the GAS Xenix assembler

C:\temp\nt196\files\MSTOOLS\SAMPLES\SIMPLE>ax386 SIMPLE.s -o SIMPLE.obj

C:\temp\nt196\files\MSTOOLS\SAMPLES\SIMPLE>wsl file SIMPLE.obj
SIMPLE.obj: 8086 relocatable (Microsoft), "SIMPLE.c", 1st record data length 10, 2nd record type 0x88, 2nd record data length 11

Not quite the same. But it does closer resemble the output from the OS/2 bound versions of the Pre-Rease compilers:

file EMPTY.OBJ
EMPTY.OBJ: 8086 relocatable (Microsoft), "empty.c", 1st record data length 9, 2nd record type 0x88, 2nd record data length 7

So will it link?!

C:\temp\nt196\files\MSTOOLS\SAMPLES\SIMPLE>LINK.EXE SIMPLE.OBJ /SUBSYSTEM:CONSOLE /MACHINE:i386 -entry:mainCRTStartup -out:simple.exe libc.lib kernel32.lib
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.

SIMPLE.OBJ : warning LNK4033: converting object format from OMF to COFF

C:\temp\nt196\files\MSTOOLS\SAMPLES\SIMPLE>simple
Win32, it's happenin'!

Well now this is interesting! LONG before MinGW, or the GCC port to Windows NT, it turns out that in fact GCC could target Windows NT the entire time!

So the next thing to do is something not as trivial, like phoon.

I setup some quick script to pre-process, compile, assemble and then try to link, but as this one uses floating point, disaster struck:

phoon.obj : error LNK2001: unresolved external symbol "___fixdfsi"
astro.obj : error LNK2001: unresolved external symbol "___fixdfsi"
phoon.exe : error LNK1120: 1 unresolved externals

Now ages ago while messgin with old GCC & DooM I also had weird math calls not working. In the end I ended up extracting them from libgcc builds, so I thought I’d try the libgcc built during the GCC 2.6.3 on NT adventure.

link /NODEFAULTLIB:libc.lib /NODEFAULTLIB:OLDNAMES.LIB -out:phoon.exe astro.obj date_p.obj phoon.obj -entry:mainCRTStartup libgcc1.lib LIBC.LIB KERNEL32.LIB
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.

And of course:

To try to make the steps make a little more sense, and to allow for some higher level of automation I made a Makefile:

CC=gcc
CC1=cc1
AS=ax386
CPP=cpp


CFLAGS= -O
CPPFLAGS= -lang-c-c++-comments -nostdinc -I/xenixnt/h

OBJ =   astro.obj \
date_p.obj \
phoon.obj

LIBS = libgcc1.lib LIBC.LIB KERNEL32.LIB

phoon.exe: $(OBJ)
        link -out:phoon.exe $(OBJ) -entry:mainCRTStartup $(LIBS)

%.obj: %.c
        $(CPP) $(CPPFLAGS) $< $*.i
        $(CC1) $*.i -quiet $(CFLAGS) -version -o $*.S
        $(AS) $*.S -o $*.obj


clean:
        del $(OBJ) *.i *.S phoon.exe

I’m sure there is better ways to do this, but it breaks the compile up to it’s individual parts:

Run the pre-processor to allow // in the comments, C++ hadn’t been the default thing back when GCC 1.40 was a thing. Also path it to the headers, in this case I’m using the ones from NT 196. Trying to link with the 196 libraries gave me this:

C:\xenixnt\demos\phoon>link /NODEFAULTLIB:LIBC.LIB /NODEFAULTLIB:OLDNAMES.LIB -out:phoon.exe astro.obj date_p.obj phoon.obj -entry:mainCRTStartup base.lib wincrt.lib ntdll.lib \xenixnt\lib\libgcc1.lib
Microsoft (R) 32-Bit Incremental Linker Version 2.50
Copyright (C) Microsoft Corp 1992-94. All rights reserved.

wincrt.lib(maincrt0.obj) : warning LNK4078: multiple ".data" sections found with different attributes (40000040)
astro.obj : error LNK2001: unresolved external symbol "_asin"
astro.obj : error LNK2001: unresolved external symbol "_atan"
astro.obj : error LNK2001: unresolved external symbol "_atan2"
phoon.obj : error LNK2001: unresolved external symbol "_cos"
astro.obj : error LNK2001: unresolved external symbol "_cos"
astro.obj : error LNK2001: unresolved external symbol "_floor"
astro.obj : error LNK2001: unresolved external symbol "_sin"
phoon.obj : error LNK2001: unresolved external symbol "_sqrt"
astro.obj : error LNK2001: unresolved external symbol "_sqrt"
astro.obj : error LNK2001: unresolved external symbol "_tan"
phoon.exe : error LNK1120: 8 unresolved externals

Which is not surprising as there is no FPU/Floating point math support in 196. I tried the December 1991 Pre-Release, but it failed for other reasons:

I did copy over BASE.DLL BASERTL.DLL CSR.DLL DBGDLL.DLL as it wanted, but despite the symbol being in the DLL it didn’t load.

So that’s why I’m using the libraries from the Win32s SDK.

Okay, so far now we have GCC 1.40 compiling to an old Xenix GAS assembler, and linking with Microsoft link from Visual C++ 1.0/2.0 era. The next step is to see if we can just link the objects under 196, and get a running EXE!

I have this tiny fibonacci example program, so with it compiled & assembled by GCC & GAS, I did the final link under 196, and YES it runs!

I then built the ’87 InfoTaskForce, Infocom interpreter, and it was just a simple link, and it’s running!

Possible things to do? GCC should be able to build itself, so it should be possible to build GCC and link that on 196 or December 1991, and get a native version of GCC on NT. The other possibility is to get newer versions of GCC (cc1 drop in replacements) to build for Xenix and / or OS/2. Obviously this Xenix linker is the gateway to older 386 Microsoft based products!

For those interested in such things, I’ve uploaded all of this to archive.org here: windows-nt-196-linking-and-running-gcc

When YYLEX shouldn’t be confused with yylex

While trying to build some old stuff I ran into this weird issue where YYLESX is undefined:

gcc -DHAVE_CONFIG_H -I. -I. -I../../include -I../.. -I../.. -I../../include -g -O2 -Wall -c cs_grammar.c
cs_grammar.y: In function ‘cs_parse’:
cs_grammar.y:1074:58: error: ‘YYLEX’ undeclared (first use in this function)
1074 | yychar = YYLEX;
| ^~~~~
cs_grammar.y:1074:58: note: each undeclared identifier is reported only once for each function it appears in
make[3]: *** [Makefile:334: cs_grammar.o] Error 1

Notice it’s all UPPERCASE, but you can find plenty on the lowercase issue where its not being linked correctly. And yeah turns out YYFLEX should define out toe yyflex

# ifndef YYLEX
#  define YYLEX		yylex()
# endif

Add that in the top of whatever source is complaining and you’re golden.

Really.

Started to re-build my MS-DOS machine

DooM!

Good news, it actually works!  I was using the version 1.1 WAD, so honestly weird crashes really aren’t unexpected.  I haven’t looked much at what to do with audio, but I was really impressed compared to the Qauake II wars, it was really surprising to not only see DooM run on the first shot in real metal, but the keyboard works as well.  Well enough for me to pick a level, and get killed.

Naturally it doesn’t work under Windows, however it runs fine with MS-DOS mode.

Null DooM, GCC 1.39, GO32 and DPMI


phew.

DooM via DJGPP v1 GO32

Around the time of the x68000 port of DooM, I was cutting down the DooM source for a null/portable version.  I never could get it to actually run either using EMX or  DJGPP 1.03, as I couldn’t get it to link to save my life with a constant never ending battle of unresolved symbols. After a while I just used what I had towards the x68000 version and concentrated on getting it up and running, and just shelved the null/portable effort.

Later on I wanted to get it running again as part of messing with another cross compiler, as DooM isn’t a trivial application to port and verify correct operation. And in the process of trying to get the null version to build and run on Windows using TDM GCC, I wanted to make sure it at least kept compiling with GCC v1.x.

Once more again I was able to compile individual files but unable to link.  But this time, I just looked at the diffs for binutils, I thought it should be somewhat easy to get hosted on Windows.  Although versions may point to binutils 1.0, I had to use binutils-1.9.tar.gz even though the diffs are against Mar 24 1991, and the source for 1.9 is dated April 17 1991.

My first effort gave me a linker that would happily link, but go32 would either refuse to run the executable, or just crash.  I was going to give up again, but I found mention in another file that DJGPP actually uses the linker from G++, the C++ compiler which was a separate thing in the late ’80s and early’90’s.  This time it worked, and I could link a trivial hello world style application!

Now that I finally had a cross linker actually working, I didn’t want to compile under emulation, so looking at the other diffs, they didn’t look too extensive. I went ahead ,and took DJGPP v1.06 and patched up the compiler & assembler to get a full cross toolchain.  And in no time, I had a null version of DooM running on MS-DOS well at least tested on DOSBox.

This was fun, and all but I didn’t see any easy way to do fun things like hook interrupts so I could get the keyboard & clock like any good MS-DOS program.  DPMI greatly eased this kind of stuff, so looking at the DJGPP history, DJGPP v1 version 1.10 actually adds preliminary DPMI support!  And in the next version, DPMI was much more better supported, however the binary format had changed from a.out to COFF as part of the move to v1.11. I was able to take the memory, and DPMI portions from the final v1.12 libc, and manually build and run them against the v1.06 library / dev tools.

And much to my surprise, it actually worked!  At least having the wrong format didn’t have any effect on how GO32 worked for me.

So feeling lazy, I snagged some of the support code from Maraakate’s revamp of DooM, just to make sure of the timer code, and the keyboard code, and again verified that I can build with the keyboard & timer ISR and I’m able to play the v1.9 shareware & commercial levels fine.  I haven’t done a thing to clean up or update the DooM source itself against all the dozens of bugs and issues with Ultimate DooM, or other games like Chex Quest etc.

I’m sure 99% of people wouldn’t care but you can download it here:

Win32_DJGPPv1_DooM.7z
Download crossdjgppv1

Although I’m using DPMI to drive realtime events, if I looked further at the GO32 v1.06 environments I could either figure out how it operates it’s timer, or modify the extender directly to drive the PIC timer and keyboard as I need.  But overlooking that, the vintage 1991 software is more than capable of running DooM.

DECUS links to ancient GNU software

Digital Equipment Computer Users’ Society (DECUS), used to put out tapes of interesting things to it’s members.  Back when everyone didn’t have an internet connection, or even if they did a high speed one.

I was looking for stuff where I only had a patch, but not the original files.  So it was great for me to not only dig out an ancient sed from the era, but also bison, and gas.  The ancient binutils are great for people who need to manipulate the a.out format, although the later binutils version 2 supports far more formats by virtue of it’s “BFD” or binary file database or as it was known as back then a ‘big fucking deal’

If you have ancient and or obsolete stuff, GNU stuff can fill the void of the often missing vendor development tools.  It’s crazy how many people sold the tools that kept their systems relevant, although needless to say that attitude pretty much solidified the end of their existence..

The good stuff from 1989 to 1993.

http://www.decuslib.com/decus/lt89a/gnusoftware/
http://www.decuslib.com/decus/lt89b2/gnusoftware/
http://www.decuslib.com/decus/lt90a/gnusoftware/
http://www.decuslib.com/decus/lt90b1/gnusoftware/
http://www.decuslib.com/decus/lt91a/gnusoftware/
http://www.decuslib.com/decus/lt91b/gnusoftware/
http://www.decuslib.com/decus/lt93a/gnusoftware/
It’s not complete, but it’s still fantastic!

 

Adding some of the GNU 1989 source ‘tapes’ into sourceforge

After scrounging around from an earlier post, on a DECUS mirror that goes back to 1989 I’ve put together the following source tapes:

Quite a list!

I haven’t tried to build any of it, but I figured for the time being, it may be easier to make some tap files for SIMH, and maybe someone else will do the hard work for me.  Or it’ll be a lazy day type thing.

Found some more ancient GNU software

I found a bunch of them here: ftp://ftp.ne.jp

CVS brows of the following:

I didn’t know that GNUmake 2.9 and prior was actually part of binutils.  I guess at some point I’ll build the older ones on 4.2 BSD to round out the experience.

And I don’t know where to find Emacs 18.41 and going further back.  Although I did find emacs1855.taz a DECUS (Digital Equipment Computer Users’ Society) image from late 1989.

Building and using GCC 0.9 aka the first public version

In my quest for old software, I’ve seen this file in multiple searches, gcc-0.9.tar.bz2, which is the first version of GCC!

article from virtuallyfun.superglobalmegacorp.com

GCC 0.9 on SIMH VAX / 4.2BSD

GCC 0.9 on SIMH VAX / 4.2BSD

From the original announcement:

 Date: Sun, 22 Mar 87 10:56:56 EST
From: rms (Richard M. Stallman)

   The GNU C compiler is now available for ftp from the file
/u2/emacs/gcc.tar on prep.ai.mit.edu.  This includes machine
descriptions for vax and sun, 60 pages of documentation on writing
machine descriptions (internals.texinfo, internals.dvi and Info
file internals).

   This also contains the ANSI standard (Nov 86) C preprocessor and 30
pages of reference manual for it.

   This compiler compiles itself correctly on the 68020 and did so
recently on the vax.  It recently compiled Emacs correctly on the
68020, and has also compiled tex-in-C and Kyoto Common Lisp.
However, it probably still has numerous bugs that I hope you will
find for me.

   I will be away for a month, so bugs reported now will not be
handled until then.

   If you can’t ftp, you can order a compiler beta-test tape from the
Free Software Foundation for $150 (plus 5% sales tax in
Massachusetts, or plus $15 overseas if you want air mail).

   Free Software Foundation
1000 Mass Ave
Cambridge, MA  02138

[tapes are generally in Unix tar format.  If you have other needs,
write to the above address, and ask if they can be met. -len]

And indeed, the files are dated 22/03/1987 making this the first public release of GCC.

GNU CC is a fairly portable optimizing C compiler intended for
machines with 32-bit words that have several registers and address
memory in terms of 8-bit bytes.  It supports full ANSI standard C, not
including libraries (which we do not consider to be part of a
compiler).
Currently we have working machine descriptions for the Vax and for
the 68000/68020 (including 68881 support).
Optimizations performed by GNU CC include:

  • Invariant code motion out of loops.
  • Common subexpression elimination.
  • Automatic register packing (register declarations are unnecessary
    and ignored).
  • Constant propagation and elimination of consequent dead code.
  • Copy propagation.
  • Elimination of dead stores.
  • Jump optimization including cross-jumping.
  • Delaying of stack adjustments after function calls.
  • Arithmetic performed in subword types when appropriate.
  • Many local optimizations.

GNU CC runs about as fast as PCC.
Most of the optimizations are machine-independent or controlled by a
machine description.  GNU CC takes advantage of all the 68020
addressing modes that we can see how to make the Sun assembler
assemble.  Debugging output for DBX is available whether you request
optimization or not.

Seeing as 4.3BSD didn’t ship until 1988, I went ahead and set out to build this on 4.2BSD. The first stumbling block I hit is that GCC needs bison.  The oldest version of bison I have is 1.25 which honestly is just too new!  However in the same location as GCC is this file gnu1988.tar.bz2 which contains all of the current GNU software of 1988!  And what is on that tape?

  • bison-1.00
  • gcc-1.21
  • gdb-2.5.1
  • gplusplus-1.21
  • libgplusplus

So this is probably as old as it is going to get, so I downloaded and went to compile bison, however getopt is a missing call!  A creative search found getopt.c (local mirror) and even better PCC liked it enough to get a running bison so I could then configure GCC.

Configuring GCC is a manual process, but not too involved:

  • Make a symbolic link from file `config.h’ to the top-level
    config file for the machine you are using. Its name should be
    `config-MACHINE.h’. This file is responsible for
    defining information about the host machine. It includes
    `tm.h’.
  • Make a symbolic link from `tm.h’ to the machine-description
    macro file for your machine (its name should be
    `tm-MACHINE.h’).
  • Make a symbolic link from `md’ to the
    machine description pattern file (its name should be
    `MACHINE.md’)
  • Make a symbolic link from
    `aux-output.c’ to the output-subroutine file for your machine
    (its name should be `MACHINE-output.c’).Make sure the Bison parser generator is installed.Build the compiler. Just type `make’ in the compiler directory.

And in a minute I had GCC compiled.  I ran it with -v and got this output:

# gcc -v
ld /lib/crt0.o -lc
Undefined:
_main

It really is nowhere near as featured as 1.21 that is for sure!  So time to do a simple hello world program:

# cat hello.c
#include <stdio.h>
void main(){
printf(“GCC 0.9 in action!\n”);
}
# gcc -v hello.c -o hello
cpp -Dvax hello.c /tmp/cc002050.cpp
cc1 /tmp/cc002050.cpp -quiet -dumpbase hello.c -noreg -o /tmp/cc002050.s
as -o hello.o /tmp/cc002050.s
ld -o hello /lib/crt0.o hello.o -lc
# ./hello
GCC 0.9 in action!

And there we go!

I don’t know why, but I haven’t seen anything about anyone actually running GCC 0.9.  Or even where or how they found this ‘lost’ file.  Let alone anyone even building or running it in 2016.

For anyone who wants to try, SIMH tape files of the binaries are here:

And of course source tapes are here.

Cross compiling Linux 0.95c+ & 0.96c from Windows

So first thing is to build GCC 2…  I couldn’t find any of the Linux patches for 2.0, 2.1 or 2.2.. I only tried to build 2.0 from source as targeting a.out i386 but it looks like the 2.0 files on the FSF’s site are missing files?

Anyways GCC 2.3.3 actually includes builtin support of Linux!  I was able to build most of it, but just like GCC 2.5.8 for OS/2 EMX, But this time I used the gcc driver from GCC 2.6.3, which added support for Windows NT 3.5 native builds, and I now had my GCC cross compiler!

D:\aoutgcc\src>gcc2 -v -c hi.c -o hi
gcc version 2.6.3 -Linux 2.3.3
cpp2 -lang-c -v -undef -D__GNUC__=2 -Dunix -Di386 -Dlinux -D__unix__ -D__i386__ -D__linux__ -D__unix -D__i386 -D__linux hi.c C:\Temp\cca09324.i
GNU CPP version 2.3.3 (80386, BSD syntax)
cc12 C:\Temp\cca09324.i -quiet -dumpbase hi.c -version -o C:\Temp\cca09324.s
GNU C version 2.3.3 (80386, BSD syntax) compiled by GNU C version 5.1.0.
a386 -o hi C:\Temp\cca09324.s

 

Thankfully the prior binutils and assembler I was using in my GCC 1.40 cross compiler, still cooperated just fine, and I could happily build and link just fine.

From there it was a matter of fighting the makefiles as for some reason as make calls other makefiles they are not passing variables, so I just cheated, and changed the paths, along with editing the dependencies to finding stuff in a more sane manner.  Plus all the Makefiles have include paths hard coded into the build process as expected.  After fighting for a while, it linked and even better, it runs!

linux-0-96c-71-cross-compiled-from-windows

Linux 0.96c-71 cross compiled from windows

So yeah, using the MCC hard disk image from oldlinux.org and it boots!

Cool stuff, indeed!

As an added bonus I was also able to get 0.97 & 0.98 to compile as well!

Download your copy @ MinGW-aout-linux–001_010_011_012_095_096_097_098.7z.