gspac/gspcg pass 0003:0000 (selector index 0, RPL 3) as a null far
pointer; lxConvert1616to32 only special-cased addr1616 == 0 and asserted
on ldt[0]. Segment index 0 is the null selector by definition, so return
NULL. This unblocks the TMS340 C front end (gspac), optimizer (gspopt)
and code generator (gspcg) under 2ine.
Fixes needed to run the 1990 TI 'TMS340 Family Code Generation Tools r5.01'
(16-bit OS/2 1.x NE, DOSCALLS-only) on 2ine:
* CMake: fall back to the system SDL2 headers when /usr/local/include/SDL2
is absent; the hard-coded path broke the build on stock distros.
* doscalls16: implement the entry points these tools import
- Dos16GetDateTime (33) with the OS/2 1.x *hours-first* 10-byte layout
(the year-first 8-byte layout crashes gspa in asctime/localtime)
- Dos16NewSize (68)
- Dos16GetHugeShift (135) / Dos16HugeIncr (136)
- Dos16CreateCSAlias (43), Dos16DevConfig (52), Dos16Move (67)
* lx_loader: walk NE fixup chains to the segment's 64K virtual size instead
of its file size, so fixups pointing into the BSS tail are applied. gspa
segfaulted in a lcall to its CRT exit handler because of this.
* doscalls: do not assert that the host PID fits in 16 bits (pid_max is
4194304 on current kernels); the 16-bit API truncates anyway.
Verified: gspa assembles a 2,412-line TMS34010 source with 'No Errors,
No Warnings', gsplnk links it with rts.lib, gsprom converts to Tek-hex.
The C compiler child (gspac via gspcl) still hits the lxConvert1616to32
selector assertion; see TMS34010.md.
This currently only works with a simple Hello World program, but this is the
bulk of the work to 16-bit program support.
Still need some minor effort to get 16-bit DLLs working, and of course we
need to implement a ton of missing 16-bit API calls.
GLoaderState is moved to a new lib2ine library, which everything links
to and sets up what it can in a DLL constructor, so your app can just
link to doscalls or whatever and it'll have what it needs without
something like lx_loader doing a lot of heavy lifting before your
main() runs.
This is the ring-3 32-bit linear address space's code segment, and it is
hardcoded on OS/2. Generally it isn't explicitly referenced, but things
like CSet/2 would generate thunks that hardcode jmps to it when returning
to 32-bit mode, so you have to patch those out (Linux also hardcodes a
code segment number, but doesn't promise the value won't change, and indeed,
it's different between x86, x86-64, and x86-on-x86-64 apps).
- Let allocateSelector() specify number of pages to allocate.
- Let findSelector() specify if this is a code or data segment.
- Let findSelector() choose if this is a code or data segment
if the caller doesn't know (DosFlatToSel(), etc).
This gets us everything we need (I hope!) to support 16-bit code in LX
binaries and call into 16-bit OS/2 APIs. This is just enough to call
into VioGetMode() (which isn't otherwise implemented yet) as an example.
If this is ever used Winelib-style to provide an OS/2 API to native Linux
binaries, the 16-bit system APIs are 32-bit clean and C callable, as one
might expect them to be. All the tapdancing is to support existing LX
binaries in the loader and bridge between the 32-bit clean APIs and
existing 16-bit code that expects to call 16-bit APIs.
This was a staggering amount of effort, but yay!
Other fixes and improvements probably leaked into this commit, as a
lot of code got touched and a lot of research and debugging took place.
Otherwise, it won't be available to DLL init code when run before the
main executable starts.
Fixes Watcom C's wlink.exe crashing because it gets a NULL command line.