Cross compiling to the Atari ST

This was a lot harder than it should have been. And not because of gcc or surprisingly ancient binutils.

I didn’t have much to go on, as ancient threads like this, or this end up unanswered or without any good conclusion. I guess it’s not surprising that all the attention is to MiNT & MINIX rather than the native platform. But I was not deterred.

The reason why this was so freaking hard was how so much of key parts of gcc for the ST have been purged and what remains being scattered to the winds. Amazingly the hardest thing to source is the include files. There is a GCC 1.30 file on all the usual GNU mirrors but to save a few kb it has no headers, instead it wants you to reuse the ones from the 1.25 binary distribution. Which is gone. There survives a pl95 binary and source package, but again no includes. Instead I got lucky with all three for pl98. Which has a lot of GCC2 hooks so I cheated on getting the 1.30 hello world by using the 2.5.8 pre-processor.

It’s kind of annoying how all these seemingly tiny files get purged to save a few kb. Just as I can’t for the life of me find the old original GNU libc.

Speaking of files, ZOO has to be the worst compressor ever. Not only is it just overall worse than ZIP, but there are 2 incompatible compression methods, like the introduction of LZD, which any of the good versions of UNZOO can’t deal with. And sure there is zoo210.tar.Z but despite being able to build it on multiple platforms it never does anything useful. All these ancient fileformats sure don’t help anything. And sure there is a MS-DOS version that the MS-DOS Player can run, but get ready for 8.3 filename renaming.

The one good thing that came out of this experience is that since I am building form i386 to 68000 I found that this setup uses the G++ linker which has endian swapping. So maybe I can complete the chain for Mint and MachTen.

I even got the 1987 Infocom interpreter running. Although I don’t know what the deal is, it seems the larger the GCC based program is the higher chance it’ll just crash on exit or force the next program to crash. Building anything native under emulation was an impossibility.

In the same effort, I’ve had the same luck with sozobon. It took way too long to find a working dlibs. I don’t know why people couldn’t either package them together or at least in the same directory. It took far longer just to find the libs… But it was still fun to get that one running as well.

It’s a far more manual process to compile as I have to invoke each stage manually, but at least I’m finally able to get things going.

One of the bigger issues is that I would always find libraries in this olb file format, that the linker from Sozobon wouldn’t recognize. And almost every attempt of trying to build the G++ linker would also fail on. It wasn’t until I was able to get the pl98 include files that I could finally get a linker to actually recognize this … seemingly different for no apparent reason format to actually link. After then I managed to finally find a build of this dlibs that would actually link with Sozobon, which naturally didn’t use olb at all.

So yeah that was an adventure.

I haven’t cleaned it up at all, and really wouldn’t expect anyone else to care, but all my mashed together work (source & binaries!) is here: MinGW-AtariTOS.7z

UPDATE

I started browsing more cd.textfiles.com and amazingly found a ‘home made CD-ROM set’ of Atari software, and buried in the gigabytes of stuff was 4 of the 5 disks of the original GCC-1.23! Namely the source & includes to the first GCC library. I didn’t think this article was going to get any traction, let alone downloads. So many people downloaded the above download.

Anyways I started to put together a better package on sourceforge since it’ll do the multiple GIT’s and nicer downloads.

Download crossAtariST

The default download set is for GCC-1.30, with the headers & lib, along with source. It’s crazy small which just goes for how this old stuff is, and how impact full for losing a few kb.

Also the shell that you use apparently makes a BIG difference. The shell that I was using EmuCON doesn’t show any output from the GCC 1.x libs. However other shells most certainly do. I’ll have to do another update regarding shells/emulation.

68000 and i386 C Compiler Version III on Windows

While looking around for simple compilers to see how easy it is to modify their assembly output syntax, I ran across this tiny file, cc68iii3.zip which bills itself as:

This compiler consists of various modules that build up a
front end — these modules are common to all versions of
this compiler — consisting of parser, analyzer and optimizer,
of modules that are specific for the target processor,
namely *68k.c (for the 68000) and *386.c (for the i386),
and of assembly language output modules that are further
dependent on the (syntax of the) target assembler.

Well isn’t that interesting! So instead of doing something 68000 based, I setup the i386-gas compiler, and tried it with MinGW. And amazingly a hello world program worked!

C:\temp\ccc\cc\infocom> type hello.c
void main(){printf("Hello World!\n");}
C:\temp\ccc\cc\infocom> ..\c386gas hello.c hello.s

C:\temp\ccc\cc\infocom> gcc hello.s -o hello

C:\temp\ccc\cc\infocom> hello
Hello World!

C:\temp\ccc\cc\infocom> type hello.s
        .file   "C386GENERATED"
        .version        "C386 V 1.0"
        .optim
c386_compiled.:
        .text
L1:
        .byte 72,101,108,108,111,32,87,111,114,108,100,33
        .byte 10,0
        .align 2
_main:
pushl %ebp
movl %esp,%ebp
pushl $L1
call _printf
popl %ecx
leave
ret
.globl _main
.globl _printf

C:\temp\ccc\cc\infocom>

Well that was unexpected, but great! So I thought I’d modify the simple Infocom interpreter to build with this. I came up with this as a block for gnumake to read in a Makefile

%.o:    %.c
        $(CC) $(CFLAGS) -E $<  -o $*.i
        c386gas $*.i $*.s
        as $*.s -o $@
        rm -f $*.i $*.s

The key substitute is $* which is the 'root' of the file being passed in. Although it's lame doing it this way but it works in a nice automatic enough fashion.

The compiler must be K&R only as it doesn't like standard includes, so I built file.c/io.c/term.c using GCC but all the rest were able to be built just fine. And even better it works!

Infocom '87

Although I'd never recommend using something like this in a place that matters. If anything GCC 1.x is probably a better choice, but it's still kind of neat.

Messing with the Monitor

The 68000 Microprocessor (5th Edition) Hardcover – Nov 25 2003
by James L. Antonakos (Author)

So I was trapped in the Library for a bit, and spied this book. It’s not every often in 2019 you are going to find books about the 68000, as I’m sure any good library will have removed stuff like this, and have it pulped ages ago. But the amount of current technical books in English here is pretty damned slim to none, so I was all to happy to pickup this book for a week.

The poor thing has been checked out 4 times in the last 15 years. I guess the kids don’t know what they are missing.

Anyways what was interesting in this book is that it has a CD-ROM, and on there is some lesson code from the book, along with an assembler that outputs to S-records of all things, and a small emulator that is meant to be compiled under MS-DOS. It was trivial to isolate the passing of DOS interrupts from Unix/MinGW and get the simulator running on something modern.

In Chapter 11 there is a brief walkthrough on building a board, which sounds like fun although I’m sure in 2019 finding parts will be.. challenging, along with a simple monitor program.

The built in assembler can happily assemble the monitor, but it’s geared for talking to the obsolete hardware as specified in the book. I just made a few small changes to instead have it’s console IO hook to the simulator’s TRAPs and I had the monitor running!

I then took the echo test program, and modified it to run at a higher location in memory, along with exiting via the RTS instruction, so that it will exit when you press Q back to the monitor. Then for the heck of it I further extended the monitor so you can Quit it, and return to the simulator.

Is this useful? I’m pretty sure the answer is absolutely not.

The CD-ROM is tiny, I thought it would be packed with goodies, but it’s 250kb compressed.

The68000MicroprocessorFifthEdition.zip

If anything people using this book will probably have lost the CD-ROM and want the programs.

  • ISBN-10: 0130195618

And my horrible changes here.

Gopher kills the LC

Macintosh LC

The LC isn’t a strong Macintosh.  It is after all, a low cost model.  And what I’m doing isn’t even slightly fair to it.

Since it has a mere 68020 running at a blazing 16Mhz with no 68881 nor any MMU running something like A/UX is simply out of the question.  However MMU less Mac’s can run MachTen.

Although I did make a backup of the disk to find out that this thing had been in Harvard of all places, apparently once belonging to Mark Saroyan.

Although there was nothing even slightly academic or useful on the disk.  I wonder if the software was even pirated as the last owner sure enjoyed all the various SIM games (city/earth/life/ant) it seems more than anything else.

I formatted the massive 50MB SCSI disk, put on a fresh copy of MacOS 7.0.1 along with the network driver and MachTen 2.2.

System 7.0.1

And as far as LC’s go, this one isn’t too bad, it’s loaded up with the maximum 10MB of RAM, although it seems the VRAM is pretty sparse as it’ll only go to 16 colours.  But since we are playing UNIX here, I didn’t see any need for that, and set it to mono.

I thought it’d be fun to install a gopherd server onto this machine, and that is where the fun started.

Granted it’s been a long time since I used a machine with no real L2 cache, let alone running at a whopping 16Mhz, and using a compiler like GCC is just incredibly slow.

So I thought I could just ‘cheat’ the system by taking the source code to GCC-1.42 and tweaking the SUN3-Mach configuration into a SUN2-Mach configuration but keeping it targeting a BSD like OS, along with setting it to compile to a 68020 without a 68881.  Oddly enough getting a cross compiler wasn’t so difficult, but the assembler on the LC, a modified GAS wouldn’t assembler the files. So I went ahead and built a68 from GAS 1.38 and now I can cross assemble from Windows. However I couldn’t get the linker ld from binutils-1.9 working.  I guess it was an endian issue somewhere, but my attempt at byte swapping files it was reading just led to further confusion.  And I figured linking on the target host wouldn’t be the end of the world, as compiling sure feels like it is.

I can’t see like anyone would care, but here it is: 
MachTen-crossgcc-1.42-nolinker.7z

So fighting the source and in a matter of a 30 minutes of on/off work I had it compiled.  All I needed to do then was FTP the objects to the machine, link and run.   Surprisingly this proved to be pretty simple.

gopherd running!

I managed to get a few pages out of it, and suddenly my telnet sessions dropped.  Looking over at the console and MacOS was busy being MacOS.

error of type 3

And that was that.

I tried another program to cross compile and upload phoon!

phoon cross compiled, natively linked.

It took a while to set the clock to the right year, as my minimal System 7 install doesn’t have the time control panel, and advancing 1 year at a time from 1999 takes time, by advancing the date to New Years Eve every minute 19 times to get us to 2018 with the old date syntax:

date 12312359

Lessons learned?

Obviously if I want to do something like this, I’m going to need a better Macintosh.  Or just not do things like this….

I’m kind of on the fence as to whither 68k Unix is really all that useful in the age of Ghz x86.  

So while out today I found a Windows RT Surface for $25

I had to pay another $15 for the charger.  I should have run away, but I’m a sucker.

Yes, there are basically NO apps, but thanks to this little guide

QuakeWorld on Windows RT

I was able to port over some trivial stuff, the usual things like hello world, Infocom Interpreter, a f2c build of Dungeon, then I went with something I’d been messing around an old GDI driver for WinQuake that builds with the NT 3.5 SDK (finally got it!).  So with a few minor tweeks here it is cross compiled from my x86_64 to the surface.

Last time I talked about the Surface was nearly 6 years ago…  The platform’s fate was pretty much sealed on day one.  With no open Win32 API it shunned traditional devs, and with some completely new and insane model it was such a hurdle for new devs, why put so much effort into such an old tired company like Microsoft?

I figured for the price of a good lunch it’d be a fun toy.

Too bad the speakers don’t work though.

I know the window on Windows 8.1 apps is closing soon.  I should put something together for the dead platform.  Maybe for phone too.  But for tonight, it was kinda fun doing a copy/paste attack to then run unsigned EXE’s on the device.

I might upload the tool chain later, but at the moment getting Visual Studio 2012 Ultimate is a breeze.

Building MAME 0.1 for MS-DOS / DJGPP

So as promised, a while back I had built a GCC 2.7.2.3 / Binutils 2.8.1 cross compiler toolchain suitable for building old Allegro based programs, such as MAME.  Of course the #1 reason why I’d want such a thing is that being able to do native builds on modern machines means that things compile in seconds, rather than an hour + compiling inside of DOSBox.

Why not use a more up to date version of both GCC/Binutils?  Well the problem is that the pre EGCS tools ended up with macro and inline assembly directives that were dumped along the way so that later versions simply will not assemble any of the later video code in Allegro, and a lot of the C needs updating too.  And it was easier to just get the older tool chain working.

It took a bit of messing around building certain portions inside of each step of the tools, but after a while I had a satisfactory chain capable of building what I had needed.

So for our fun, we will need my cross DJGPP v2 tool chain for win32, MAME 0.1, Allegro 3.12 and Synthetic Audio Library (SEAL) Development Kit 1.0.7 .

Lib Allegro is already pre-built in my cross compiler tool chain, all that I needed to add was SEAL, with only one change, 1.0.7 is expecting an EGCS compiler, which this is not, so the -mpentium flag won’t work, however -m486 will work fine.

Otherwise, in MAME all I did was alter some include paths to pickup both Allegro and SEAL, and in no time I had an executable.  And the best part is checking via DOSBox, it runs, with sound!

MAME 0.1 on DOSBox PACMAN hiding

Thankfully MAME has been really good about preserving prior releases, along with their source tree, and it’s pretty cool to be able to rebuild this using the era correct vintage tools, and I can’t stress how much more tolerable it is to build on faster equipment.

More cross compiler assertion fun

undefined reference to `___eprintf'

Got this fun one in dwarf.c (and probably many others) while building an ELF toolchain from Linux to run on Windows to target.. Linux.  Anyways I think this is a symptom of Canadian Cross compilers.

So a little digging and ___eprintf turns out to be from the assert.h as macros for assert depend on this being in libgcc.a .. And yeah, MinGW uses something else.  So just copy the assert.h from MinGW, and re-build and away it works.

D:\elfgcc\bin>cc1
int main(){printf("hi!\n");return 0;}
        .file   "stdin"
        .version        "01.01"
gcc2_compiled.:
 main.section   .rodata
.LC0:
        .string "hi!\n"
.text
        .align 4
.globl main
        .type    main,@function
main:
        pushl %ebp
        movl %esp,%ebp
        pushl $.LC0
        call printf
        addl $4,%esp
        xorl %eax,%eax
        jmp .L1
        .align 4
.L1:
        leave
        ret
.Lfe1:
        .size    main,.Lfe1-main
^Z
        .ident  "GCC: (GNU) 2.7.2.3"

time in parse: 1.155000
time in integration: 0.000000
time in jump: 0.000000
time in cse: 0.000000
time in loop: 0.000000
time in cse2: 0.000000
time in flow: 0.000000
time in combine: 0.000000
time in sched: 0.000000
time in local-alloc: 0.000000
time in global-alloc: 0.000000
time in sched2: 0.000000
time in dbranch: 0.000000
time in shorten-branch: 0.000000
time in stack-reg: 0.000000
time in final: 0.000000
time in varconst: 0.000000
time in symout: 0.000000
time in dump: 0.000000

Well, wasn’t that fun?

Cross Compiling 386BSD 0.1pl23 from Windows 10

I bumped the version to *current year*

Oh yes, this will be a thing!

Sure I can cross compile Linux, but what about 386BSD?  This had long been a thorn in my side, as the GCC/Binutil toolchain that is used in this early era is not GNU pure, they had been modified in all kinds of ways.  One of which was a builtin memcpy that doesn’t work the same as a normal memcpy, and the other being that the C compiler & pre-processor rely in YACC to build the tokens.  I had been using bison before, however even though bison didn’t generate any errors it build the compiler wrong enough that the majority of the kernel wouldn’t compile.

As it stands right now, the only things that do not compile is locore

to post process the kernel, symorder is used along with dbsym, although neither do any processing to the kernel file itself, so they aren’t needed to get a working system.

386BSD Release 0.1 by William and Lynne Jolitz.
Copyright (c) 1989,1990,1991,1992 William F. Jolitz. All rights reserved.
Based in part on work by the 386BSD User Community and the
BSD Networking Software, Release 2 by UCB EECS Department.
386BSD 0.1.2018 (GENERICISA) 02/02/18 15:01

Other than that, yeah it’s great, compile a kernel in under 15 seconds.

Anyone that cares, the initial release is here: 386bsd01.7z

 

GCC 1.27 & MS-DOS

Inspired by Building and using a 29-year-old compiler on a modern system, i thought I too could get this ancient version of GCC working.  At the time I never had bothered with the older version as I had always assumed that there were many fixes and adaptations to GCC for it to run on MS-DOS via GO32/DJGPP.  However, after doing this, it’s obvious that GO32/DJGPP was rather built around GCC’s stock output, which would sure make a lot more sense.

And it turns out that the target machine being an i386 Sequent running BSD is the best match, both in turns of underscores, and debugging format.  At first, I had tried the AT&T SYSV i386 target, however it couldn’t link anything from the standard libraries that DJGPP has as they all have a leading underscore.  After starting to mess with internal macros to turn things on and off, and re-define how various portions of assembly are emitted, I found the Sequent target and went with that and everything was fine and using the existing build infrastructure for GCC 1.39 I now could actually run hello world!

gcc_v1 -v -E hello.c -o hello.i
gcc version 1.39
cpp_v1 -v -undef -D__GNUC__ -DGNUDOS -Dunix -Di386 -D__unix__ -D__i386__ hello.c -o hello.i
GNU CPP version 1.39
gcc_v1 -v -S hello.i -o hello.s
gcc version 1.39
cc1_v1 hello.i -quiet -version -o hello.s
GNU C version 1.27 (80386, BSD syntax) compiled by GNU C version 5.1.0.
gcc_v1 -v -c hello.s -o hello.o
gcc version 1.39
as -o hello.o hello.s
gcc_v1 -v -o hello hello.o
gcc version 1.39
ld -o hello C:/dos/xdjgpp.v1/lib/crt0.o hello.o -lc

go32 version 1.12.maint3 Copyright (C) 1994 DJ Delorie

hello from DJGPP v1/GCC 1.39!

Wasn’t that great?  Then going through my ‘test’ programs I went to try to build the infocom interpreter, and that is when things went off the rails.

funcs.o: Undefined symbol __udivsi3 referenced from text segment
options.o: Undefined symbol __divsi3 referenced from text segment
options.o: Undefined symbol __divsi3 referenced from text segment
print.o: Undefined symbol __divsi3 referenced from text segment
print.o: Undefined symbol __udivsi3 referenced from text segment
support.o: Undefined symbol __divsi3 referenced from text segment
gcc_v1: Program ld got fatal signal 1.

I’ve had some issues with GCC and these ‘built in’ functions before.  This was an early major stumbling block back in the x68000 GCC days, where after a lot of searching I was able to find 68000 versions of various math routines that were in the native Hudson Soft assembler to link in.  While GCC 1.x does have a libgnu/gnulib to include these functions it warns you over and over to not use GCC to build them, but rather the native CC.  But the problem is that I don’t have a native CC.

But I managed to save myself after googling around by finding srt0.c from 386BSD.  Namely these two:

.globl ___udivsi3
___udivsi3:
	movl 4(%esp),%eax
	xorl %edx,%edx
	divl 8(%esp)
	ret

.globl ___divsi3
___divsi3:
	movl 4(%esp),%eax
	xorl %edx,%edx
	cltd
	idivl 8(%esp)
	ret

I ended up having to removing a single underscore, but now I could link infocom, and even better it runs!

Wanting to try something far more exciting, I went ahead and tried to build DooM.  However, GCC 1.27 has an issue with m_fixed.c  I fired up GDB to at least take a look, although I’m not sure where the fault lies.

FixedMul
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Breakpoint 1, 0x752c5ad5 in msvcrt!_exit () from C:\WINDOWS\System32\msvcrt.dll
(gdb) bt
#0 0x752c5ad5 in msvcrt!_exit () from C:\WINDOWS\System32\msvcrt.dll
#1 0x752bb379 in msvcrt!abort () from C:\WINDOWS\System32\msvcrt.dll
#2 0x0045805c in final (first=0xe066a0, file=0x75312688 <msvcrt!_iob+128>, write_symbols=NO_DEBUG, optimize=0)
at final.c:653
#3 0x00403198 in rest_of_compilation (decl=0x722718) at toplev.c:1296
#4 0x0040fbce in finish_function () at c-decl.c:3272
#5 0x004040c0 in yyparse () at c-parse.y:224
#6 0x0040239d in compile_file (name=0xe00def "C:/dos/xdjgpp.v1/tmp/cca02992.cpp") at toplev.c:837
#7 0x00403a33 in main (argc=11, argv=0xe00f90, envp=0xe01598) at toplev.c:1556

With the code being:

#ifdef REGISTER_CONSTRAINTS
	    if (! constrain_operands (insn_code_number))
	      abort ();
#endif

So I assume some error with constrain operands? Not that it makes it any better.  However, I know this one file compiles fine with 1.39, and since we are on the i386 another alternative is just to use the assembly version that was hiding in the readme..

DooM mostly built by GCC 1.27

And much to my amazement, it works!  Keeping in mind that this is using an a.out tool chain, along with the last DPMI enabled GO32 extender.

Considering the compiler dates back from September 5th, 1988 it’s really great to see it running.

I’ll have to upload source (GCC 1.27/DooM) & binaries later.  But I imagine it should also run on EMX/RSX for a Win32 version.

26th anniversary of Linux!

As the joke goes:

Happy 25th birthday, Linux! Here’s your f-ing cake, go ahead and compile it yourself.

So it’s always a fun time for me to push my old project Ancient Linux on Windows.  And what makes this so special?  Well it’s a cross compiler for the ancient Linux kernels, along with source to the kernels so you can easily edit, compile and run early Linux from Windows!

As always the kernels I have built and done super basic testing on are:

  • linux-0.10
  • linux-0.11
  • linux-0.12
  • linux-0.95c+
  • linux-0.96c
  • linux-0.97.6
  • linux-0.98.6

All of these are a.out kernels, like things were back in the old days.  You can edit stuff in notepad if you so wish, or any other editor.  A MSYS environment is included, so you can just type in ‘make’ and a kernel can be built, and it also can be tested in the included Qemu.  I’ve updated a few things, first with better environment variables, and only tested on Windows 10.  Although building a standalone linux EXE still requires a bit of work, it isn’t my goal here as this whole thing is instead geared around building kernels from source.  I included bison in this build, so more of GCC is generated on the host.  Not that I think it matters too much, although it ended up being an issue doing DooM on GCC 1.39.

So for people who want to relive the good old bad days of Linux, and want to do so from the comfort of Windows, this is your chance!


Download Ancient Linux on Windows
Download Ancient Linux on Windows