tkchia / gcc-ia16

Fork of Lambertsen & Jenner (& al.)'s IA-16 (Intel 16-bit x86) port of GNU compilers ― added far pointers & more • use https://github.com/tkchia/build-ia16 to build • Ubuntu binaries at https://launchpad.net/%7Etkchia/+archive/ubuntu/build-ia16/ • DJGPP/MS-DOS binaries at https://gitlab.com/tkchia/build-ia16/-/releases • mirror of https://gitlab.com/tkchia/gcc-ia16
GNU General Public License v2.0
178 stars 13 forks source link

Compact model and printf far pointer string format %Fs both not supported #84

Open ecm-pushbx opened 3 years ago

ecm-pushbx commented 3 years ago

Hello! I just finished adapting Ralf Brown's AMITSRS to compile with gcc-ia16 and libi86. I had to copy the signature and description fields into an internal buffer of the program to make it work, using the libi86 _fmemcpy function.

This is part of a comment at the top of the source:

Must be compiled in a large data model (compact recommended) ex. TCC -mc AMITSRS

I assume this is needed to make printf accept far pointer strings for the %s format. Because this memory model is not yet implemented by gcc-ia16 I tried using the %Fs format string to accept far pointers. This appears to not be supported. So I finally settled on the intermediate buffer, which is fine here because the signatures and descriptions are of a known maximum length (80 bytes).

ecm-pushbx commented 3 years ago

Forgot the link: https://hg.pushbx.org/ecm/amitsrs/rev/123031d14d43 This is the commit I made to work around the far string issue.

tkchia commented 3 years ago

Hello @ecm-pushbx,

Yes — unfortunately the newlib-ia16 runtime's printf implementation does not currently grok far pointers. And it seems to be quite non-trivial to add these to the library. (<stdio.h> support is one of the messier parts of Newlib...)

Your workaround is probably as good as it gets, for the time being. 😐

Thank you!

ghaerr commented 3 years ago

Hello @tkchia,

support is one of the messier parts of Newlib...

Wow, looking around in newlib-ia16/newlib/libc/stdio/ shows a lot of code and complexity for a 16-bit library, although it does look like it tries to be ANSI X3J11 compliant. There are also "nano" and "full-blown" versions of the low-level vfprintf and vfscanf functions, on top of which most all the other stdio format-interpretation functions rest.

And it seems to be quite non-trivial to add these to the library.

Looking particularly at nano-vfprintf.c, it would seem that, IF the library is built using the "nano" vfprintf, AND the "string-only" version of the library isn't being built, then changing the definition of __sfputs_r definition as well as the pfunc signature to use a char __far *buf as the third parameter could solve most of the problem without too much ugliness. This would allow a far pointer to be passed to the lower level output function (pfunc), which is statically called in vfprintf_r. Of course, the other areas where a pfunc is passed, such as __printf_common would also need the far pointer signature change.

If the IA-16 library is possibly compiled with a variety of compilation options, the far pointer buffer signature change could manifest into quite a few files, but I'm not sure the library is built separately with many different options?

That change then leaves the problem of the format string to use, and %F is already used for floating point. If perhaps %S were used, instead of a separate prefix option, then a small change in nano-vprintf_i.c for the 's'/'S' case, along with a far _fmemchr should allow either a DS:ptr or user-passed far pointer to the passed pfunc routine for output.

I haven't (yet) tried changing to a far signature and compiling to see how many files/functions this could ripple to, so I might be off base here as to the complexity required for this, and/or whether it's even worth the effort.

Thank you!

ghaerr commented 2 years ago

Hello @tkchia,

Noticing the 'help wanted' on this issue, I took a stab at pulling down newlib-ia16 and tried configuring it but realize it's going to be complicated to understand how to compile and test this with my preferred environment, macOS and ELKS. I thought to as a few questions:

I was never a full fan of ELKS having its own libc. While I'm certainly not proposing newlib-ia16 as a replacement project, the idea of having users of this repository be able to compile and run for an ELKS target might increase the usability of ELKS (and certainly allow for coding and testing on my part).

Thank you!

tkchia commented 2 years ago

Hello @ghaerr,

Sorry for the really late reply! To try to answer some of your questions:

Thank you!

ghaerr commented 2 years ago

Hello @tkchia,

Thank you very much for your explanation of build options, you provided a lot of information unknown to me.

And yes, some work is probably needed to get the scripts working on macOS.

Yes, indeed. It's likely going to need quite a bit of work, for instance none of the arguments passed to script are implemented on macOS. Should I try to jump in and implement far pointer printf strings, it'd be lots easer on Linux.

(plus apparently lithoxs did not quite like Newlib's bloatedness).

Having got quite familiar with ELKS' C library over the last few years, I'd have to say it's smaller size and simplicity is probably better suited for ELKS at this point. ELKS doesn't need the multi-threaded nor multi-processor features either.

instead uses Andrew Jenner's bare-bones 86sim emulator. 86sim should probably also work on macOS.

86sim is a most interesting project!! It readily compiles on macOS. I have already extended it slightly to support a few more MSDOS system calls I ran into while testing some arbitrary .exe programs. I have also found a bug in the usage and meaning of 'loadSegment' internally. Are you at all interested in those modifications, or is your 86sim version only supposed to support the GCC regression tests?

I'm also thinking it could be quite straightforward to slightly rearrange 86sim to more easily support execution of ELKS applications directly. This could possibly prove useful for regression testing and/or debugging. Would you be interested in such an enhancement, or should something like this live in its own repository outside of reenigne and/or gcc-ia16?

Thank you!

tkchia commented 2 years ago

Hello @ghaerr,

I'm also thinking it could be quite straightforward to slightly rearrange 86sim to more easily support execution of ELKS applications directly. This could possibly prove useful for regression testing and/or debugging. Would you be interested in such an enhancement, or should something like this live in its own repository outside of reenigne and/or gcc-ia16?

Yes, I am interested in this (and other patches). :slightly_smiling_face: I am not sure if Mr. Jenner might be interested in any further patches — I think he has other plans for his repository — but I will be glad to accept your changes.

Thank you!

ghaerr commented 2 years ago

Hello @tkchia,

I've started an 86sim fork from your and Andrew Jenner's project, which has initial support for ELKS a.out executables and also continues to load and run MZ executables. It doesn't implement many of the ELKS system calls yet, as the code being contained in a single .cpp file with large procedures makes for tough maintenance of all that.

I haven't yet decided whether to clean it up or what exactly to do with it yet. It seems there is a need for a very small 8086 emulator whose components (emulator, a.out/MZ executable header reading, system calls, etc) might be readily available for project experimentation or quick determination of code execution outside a native OS.

What 86sim lacks is a disassembler to see what is going on. Having that along with 86sim in a very few source files could make off-host debugging of various executable types a lot easier, it seems.

Have you seen Blinkenlights, a super nice text-mode-UI 8086 emulator for 8086 boot and other code? Ultimately, adding the ability to execute MSDOS or ELKS programs to that would be fantastic; unfortunately, it's build is tied heavily to the Actually Portable Executable project and is a complex build running on Linux only.

Thank you!

tkchia commented 2 years ago

Hello @ghaerr,

I haven't yet decided whether to clean it up or what exactly to do with it yet. It seems there is a need for a very small 8086 emulator whose components (emulator, a.out/MZ executable header reading, system calls, etc) might be readily available for project experimentation or quick determination of code execution outside a native OS.

Well... if (and when) you decide that you would like me to merge in your changes, do let me know. :slightly_smiling_face:

Have you seen Blinkenlights, a super nice text-mode-UI 8086 emulator for 8086 boot and other code?

Well, I tried it a bit — and it definitely does look spiffy, though I am not sure about using it day to day. :slightly_smiling_face::slightly_smiling_face:

Thank you!

asiekierka commented 2 years ago

It might be worth to separate this into two issues:

An interesting, niche use-case I found for large model support would be adding gcc-ia16 to this small benchmark project I found.

andrewbird commented 2 years ago

Hello @tkchia, Just a quick note to say I'm also interested in some way of using far pointers to strings with printf(). For now I've worked around it by copying the string data to a near string first, which is fine of course. The suggestion above (using %S) seems attractive as it'd be much cleaner if we could do printf("hello '%S'\n", farstring) instead.

Thank you!