On the trail of PCC for the 8086

While on discord the topic came up of why there is no good/free C compiler for MS-DOS. Oh sure there is OpenWatcom but the 2 heavy hitters of the era, Microsoft C & Borland C are not open in the slightest.

There is DeSmet C, although it’s source is full of unnamed structs meaning that building it with anything sane would require a ‘lot of work ™’ which of course is not what I’m all that about. Instead, I remembered a directory up on TUHS /Applications/Portable_CC with a zip file 8086.zip Although this is a zip file, you’ll want to unzip on something Unix-y as there is a lot of case duplicate files. That said this is a PCC port to the 8086, which includes a libc, 8087 support, and is all expected to be built on a VAX-11/780 running 4.1BSD. Now this ended up being a stumbling block because I tried a *LOT* of things thinking that they were upwards compatible with 4.1, and the answer is USE 4.1!

So to effectively get going you’ll need a SIMH VAX780 and just follow my old steps on Installing 4.1BSD. As far as the zip file, I used Linux but had to create a tar file specifying the Unix v7 format with:

tar --format=v7 -cf pcc.tar .

And of course, convert the tar file to a simh tap file. Or if you are like me, just download a tap file here: PCC-Machines.tap.bz2.

With that said it’s a very strange setup as it relies on the 4.1BSD Vax environment so much that there is assembly injected into the linker.

asm("movc3 r8,(r11),(r7)");

So this will not cleanly run. Just as it depends on many system a.out specifics on building for MS-DOS. It’s not so much a MS-DOS tool chain, rather it outputs to vax a.out and uses a slightly modified vax linker. The MS-DOS magic happens in the conversion of the final a.out into a com file.

That is right it’s a VAX specific cross compiler that only build’s COM files.

I’ve managed to build some trivial stuff, and they work. Sadly my attempt at building that InfoTaskforce of ’87 failed.

I haven’t dug that much further into the linker although I have to wonder if a GNU cross linker to make a.out could make something that the conversion program would be happy with. The assembler of course doesn’t work, perhaps it’s something with packing structs?

As always, the simple stuff looks trivial but it was a fair bit involved.

Since there is no real ‘cc’ it’s a script but the vauge steps are:

/lib/cpp -I/usr/src/pcc/Machines/8086/lib86/include hi.c hi.i
/usr/src/pcc/Machines/8086/c86/c86 < hi.i > hi.a86
/usr/src/pcc/Machines/8086/a86/a86 hi
/usr/src/pcc/Machines/8086/a86/ld86 -X -N -r -o hi.out /usr/src/pcc/Machines/8086/lib86/crt0.b hi.b /usr/src/pcc/Machines/8086/lib86/libc.a 
/usr/src/pcc/Machines/8086/a86/cvt86 hi.out hi.com

It kind of makes sense.

Seems like somehow a lost opportunity in of itself back in the day

I just saw on the PCC mailing list that it just built NetBSD

From Iain Hibbert:

On Mon, 9 May 2011, Anders Magnusson wrote:

> Modified Files:
> pcc/arch/i386: table.c
>
> Log Message:
> Simple fix to avoid bug reported in Jira#PCC-343 by Iain Hibbert.

and so, pcc achieves another milestone..

kernel text is mapped with 3 large pages and 302 normal pages
Loaded initial symtab at 0xc0e37650, strtab at 0xc0ecdaa0, # entries 38363
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 5.99.48 (PCC) #1: Tue May 10 07:49:08 BST 2011
[email protected]:/var/work/NetBSD-current/obj.i386/sys/arch/i386/compile/PCC
total memory = 127 MB
avail memory = 110 MB
mainbus0 (root)
cpu0 at mainbus0 apid 0: QEMU Virtual CPU version 0.13.0, id 0x633
cpu1 at mainbus0 apid 1: QEMU Virtual CPU version 0.13.0, id 0x633
ioapic0 at mainbus0 apid 2
acpi0 at mainbus0: Intel ACPICA 20110211
pckbc1 at acpi0 (KBD, PNP0303) (kbd port): io 0x60,0x64 irq 1
pckbc2 at acpi0 (MOU, PNP0F13) (aux port): irq 12
FDC0 (PNP0700) at acpi0 not configured
LPT (PNP0400) at acpi0 not configured
COM1 (PNP0501) at acpi0 not configured
hpet0 at acpi0 (HPET, PNP0103-0): mem 0xfed00000-0xfed003ff
apm0 at acpi0: Power Management spec V1.2
pckbd0 at pckbc1 (kbd slot)
pckbc1: using irq 1 for kbd slot
wskbd0 at pckbd0 mux 1
pms0 at pckbc1 (aux slot)
pckbc1: using irq 12 for aux slot
wsmouse0 at pms0 mux 0
pci0 at mainbus0 bus 0: configuration mode 1
pchb0 at pci0 dev 0 function 0: vendor 0x8086 product 0x1237 (rev. 0x02)
pcib0 at pci0 dev 1 function 0: vendor 0x8086 product 0x7000 (rev. 0x00)
piixide0 at pci0 dev 1 function 1: Intel 82371SB IDE Interface (PIIX3) (rev. 0x00)
piixide0: primary channel interrupting at ioapic0 pin 14
atabus0 at piixide0 channel 0
piixide0: secondary channel interrupting at ioapic0 pin 15
atabus1 at piixide0 channel 1
piixpm0 at pci0 dev 1 function 3
piixpm0: vendor 0x8086 product 0x7113 (rev. 0x03)
piixpm0: 24-bit timer
piixpm0: interrupting at ioapic0 pin 9
iic0 at piixpm0: I2C bus
vga1 at pci0 dev 2 function 0: vendor 0x1013 product 0x00b8 (rev. 0x00)
wsdisplay0 at vga1 kbdmux 1
drm at vga1 not configured
wm0 at pci0 dev 3 function 0: Intel i82540EM 1000BASE-T Ethernet, rev. 3
wm0: interrupting at ioapic0 pin 11
wm0: Ethernet address 52:54:00:12:34:56
makphy0 at wm0 phy 1: Marvell 88E1011 Gigabit PHY, rev. 0
makphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
isa0 at pcib0
lpt0 at isa0 port 0x378-0x37b irq 7
com0 at isa0 port 0x3f8-0x3ff irq 4: ns16550a, working fifo
com0: console
com0: kgdb
attimer0 at isa0 port 0x40-0x43
pcppi0 at isa0 port 0x61
midi0 at pcppi0: PC speaker
sysbeep0 at pcppi0
isapnp0 at isa0 port 0x279
npx0 at isa0 port 0xf0-0xff
fdc0 at isa0 port 0x3f0-0x3f7 irq 6 drq 2
attimer0: attached to pcppi0
acpicpu0 at cpu0: ACPI CPU
acpicpu1 at cpu1: ACPI CPU
wd0 at atabus0 drive 0
wd0:
wd0: 5000 MB, 10158 cyl, 16 head, 63 sec, 512 bytes/sect x 10240000 sectors
atapibus0 at atabus1: 2 targets
cd0 at atapibus0 drive 0: cdrom removable
pad0: outputs: 44100Hz, 16-bit, stereo
audio0 at pad0: half duplex, playback, capture
boot device: wd0
root on wd0a dumps on wd0b
mountroot: trying smbfs…
mountroot: trying ntfs…
mountroot: trying nfs…
mountroot: trying msdos…
mountroot: trying lfs…
mountroot: trying ext2fs…
mountroot: trying ffs…
root file system type: ffs
clock: unknown CMOS layout
init: copying out path `/sbin/init’ 11
Tue May 10 07:50:12 GMT 2011
Starting root file system check:
/dev/rwd0a: file system is clean; not checking
swapctl: setting dump device to /dev/wd0b
swapctl: adding /dev/wd0b as swap device at priority 0
Starting file system checks:
Setting tty flags.
Setting sysctl variables:
ddb.onpanic: 2 -> 0
Starting network.
Hostname: qemu
IPv6 mode: host
Configuring network interfaces:.
Adding interface aliases:.
Building databases: dev, utmp, utmpx, services done
encoding -> uk
Starting syslogd.
Mounting all filesystems…
Clearing temporary files.
Updating fontconfig cache: done
Creating a.out runtime link editor directory cache.
Checking quotas: done.
swapctl: setting dump device to /dev/wd0b
Starting virecover.
Checking for core dump…
savecore: no core dump
Starting local daemons:.
Updating motd.
Starting inetd.
Starting cron.
Tue May 10 07:52:31 GMT 2011

NetBSD/i386 (qemu) (console)

login: root
May 10 07:52:45 qemu login: ROOT LOGIN (root) on tty console
Last login: Tue May 10 07:46:44 2011 on console
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 5.99.48 (PCC) #1: Tue May 10 07:49:08 BST 2011

Welcome to NetBSD!

This system is running a development snapshot of the NetBSD operating system,
also known as NetBSD-current. It is very possible that it has serious bugs,
regressions, broken features or other problems. Please bear this in mind
and use the system with care.

You are encouraged to test this version as thoroughly as possible. Should you
encounter any problem, please report it back to the development team using the
send-pr(1) utility (requires a working MTA). If yours is not properly set up,
use the web interface at: http://www.NetBSD.org/support/send-pr.html

Thank you for helping us test and improve NetBSD.

Terminal type is vt100.
We recommend that you create a non-root account and use su(1) for root access.
qemu# ls
.cshrc .klogin .lesshst .login .profile .shrc
qemu# cat >test.c
int
main(int ac, char *av[])
{
printf(“Hello World!\n”);
return 0;
}
^D
qemu# pcc -o test test.c
qemu# ./test
Hello World!
qemu# shutdown -p now
Shutdown NOW!
shutdown: [pid 369]
qemu#
wall: You have write permission turned off; no reply possible

*** FINAL System shutdown message from root@qemu ***
System going down IMMEDIATELY

May 10 07:54:14 qemu shutdown: poweroff by root:

System shutdown time has arrived

About to run shutdown hooks…
Stopping cron.
Waiting for PIDS: 345.
Stopping inetd.
Waiting for PIDS: 308.
Removing block-type swap devices
swapctl: removing /dev/wd0b as swap device
Tue May 10 07:54:57 GMT 2011

Done running shutdown hooks.
May 10 07:55:10 qemu syslogd[151]: Exiting on signal 15
syncing disks… 3 done

unmounting 0xcb6de004 /proc (procfs)…
unmounting 0xcb68f004 /dev/pts (ptyfs)…
unmounting 0xcb65f604 /kern (kernfs)…
unmounting 0xca77820c / (/dev/wd0a)…
unmounting 0xca77820c / (/dev/wd0a)…
cd0: detached
sysbeep0: detached
midi0: detached
atapibus0: detached
npx0: detached
pcppi0: detached
atabus1: detached
makphy0: detached
wm0: detached
pchb0: detached
audio0: detached

unmounting 0xca77820c / (/dev/wd0a)…
forcefully unmounting / (/dev/wd0a)…
wd0: detached
atabus0: detached
acpi0: entering state S5