3

I've downloaded Sourcery IA16 compiler, which is a GNU C++ compiler for 16-bit targets, and it works (although, it does not support far pointers, and have some glitches with inline asm register allocation, whatever).

But when I declare a float variable in C, the compiler says:

/tmp/ccBB3kEN.o: In function `foo()':
(.text+0x38): undefined reference to `__floatsisf'
/tmp/ccBB3kEN.o: In function `foo()':
(.text+0x44): undefined reference to `__mulsf3'
/tmp/ccBB3kEN.o: In function `foo()':
(.text+0x4c): undefined reference to `__fixsfsi'

As figure shows, by default, it wants to use soft-fpu, so I tought, I should add some compiler options to generate native FPU code. But I've failed.

Now I'm using compiler option -march=i80186, and the help says that I should add some postfix to it:

-march=CPU[,+EXTENSION...]
  Igenerate code for CPU and EXTENSION, CPU is one of:
  generic32, generic64, i386, i486, i586, i686,
  pentium, pentiumpro, pentiumii, pentiumiii, pentium4,
  prescott, nocona, core, core2, corei7, l1om, k1om,
  iamcu, k6, k6_2, athlon, opteron, k8, amdfam10,
  bdver1, bdver2, bdver3, bdver4, znver1, btver1,
  btver2
EXTENSION is combination of:
  8087, 287, 387, no87, mmx, nommx, sse, sse2, sse3,
  (etc.)

It looks like help text is not for IA16, as it does not contains 16-bit CPUs (but contains 32/64-bit ones), and also extensions do not work, I've been tried with -march=i8086,8087:

ia16-elf-g++: error: unrecognized command line option '-march=i8086,8087

Other options, like -mhard-float also does not work.

ia16-elf-g++: error: unrecognized command line option '-mhard-float'

My question is: how can I set 8086 + 8087 target for this compiler? If it does not support it, is there any other C/C++ compiler which can produce MS-DOS .com output with FPU code (on Linux or MacOS platforms)?

ern0
  • 3,074
  • 25
  • 40
  • My recollection of FPU emulation back in the DOS days was that when the software routine was called it would check if the 8087 coprocessor was installed, and if so it would patch the call site to be native 8087 opcodes. Then it would return to the patched opcodes to do the work (and of course any subsequent execution of that code wouldn't even make a call to the software routine). I don't know if the GCC FPU emulation library does the same thing, but it might be worth checking. – Michael Burr Oct 01 '17 at 01:20
  • BTW I've seen OpenWacom being used to compile MS-DOS executables in various projects; it may not be as updated and standard-compliant as gcc, but Wacom has been a production-strenght compiler for DOS for quite some time, while I don't think gcc ever really was. – Matteo Italia Oct 01 '17 at 02:13
  • @MichaelBurr: IIRC all x87 opcodes were emitted with a special mangled first byte that would trap; the interrupt routine would then check if the coprocessor was available, if so it would patch the opcode and resume, otherwise it would do the calculation in software. But from this kind of linker errors (directly in the relevant function and not in some support library), I think that gcc is just trying to perform all the calculations in software. – Matteo Italia Oct 01 '17 at 02:18
  • The "8087" had multiple versions and wasn't really even fully IEEE 754. The 80{1,2,3}87 were more standardized. Unfortunately, the ia16-elf toolchain appears to only support the 387, which is a strict superset of the 287 (adding `FP{,A}TAN` wider bounds, `SIN` and `COS`). –  Oct 01 '17 at 03:00

1 Answers1

1

Docs are at path/to/share/doc/sourceryg++-ia16-elf/man/man1/ia16-elf-g++.1

If the target emulator or device isn't a 80{{,1}8{6,8},286} : -mfpmath=80387

Note that ia16-elf-g{++,cc} produce tiny model .COM files by default.

You can also try -march=i8086+8087, but this might only work with as.