Tuesday 7 November 2023

Intro

Next : Scope

My first computer was a TI99/4A in 1982. I had a mini-memory module with a whopping 4KiB of RAM that came with a line-by-line assembler on cassette that I used to teach myself machine code for the TMS9900 CPU. I guess that was the start of my career in embedded computing!

Recently I fired up my '99 for the first time in decades and also resumed working on an emulator I had started quite some time ago.  There are several fully featured and mature emulators for the TI now such as MAME and Tursi's Classic99, but I still keep my own one in development as a pet project.  While looking for another interesting project or two to work on, I came across an active community of '99ers on Atari age.  One of the threads there caught my attention.   It was a backend for gcc for the tms9900 by "Insominia" (Eric), started in 2010.  Insomnia also maintained a very informative blog of his findings.  A huge amount of work had gone into this project before I even knew it existed , so I'm definitely "standing on the shoulders of giants" here.

I downloaded and built the compiler and tried it out but soon found some issues with code I was trying to compile.  The first issue I found was local variables were sometimes being trashed.  I didn't initially understand why I was the only one experiencing this, but then found I wasn't using any optimiser flags, whereas other users routinely built with the -O2 or -Os flags.  Without these optimisations selected, gcc creates a stack frame and there were some problems with the implementation.  I soon found there were other problems as well, particularly around byte arithmetic and byte arrays.  There had been no active development for several years despite several people actively trying to use it to compiles games and various tools.  So, I had found my challenge and delved into the code to understand what has happening.

I soon found out that the bulk of the functionality is implemented in a "machine description" language which necessitated a bit of background reading. The documentation for creating machine descriptions is good, but not great.  The docs do have some very detailed descriptions of the various options like define_insn, define_expand and so on, but really don’t offer a lot in terms of when or where to use them.  There are some good tutorial blogs such as this one but a lot of what I found out was through trial and error.

So I thought it would be helpful therefore to document my journey along the learning curve and the options I explored to explain some of the choices I made when making changes and publishing updates to this gcc backend, in case anyone else wants to get involved, or I get hit by a bus, etc. As a typical engineer, I've left the documentation to the end, so I'm writing this retrospectively with dates approximate to when things were done.  

The code is in github.  Each release has its own branch (latest is 1.31) which has many commits.  These are squashed and merged to main for each release.  I like to keep the dev branches though so I can go back through the commit history to see what I changed.

The README has the release notes and install instructions.  There is a bug tracker here.  Feel free to add bugs but please do include a code sample so I can reproduce it.

In this blog, traps I've fallen into are marked with NOTE.  Code samples are marked like this.  Code samples use TI opcodes and notation.  Hex numbers are prefixed with >, labels are prefixed with @ and so on.  Register numbers are optional so MOV 1,1 is the same as MOV r1,r1.  Any time I refer to a word I mean a 16-bit value (a C short) and a long is 32-bits (a C int).


I published the URL to this blog on atari age.  The posts are in reverse chronological order but the best place to start is the beginning .