Building for a 24-bit target

Is there any way to build Rust for a 24-bit target? I'm trying to compile for the eZ80 CPU using a fork of LLVM, but it has 24-bit pointers and registers. From a quick glance at the rustc source, it seems like 16, 32, and 64-bit pointers are the only hardcoded values allowed. Is there any way to do this, or am I out of luck?


Well, I'm just one data point, but after a career of more than 17 years in this industry I learned today that some folks actually created a 24-bit machine.

If you'd asked me before today about such a machine, I'd have asked "what's the point?", though the answer relative to 32-bit chips is probably financial in nature.

All this to say, the very notion of a 24-bit machine is highly obscure, so I would be surprised if it was easy to make this work with Rust as-is, assuming it's possible at all.


I think you're out of luck, at least in Rust as it exists today. You'd have to settle for 32-bit pointers.

Maybe you'd be able to add support for it, especially if the 24-bit pointers have alignment 1, 2 or 4. If they have alignment=3 that may be too weird for Rust.

Even the "may" is an understatement; the reference explicitly says that the alignment must always be a power of 2.


It allows addressing 16 MB of RAM, which is just about the size of fast memory (SRAM). This means you don't need complicated caching. And you save 25% of memory for pointers compared to using 32 bits!

I am pretty sure the hardware doesn't require alignment (i.e. alignment 1 is OK).


The problem is not with pointers. eZ80 have native 24bit registers but doesn't have any means to do fast 32bit computations.

As for using Rust… the mere fact that TI added 2nd CPU just to run Python to eZ80 device spokes volumes.

CircuitPython is written in C, which, at least in theory, may work on 24bit machine, and additional hardware cost money… and yet TI decided it's easier to add another, 32bit CPU just for that.

Using segmented memory like with 8086 or Apple-designed 65C816 is harder than using flat 24bit address space.

But of course with typical RAM sizes measured in kilobytes it's not clear whether Rust support is even needed there.

It's not that's entirely useless, but amount of efforts compared to possible benefits…


I just realized that I even owned one at some point: TI-84 Plus series - Wikipedia


Note that if you had version released before 2015 then it was just plain old 8bit Z80.

They upgraded to eZ80 when it was found out that while 8bit Z80 is fast enough to drive USB it's not fast enough to drive TI-84 Plus C SE “large” 320x240 color LCD.

That's why TI upgraded 15MHz Z80 to 48MHz eZ80, primary motivation was 3x clock speed upgrade and Z80 compatibility, not weird 24bit architecture.


I think the amazing fact is not that someone created such device, but the fact that you can actually go to Wallmart (or any large such store) and actually buy it new it if you want to play with this weird 24bit world.

It's just very folks care about it, but it's not piece of unobtanium.


I'm echoing the "today I learned" of others.

Im also wondering if this isn't too weird for (standard) C as well? How are the C primitive integer types defined on this thing? Long is 24 bit?

I feel like the standard assumption of developers trying to be portable is that integers are various powers of 2 (bytes) in size, bytes are 8 bits (these days) and alignment is the same as size of the type (or doesn't matter). No one expects anything made during this century to defy those expectations.

(Yes, there are old systems that defy this. But generally I feel like those tend to be things like the Apollo Guidance Computer, electron tube computers and other very early ones.)

And as such there are probably a lot of assumptions in code that will break.

1 Like

C has no problem with this. short = 16 bits, int = 24 bits, long = 32 bits.

I think there is nothing stopping Rust from supporting this with usize being 24 bits, it's just not implemented in rustc.


Since C has no problem, would compiling to C with something like mrustc, and then compiling the output with the eZ80 toolchain work?

In this case the point is that the eZ80 is basically an extension of the famous Z80 8 bit processor. It can run all your favourite 8 bit Z80 assembler programs. Which seems to be important for certain calculator manufacturers who are still using their calculator software from 1970/80s.

The extension being all about increasing the memory space so that more code and data can be accommodated than the Z80's 64K bytes.

Back in the day Intel's extension of their 8 bit 8085 was the 8088/86, with it's extra 16 bit instructions and 64K memory segments and 20 bit addressing (1 megabyte).

It was a strange world back in the day.

Now, if I understand correctly Rust can be used to program the 8 bit AVR micro-controllers. So could Rust support the 8 bit Z80 subset of the eZ80? I found some attempts at Z80 support in LLVM but they seem to be years old and abandoned.

I'm intrigued by the existence of popular 24-bit machines, but even more so by hearing that these are used as calculators. Do they also have 24-bit floating point arithmetic?

As far as I understand these calculators run software that was written way back when for the 8 bit Z80 microprocessors. They had no hardware floating support, it was all done in assembly language. Almost certainly the floating point format used is nothing like our modern IEEE 754. Given the number of digits these calculators work with I'm guessing the format is bigger than 24 bits.

1 Like

And it's easy to understand why. First ever CPU (made for calculators, naturally) is 2900 transistors. While first math co-processor, 8087 is 49000 transistors, 16 times more. And to achieve even that they had to squeeze two bits into each transistor.

Ironically enough floating point module is way, way, WAY too expensive to have it in the calculator. Even RAM was too expensive to have in first calculators! They used shift registers as memory. But to make calculators easier to implement all early CPUs (even puny 6502) had support for binary-decimal arithmetic.

It's kinda amusing that someone would think calculators have any-bit floating points in hardware, but I guess if you never had to learn programming on these devices because real computer was too expensive for you, then you may not know all these details.

1 Like

Oh yeah. Good old Binary Coded Decimal (BCD) arithmetic and the Decimal Adjust for Addition (DAA) instruction of the Z80.

I had a devil of a time emulating DAA in my 8085/Z80 emulator, written in Parallax Propeller assembly language. There were differences in status flag setting between Intel and Zilog. All for nothing as none of the CP/M operating system or any program I found to run on it used DAA.

Well. Duh. Calculators don't use CP/M. They have their own firmware (whether to call it "OS" or not is tough question).

Is that derogatory tone really necessary for you to make you point?

I said nothing about calculators. I was talking about my Z80 emulator running CP/M on a Parallax Propeller MCU.

Of course.

Now I recall... I did find one program that ran on CP/M and was a test of all possible Z80 instructions. It was written as a test of peoples emulators. Of course I had to get that working 100%, but it turned out that none of the CP/M programs I could find used most of those Z80 instructions. They were built to run on CP/M systems that used the Intel 8085 processor which had far fewer instructions and a slightly different DAA instruction, which was never used anyway. A lot of work for nothing...

1 Like

Not a fully 24-bit target, but I'm working on support for w65, which also has 24-bit pointers. The ABI extends these to 32-bit. For arithmetic, assuming you get a carry flag, you can just do widening arithmetic as usual. This is how w65 would handle >16-bit (it's register and ALU size) operations (except for division)