The EightThirtyTwo ISA – Part 15 – 2020-02-06
I’ve joked a few times in this series about being too lazy to write an assember – but it would be more true to say that the stop-gap solution I was using was adequate, so my time was better spent on the more enjoyable aspects of the project. I am now feeling the limitations of using the GNU assembler to produce a bytestream for a target it knows nothing about, and to improve either the performance or code density of the vbcc backend’s output any further, I need to address the problem I’ve had so far with cross-module references…
The most efficient way to reference a symbol with the 832 architecture is to use successive “li” instructions to build a PC-relative offset six bits at a time. That’s fine if the reference and its target are in the same source module and section, since then the offset is fixed, and can’t change during the linking process. The problem is with cross-module references, since we then have a link-time determined value to be broken up into six-bit chunks and inserted into successive ‘li’ instructions.
That’s not possible with the current solution, so I’m currently using a less efficient method, a ‘ldinc r7’ instruction followed by an inline 32-bit reference. This works fine but is a bit of a performance drag since it causes the instruction prefetch to be flushed as the program counter skips over the inlined constant, then triggers a separate load for that constant. Worse still, since the instruction stream is a stream of bytes, there’s no alignment guarantee for the loaded reference, so on average three out of four such references will require two loads!
For this reason, the time has come to write not only an assembler, but a linker too.
The options are to adapt an existing project or start from scratch, and I’m likely to learn more from the latter option, so that’s my plan. While my first instinct when tackling this kind of project would be to reach for C++, I’m actually going to use plain C this time, simply because it would be nice if the toolchain could eventually be self-hosting, and I don’t imagine a C++ compiler for 832 will come into existence any time soon!
So in the interests of keeping things as simple as possible I have defined a new object file format specifically for 832 consisting of…:
- Header – 4 bytes: ASCII “832” followed by 01, which will serve as a version number if I change the format later on. The linker will skip over this header if it’s encountered in the middle of an object file, so linker libraries can be created simply by concatenating object files. (Is my Amiga heritage showing?!)
- “SECT” designates a section, which will contain a list of symbols, references, and optionally a binary blob.
- “SYMB” designates a list of symbols
- “REFS” designates a list of references
- “BNRY” designates a binary blob. This will be missing from BSS sections.
There’s no great trick to assembling a file to this object format – it’s merely an exercise in parsing. For now there’s no support for expressions or fancy calculations between symbols – it merely supports the facilities required to assemble C code emitted by the vbcc backend.
Assembling, however, is very much the easy bit…