Jump to content
IGNORED

GCC for the TI


insomnia

Recommended Posts

Hopefully I'm not overdoing my welcome here, with all my questions.

 

All the examples I have for EA5 programs use BL @main in the crt_eas5.asm file. Is it possible, to launch EA5 apps in XB (2.9) with CALL MLOAD and return to XB? Or how should I build GCC apps such that they can be run from inside the XB env and return? When I write XB programs and compile, I receive an OBJ output file that I can readily link into an EA5 or another version that XB recognizes as an XB program and can use CALL RUN. Sorry I don't know what that latter type is called. When using GCC I have an object file, but it is in ELF format. 

 

I can't help but wonder if most folks using GCC stick mostly to cartridges to take advantage of the more usable space (cartridge address space + RAM). 32KB isn't much to contain both program and data. I also read somewhere and can't find another reference about some cartridge type that could map in multiple ROMs. Can someone point me to that format?

Link to comment
Share on other sites

30 minutes ago, mrvan said:

Hopefully I'm not overdoing my welcome here, with all my questions.

 

All the examples I have for EA5 programs use BL @main in the crt_eas5.asm file. Is it possible, to launch EA5 apps in XB (2.9) with CALL MLOAD and return to XB? Or how should I build GCC apps such that they can be run from inside the XB env and return? When I write XB programs and compile, I receive an OBJ output file that I can readily link into an EA5 or another version that XB recognizes as an XB program and can use CALL RUN. Sorry I don't know what that latter type is called. When using GCC I have an object file, but it is in ELF format. 

 

I can't help but wonder if most folks using GCC stick mostly to cartridges to take advantage of the more usable space (cartridge address space + RAM). 32KB isn't much to contain both program and data. I also read somewhere and can't find another reference about some cartridge type that could map in multiple ROMs. Can someone point me to that format?

I have examples of utilizing vast cartridge ROM and SAMS ram, but they are not beginner friendly, for accessing all the cartridge banking, and even SAMS ram bank switching. My approach changes the way you write the code... https://github.com/jedimatt42/fcmd 

 

As for using gcc to build overlays to work with the XB 2.9 environment, it's a little bit of a chocolate and peanut-butter issue... it may end up great, but those with the necessary knowledge aren't likely to bump into each other. Coercing the elf binary into an XB friendly loadable module might be do-able. But I'm guessing you'd have to spec out what CALL MLOAD does for us before we could help. Texas Instrument's CALL LOAD handles their uncompressed tag object format... It also stashes addresses into a link table so CALL LINK can find them by name. I would imagine to build some interoperability with any variant of XB, you would have to write a custom entry point ( usually what the crt variants provide ) that makes sure your code gets loaded where it needs to be, and when your C function is returned from, returns to XB correctly. I don't actually know what XB (2.9) is, but if this is XB GEM, I hear that returning correctly is a bespoke issue. 

 

I would expect, that in order to get far enough along to build interoperable components between GCC and any XB, you will have learned enough 4A assembly to just do XB and assembly, or learned enough of the 4A architecture to realize that you can do the stuff that XB makes look easy, pretty easy in C. 

  • Like 1
Link to comment
Share on other sites

12 hours ago, jedimatt42 said:

I have examples of utilizing vast cartridge ROM and SAMS ram, but they are not beginner friendly, for accessing all the cartridge banking, and even SAMS ram bank switching. My approach changes the way you write the code... https://github.com/jedimatt42/fcmd 

 

As for using gcc to build overlays to work with the XB 2.9 environment, it's a little bit of a chocolate and peanut-butter issue... it may end up great, but those with the necessary knowledge aren't likely to bump into each other. Coercing the elf binary into an XB friendly loadable module might be do-able. But I'm guessing you'd have to spec out what CALL MLOAD does for us before we could help. Texas Instrument's CALL LOAD handles their uncompressed tag object format... It also stashes addresses into a link table so CALL LINK can find them by name. I would imagine to build some interoperability with any variant of XB, you would have to write a custom entry point ( usually what the crt variants provide ) that makes sure your code gets loaded where it needs to be, and when your C function is returned from, returns to XB correctly. I don't actually know what XB (2.9) is, but if this is XB GEM, I hear that returning correctly is a bespoke issue. 

 

I would expect, that in order to get far enough along to build interoperable components between GCC and any XB, you will have learned enough 4A assembly to just do XB and assembly, or learned enough of the 4A architecture to realize that you can do the stuff that XB makes look easy, pretty easy in C. 

Thanks jedimatt42. I've started reviewing your code and it does provide insight into quite a bit. I definitely have more learning to go. And yes, I imagine the experts in such details are few and far between with the small number of folks that dare to step back 40+ years into the past for these machines.

Link to comment
Share on other sites

On 4/8/2023 at 5:32 PM, jedimatt42 said:

I have examples of utilizing vast cartridge ROM and SAMS ram, but they are not beginner friendly, for accessing all the cartridge banking, and even SAMS ram bank switching. My approach changes the way you write the code... https://github.com/jedimatt42/fcmd 

 

As for using gcc to build overlays to work with the XB 2.9 environment, it's a little bit of a chocolate and peanut-butter issue... it may end up great, but those with the necessary knowledge aren't likely to bump into each other. Coercing the elf binary into an XB friendly loadable module might be do-able. But I'm guessing you'd have to spec out what CALL MLOAD does for us before we could help. Texas Instrument's CALL LOAD handles their uncompressed tag object format... It also stashes addresses into a link table so CALL LINK can find them by name. I would imagine to build some interoperability with any variant of XB, you would have to write a custom entry point ( usually what the crt variants provide ) that makes sure your code gets loaded where it needs to be, and when your C function is returned from, returns to XB correctly. I don't actually know what XB (2.9) is, but if this is XB GEM, I hear that returning correctly is a bespoke issue. 

 

I would expect, that in order to get far enough along to build interoperable components between GCC and any XB, you will have learned enough 4A assembly to just do XB and assembly, or learned enough of the 4A architecture to realize that you can do the stuff that XB makes look easy, pretty easy in C. 

I'm working my way through things...

 

Hi jedditmatt42,

 

I'm still on my quest to figure out full type support provided with this GCC compiler, and was looking for the source for libgcc in particular. I found your extremely simple to follow instructions for building GCC in Linux at https://github-wiki-see.page/m/jedimatt42/fcmd/wiki/tms9900gcc-Ubuntu-Installation-Guide. I can confirm they still work as of Ubuntu 22.04, and on ARM64 (a new Mac M2 Max) in Parallels Desktop, with the following updates:

 

In build/binutils-2.19.1/config.guess, duplicate the lines 964-966, place immediately after, and change the new switch condition from x86_64 to aarch64.

 

Same change in build/gcc-4.4.0/config.guess, duplicate the lines 980-882 and make the same change as before.

 

I may eventually dare to attempt installation directly in MacOS, but will save that for another day.

  • Like 3
Link to comment
Share on other sites

@mrvan I have not tried, yet to build @EtchedPixels compiler but I am pretty sure it must be possible to build it and use to compile something. At lest this is what @EtchedPixels has reported.
If I remember well @EtchedPixels compiler is spread across 3 GitHub repositories. So the build process requires some extra work.
@EtchedPixelscould you please write some simple instructions ? or, even better, maybe put everything into a single repository ?

Link to comment
Share on other sites

4 hours ago, Fabrizio Caruso said:

@mrvan I have not tried, yet to build @EtchedPixels compiler but I am pretty sure it must be possible to build it and use to compile something. At lest this is what @EtchedPixels has reported.
If I remember well @EtchedPixels compiler is spread across 3 GitHub repositories. So the build process requires some extra work.
@EtchedPixelscould you please write some simple instructions ? or, even better, maybe put everything into a single repository ?

Thank you, Fabrizio Caruso. I'm managing to get by with GCC, with its many limitations. But it is C, and for that I am very thankful. Even in that, I'm busily adding methods that are normally part of libgcc, to support longs, floats and doubles. 

Link to comment
Share on other sites

Can anyone point me to how I can call the GROM methods for math from GCC? I've bothered to implement C methods for atol, atof, add for long/ulong/double, but read these may be implemented in the console GROM. There still may be an issue even if I use the GROM methods, at least for doubles, as the GCC compiler generates incorrect RADIX 100 formats for double literals (I've studied the format and printed the hex)--for instance 1.0 generates 0x3F 0x01 0x00... if I recall, rather than 0x40 0x01, 0x00... Also several violations of the mantissa values being over 99. I might be able to fix the GCC compiler, but have not gotten too deep into understanding its details, beyond learning about the GCC library, which is related but separate. This may end up on my list, unless the other C compiler proves to be superior.

Link to comment
Share on other sites

1 hour ago, mrvan said:

Can anyone point me to how I can call the GROM methods for math from GCC? I've bothered to implement C methods for atol, atof, add for long/ulong/double, but read these may be implemented in the console GROM. There still may be an issue even if I use the GROM methods, at least for doubles, as the GCC compiler generates incorrect RADIX 100 formats for double literals (I've studied the format and printed the hex)--for instance 1.0 generates 0x3F 0x01 0x00... if I recall, rather than 0x40 0x01, 0x00... Also several violations of the mantissa values being over 99. I might be able to fix the GCC compiler, but have not gotten too deep into understanding its details, beyond learning about the GCC library, which is related but separate. This may end up on my list, unless the other C compiler proves to be superior.

I call one of the routines here for the builtin float to int: https://github.com/jedimatt42/fcmd/blob/a4e2ad136eb0d3b2d33b67e644d8ac3417becc94/b2_tifloat.c#L55

 

The input parameter was the address of the TI float data. 

 

The address of the routines can be found in the TI Intern. For the float to int, there was no benefit in using the XMLLNK overhead. I did not examine the other routines. I've had no use for actual floats.  Float arithmetic is a choice, and usually sub-optimal unless you need to show a result as a float. 

  • Like 1
Link to comment
Share on other sites

7 hours ago, jedimatt42 said:

I call one of the routines here for the builtin float to int: https://github.com/jedimatt42/fcmd/blob/a4e2ad136eb0d3b2d33b67e644d8ac3417becc94/b2_tifloat.c#L55

 

The input parameter was the address of the TI float data. 

 

The address of the routines can be found in the TI Intern. For the float to int, there was no benefit in using the XMLLNK overhead. I did not examine the other routines. I've had no use for actual floats.  Float arithmetic is a choice, and usually sub-optimal unless you need to show a result as a float. 

Awesome, thank you! I found this guide at https://www.unige.ch/medecine/nouspikel/ti99/reals.htm. Your example provides just enough detail that I can find my way between this doc and your code. I'll still have to determine how to get to the GROM methods. I need to spend a bit more time looking over this link and your code.

Link to comment
Share on other sites

On 4/15/2023 at 3:06 PM, jedimatt42 said:

I call one of the routines here for the builtin float to int: https://github.com/jedimatt42/fcmd/blob/a4e2ad136eb0d3b2d33b67e644d8ac3417becc94/b2_tifloat.c#L55

 

The input parameter was the address of the TI float data. 

 

The address of the routines can be found in the TI Intern. For the float to int, there was no benefit in using the XMLLNK overhead. I did not examine the other routines. I've had no use for actual floats.  Float arithmetic is a choice, and usually sub-optimal unless you need to show a result as a float. 

Thanks jedimatt42. I was able to modify to perform a floating point (double) add.

  • Like 2
Link to comment
Share on other sites

  • 1 month later...

Hi all, I've continued my trek with GCC, and am having a very nice time. I found some of insomnia's floating point work and a decent amount of standard C and asm library methods which I presume he also wrote. Some is incomplete but easily recognized and excludable--I sure wish he'd return. I want a relatively full featured C99 environment.

 

So I've written stdio's fopen, fputs, fgets and fclose, wrapping the DSR calls with a thin veneer. I'll work all the others later as they are variations, and these are sufficient for my immediate needs. I expected it to be more difficult as the DSR routines are somewhat cryptic but found enough hints in jeddimatt42's repository.

 

My next somewhat obvious step, is to add stdin, stdout, and stderr and then that leads to special files. I don't and won't have /dev/* as in *nix, so have thought to just define reasonable names for pio, rs232, etc., as TI did in XB. stdout is easily mapped calling conio*(), and similar for stdin.

 

Next is the parallel port...that's where I'm getting stuck.

 

I have a const char *s as input to a method and then have:

         p = (char *) s; 

         while (*p) {

            rs232_writePIO (RS232_ALT_CARD, *p);

            p++;

         }

No write to the parallel port. I've also tried RS232_CARD as well, no go.

 

Any thoughts as to what the issue may be, or perhaps you might know of an example that works? If it matters, I'm using MAME and have the parallel port mapped to output to a file. I've used PIO in XB successfully so know it works in my configuration. My program is an EA5 that I start in XB with call mload().

 

Thank you in advance,

mrvan 

Link to comment
Share on other sites

I am probably missing something but if you have fopen, fputs, fgets and fclose working with files via the DSR now,

then you should be able to fopen "PIO"  and use fputs to send data to it shouldn't you?

 

If you want to write your own driver then you need CRU functions to enable the card.

Assembler is probably best for that. 

 

Sample programs are here:

www.unige.ch/medecine/nouspikel/ti99/rs232c.htm

 

 

  • Like 1
Link to comment
Share on other sites

3 hours ago, TheBF said:

I am probably missing something but if you have fopen, fputs, fgets and fclose working with files via the DSR now,

then you should be able to fopen "PIO"  and use fputs to send data to it shouldn't you?

 

If you want to write your own driver then you need CRU functions to enable the card.

Assembler is probably best for that. 

 

Sample programs are here:

www.unige.ch/medecine/nouspikel/ti99/ 

 

 

Hi TheBF, yes, I thought the DSR routine should have worked as well...Those for the disks work for all regular files, including those in directories and on a hard drive. From all I read, the DSR should respond for the filename PIO. As I've dug through this more, there are claims that some parallel cards out there may not respond except by using the DSR, so that seems to be the right way. I'm in MAME so perhaps doesn't matter right now, but I do intend to get back to a real TI-99 if my wife doesn't catch me and block my purchase--I have more than my fair share of hobby space already.

 

So I went back to opening "PIO" via DSR and received a return of 0xE0 which is DSR_ERR_FILEERROR. I reconfirmed that I can indeed write to "PIO" in XB, to make sure I wasn't chasing a rabbit. 

  • Like 2
Link to comment
Share on other sites

For what it's worth, I just tried opening RS232 and PIO on my Forth system on real iron and I get an error as well.

I never intended to use the DSR for either since they give no benefit to a Forth system versus my own code, but I don't know why my DSRLINK does not let me open them.

  • Like 1
Link to comment
Share on other sites

17 hours ago, TheBF said:

In the "that's interesting C" department: 

 

If you don't like GCC for TI maybe you would like to create the absolute opposite end of the spectrum. :) 

 

Sector C  (512 bytes)

xorvoid

OMFG

 

That is the most badass programming I have seen... ever
 

Maybe it's because I've spent the last couple weeks writing lexers and parsers. I've got thousands of lines of code and not even touched codegen!  
 

Barely C is getting all this done in 512 bytes??!!  I gotta tell my colleagues who think little of Forth. 

 

Maybe because I've regarded compilers as an out-of-reach  dark art since childhood, when I saw Clint Pulley's C99 really compiling. Didn't comprehend most compiler science. 

(aside: my lexer-parser now does a big chunk of C... I'm calling it "SwanC".)
 

Maybe because gcc and llvm are such giant hundred-handed monsters

512 bytes??!!

 

 

OMFG. 

  • Like 4
  • Haha 2
Link to comment
Share on other sites

  • 2 weeks later...
On 5/24/2023 at 5:11 PM, TheBF said:

In the "that's interesting C" department: 

 

If you don't like GCC for TI maybe you would like to create the absolute opposite end of the spectrum. :) 

 

Sector C  (512 bytes)

xorvoid

Dang I'll try to never complain again about running in a mere 32KB!

Link to comment
Share on other sites

On 5/19/2023 at 6:09 PM, jedimatt42 said:

The flags in the PAB might be important. I would expect it (PIO) must be sequential, and I would try starting with output mode. 

I read all the status flags and nothing was abnormal, I also noted in your code the need to read back the PAB to get the status.

 

I put this problem on the back burner for a few weeks, having plenty of other areas I wanted to address. But today was the day to address this. I created a separate method to perform the DSR open, write and close together. No bytes written. So I went back to the TI Tech Pages and studied every detail. https://www.unige.ch/medecine/nouspikel/ti99/rs232c.htm#CRU map. I assessed the ASM language in libti99 for the direct writing (not using DSR as it seems to recommend) and all looked good. I also compared with your enable/disableROM methods. As I studied further I looked over the example ASM code nouspikel documented, and it finally jumped out at me that his example code used handshaking. I added the write handshaking and the first byte came out. So I then added the acknowledge handshaking and all the bytes were written. 

 

So it seems that MAME doesn't address handshaking when directing PIO to a file. But it bothers me that XB and PIO work just fine in MAME, so I'm wondering if XB uses DSR or lower-level CRU and direct write to the port. And if lower level, does it also perform both sides of the handshaking, or is there some additional thoughtful protocol needed, such as waiting t time for an acknowledge and if not received then self-do.

 

One positive thing came from this exercise, aside from all the learning, was that I had reserved space for multiple PABs in the VDP, and had done so sequentially. In studying the code from front to back I noticed that the filename was appended to the end of the PAB during the dsrlnk call. That's a bit of a landmine. I had only reserved sizeof (pab) space. I reserved 32 bytes for filename for now...I know I've seen some max length somewhere but don't recall where, that has enough space for the drive, directories and the filename. The longest path on my virtual HD is 24 bytes.

 

Enough for now, but I appreciate all the assistance. 

Link to comment
Share on other sites

Enhancement for elf2cart - writes .data section initialization data and adds _init_data.

 

I noticed as part of chasing down a difficult bug, that the ROM-based images written by elf2cart.c don't have the initial values for the .data section. Thus items can have invalid/uninitialized values that should have initialized values. This affects libti99, which sets some initial values, most notably the pointers for the methods vdpchar and scrn_scroll defined as:

 

void (*vdpchar)(int pAddr, int ch) = vdpchar_default;

void (*scrn_scroll)() = scrn_scroll_default;

 

 

Since writing a single char to VDP is inefficient and scrolling is not so pleasant on the TI99, it's possible these methods are rarely used, so perhaps this wasn't noticed, or perhaps folks just worked around it.

 

I spent the morning updating elf2cart.c with broad sections of elf2ea5.c that address the source data section and also nicely write the _init_data structure. I thought to retain compatibility with the previous version that doesn't write the .data source, but I see it more as an omission/bug that makes legal C code not operate correctly.

 

This has the nice effect that _start methods between ea5s and carts can be identical, initializing both .data and .bss sections. This will help ensure that each environment starts with mostly the same rules. I'm thankful that insomnia obviously wrote the elf2ea5 program using the initial source for elf2cart and that made my update fairly straight forward.

 

I've attached elf2cart and example _start method.

elf2cart.tar.gz start_cart.asm

  • Like 5
  • Thanks 1
Link to comment
Share on other sites

On 6/5/2023 at 11:03 PM, mrvan said:

So it seems that MAME doesn't address handshaking when directing PIO to a file. But it bothers me that XB and PIO work just fine in MAME, so I'm wondering if XB uses DSR or lower-level CRU and direct write to the port.

Someone can correct me if needed but since the PIO is accessed via the OPEN command in XB, it's a pretty safe bet that it is using DSR code on the board.

On 6/5/2023 at 11:03 PM, mrvan said:

One positive thing came from this exercise, aside from all the learning, was that I had reserved space for multiple PABs in the VDP, and had done so sequentially. In studying the code from front to back I noticed that the filename was appended to the end of the PAB during the dsrlnk call. That's a bit of a landmine. I had only reserved sizeof (pab) space. I reserved 32 bytes for filename for now...I know I've seen some max length somewhere but don't recall where, that has enough space for the drive, directories and the filename. The longest path on my virtual HD is 24 bytes.

Yes the file name field in the PAB is a byte counted string at the end of the PAB data structure, as you have discovered. 

It documented in the editor assembler manual in the file section with other good stuff on file access that might be useful in your search. ?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...