Comment by PaulHoule

3 days ago

I guess next week they're going to get to the interesting bit which is how weird the architecture actually was on that thing...

https://en.wikipedia.org/wiki/TI-99/4A

Particularly it only had 256 bytes of RAM attached to the CPU but had (I think) 16 kb of RAM attached to the video controller which the CPU could read and write through I/O registers. You could use this for non-video storage but you couldn't access it directly.

Coding in BASIC could, at the very least, hide the insanity from you.

It gets way weirder.

The TMS9900 didn't have any internal data registers. It only had a program counter, a status register, and a workspace pointer. Instead, it put the "registers" in that same 256 bytes of RAM. There were sixteen 16-bit registers which the workspace pointer pointed to.

The original idea was that this made for fast context switches, instead of dumping all registers to stack (it doesn't even have a stack pointer), just update the workspace pointer to point at a new set. But I have to assume this wasn't really used on the TI-99/4A, as there just wasn't enough RAM. Because your only other ram was locked behind the video controller, that 256 bytes had to contain all your registers, any your dynamically loaded code and any data you wanted rapid access to.

The TMS9900 is weird, because it's the only CPU of the early home computer era that wasn't designed for microcomputers. It's actually an implementation of the TI-990 mini-computer on a single chip and is actually used in later versions of the minicomputer. Those minicomputers had more than enough fast 16-bit memory to take advantage of this fast context switching.

Every other commonly used microprocessor of the 70s (8080, 6800, F8, 6502, RCA1802, Z80, 6809, 8086, 68000) was explicitly designed to target the low-cost microcomputer market.

  • I've been working on a TMS99110 homebrew & emulator, and have studied the architecture of the 990 a whole lot over the past couple years. I want to make a very important distinction in a few things you said.

    For anyone that didn't get the context, it's the 99/4 design that has this weird RAM layout. The 990 architecture itself can use any (16-bit) word in memory as the starting point of the 16 registers. Developers have been known to use and abuse the workspace pointer to slide around the "window" on the registers.

    The window itself also uses the top three registers to link back to the previous workspace, status, and PC, if you use the proper instructions to branch and return. While there is no stack*, you can still crawl back through those references and get the state of each call.

    It's a really cool little architecture, hobbled by the 16-bit address space and how slow it was to keep the registers in RAM. Nowadays I can pick up a 1MB memory chip that's faster than the native bus speed for a few bucks, but that wasn't anywhere near the case in the late 70s and early 80s.

    *: The 990/12 minicomputer features the PSHS and POPS instructions, which take a pointer to a definition of where the stack lives and how big it should be. These instructions are not implemented in any production processor, but the platform makes it possible to emulate these instructions in software transparently... as an actual explicit instead of accidental feature in the later few iterations. The 990/12 itself was microcoded on a set of four daisy-chained programmable 4-bit bit slicers so they didn't need any of that nonsense.

  • If you disasembled the ROMs you'd find they're filled with BLWP/RTWP instructions. That's how subroutines were executed: Branch and Load Workspace Pointer. The BLWP instruction would load the WP and PC from the next two words and save the current WP/PC/SR into the new R13/14/15. RTWP would restore R13/14/15 into WP/PC/SR. The end result was a stack implemented as a linked list instead of a contiguous array. A lot of the subroutines in ROM just read/wrote tokens from/to the VRAM and then interpreted them as BASIC.

    • Back when I lived in Texas and they started doing vanity plates, I applied for the plate "BLWP" (I lived in D/FW and visited Lubbock from time to time, so there was a non-zero chance someone driving by would get it.) After waiting a month, I got the letter from the DPS... no... someone beat me to it. So I guess there were at least two fans of the 990's memory-to-memory architecture out there.

  • So before people start saying "OMG! Memory-to-Memory architectures are so slow! What a stupid idea!" allow me to remind people that back in the early 70s when the 960 was turning into the 990, external bipolar memory was faster than on-chip NMOS static RAM. And since the 960 and 990 were originally implemented with a weird collection of ASICs, discrete parts and 7400-series logic chips, the idea that you would just drop a bipolar part in the design wasn't that weird of an idea. But then as the 990 evolved and TI built a single chip implementation, they retained the memory-to-memory architecture for software compatibility reasons. So yeah... ultimately... CMOS logic got faster than bipolar memory and in retrospect it wasn't the greatest design. But at the time it wasn't THAT bad of an idea. And yeah, it did make task switching very fast. But don't get me started on serial IO off the CPU. And dang, what a great, largely orthogonal instruction set. I sometimes fire up the Assembler / Editor on my 99/4 emulator just to play with it.

    Anywho... this isn't a critique of the OP or @phire, it's a reminder for the community at large that tech decisions that seem bad in retrospect often had non-idiotic motivations at the time.

Speaking of interesting bits, this machine isn't actually an 8-bit computer, the CPU is 16-bit. (The video controller is 8-bit though, i.e. the VRAM data bus is 8-bits. It's also the same video controller used in various other machines, e.g. MSX.)

  • The other early 16-bit CPUs include:

    National Instrument's PACE- I've never seen one used in anything: https://en.wikipedia.org/wiki/National_Semiconductor_PACE

    but its bit-slice precursor, the IMP-16 was used in Aston Martin's Lagonda https://sprague.com/peter-sprague/aston-martin/

    https://opposite-lock.com/topic/90934/lagonda-dashboards

    General Instrument's CP1600, used in the Intellivision (a video game console yes, but there was a home computer keyboard attachment).

    http://spatula-city.org/~im14u2c/chips/GICP1600.pdf

    Its co-processor, the CP1640 is famous for evolving into Microchip's PIC microcontroller.

    • Much more influential 16-bit CPUs from that era include the PDP-11's CPU, the Data General Nova's CPU, the Xerox Alto's CPU, and arguably even the 8086 and 8088. The chronology seems to go as follows:

      - 01965: IBM 1130

      - 01966: HP 2116A, the first model of the HP 2100 series

      - 01969: Nova

      - 01970: PDP-11

      - 01971: IBM System/7

      - 01973: Alto (not shipped. NEVER shipped)

      - 01973: TI-990 (the 990/3, according to https://cozx.com/dpitts/ti990.html)

      - 01974: HP 3000

      - 01974: PACE (which was from National Semiconductor, not National Instruments)

      - 01975: CP1600

      - 01976: TMS9900 (what the TI-99/4A used)

      - 01976: Tandem (first Tandem/16 shipped to Citibank)

      - 01978: 8086

      - 01979: 8088

      - 01981: TI-99/4A

      Since there were plenty of 6-bit, 8-bit, 12-bit, 32-bit, 36-bit, 60-bit, and 64-bit CPUs in the 01950s, you'd think there would be some 16-bit CPUs then too, but I can't think of any. I'd even forgotten about the HP 2100 until I went looking just now.

      6 replies →

  • "Bits" is a stupid measure of "computer". The TI-99/4A clearly belongs in the 8-bit era of computers.

    Motorola's 68000 was the single most prolific microprocessor of the 16-bit era. Yet all the registers are 32-bit, and all the instructions easily operate on 32-bit values [1]. About the only claim to being "16-bit" is the 16-bit wide data bus.

    If we go by that metric, then the IBM PC (with its 8088 hobbled by an 8-bit data bus) is clearly just another 8-bit microcomputer.

    BTW, this is absolutely the way that Motorola sees it. The 68008 is just a 68000 hobbled with an 8-bit data bus, and they label it as a 8/32-bit microprocessor.

    [1] And if anyone dares to point out that the 68000's ALU is only 16-bits wide, then I have bad news about the Z-80: It only has a 4-bit ALU, so I guess it's actually a 4-bit microprocessor

    • The Amiga was loudly marketed as having a 32-bit CPU though (the Atari ST a lot less so, for whatever reason).

      Having a 16-bit ALU in theory would make the 9900 a 16-bit processor as much as the 8086. The TI-99/4A is definitely weird (and slow!!) but it does fit the definition of a 16-bit system.

      1 reply →

    • Judging by the cycle counts, it's a 16 bit cpu internally? Word operations are almost always cheaper, even when there are no additional memory accesses for the long case. (I think long register to register moves are the only free long case. It's been a while, though.)

    • The '8-bit' micros all had a 16-bit address space, at least in their early implementations. (Later we got the eZ80, 65816, etc.) which lets you address 64k words of memory and the word was always 8-bit bytes.

      Contrast that to the PDP-10 [1] which had a 36 bit word and a 20-bit address space and could access 256k words for a total of 1152 kilobytes.

      The use of 8-bit bytes for characters I think killed off any word size other than 8-bit because otherwise it would be awkward to work with characters. [2] To be efficient you have to pack multiple characters into a word, it's something that comes up common enough you could create some special machine instructions for it, but if you want to support a C compiler you need a char. It's easiest if native pointers point to a byte. If it was otherwise you could make up a char that consists of a native pointer plus a pointer to the char inside the word, but boy what a hassle. [3]

      Modern computers get many of the benefits of a larger word size (wider pipe to suck data through) by having a cache system that decouples the memory interface from the CPU, so a CPU could ask for 32 bits and get it retrieved 8 bits at a time, or it could ask for 32 bits and get the surrounding 128 bits stored in the cache so they don't need to be retrieved next)

      [1] https://en.wikipedia.org/wiki/PDP-10

      [2] DEC had a system of 6-bit characters, which divides nicely into 36, but you have the same problem

      [3] That PDP-10 did have deep pointers that could point to a specific range of bits inside a word, that's what you need if you want something like that to be reasonable to program. I've been thinking about a fantasy computer to run inside Javascript and came across a 48-bit word size to use doubles efficiently to store words. That thing would have 24-bit address spaces, plus it would be possible to make 'deep pointers' that have 6 bits of offset and 6 bits of length (with the possibility of 0-length to point to a specific bit) and could be extended to 'wide pointers' by putting a few bits in front that would reference particular address spaces (might be video RAM, or a unit of memory protection, or made contiguous to represent a larger address space) I think I'd want enough to make a 1GB word address space so it could outdo a 32-bit machine and then let the rest be used for flags just to make it as baroque as possible... And that's why you only see 8-bit words today!

    • Well, I was gonna say this: A CPU is X bits if the highest number of bits that the value of a "load immediate" instruction can have is X. But I think this makes MIPS 16-bit.

      3 replies →

    • > "Bits" is a stupid measure of "computer".

      But that is the very way that they are defined through our historical understanding. The 990 platform, established in 1973, not the 80s, is 16-bit, with 16-bit words and 16-bit pointers.

    • Wait'll you discover that different CPUs use different word lengths, and not just your expected 8-bit X power-of-2 of current modern processors). 36-bit native word with a 9 bit databus and a 16-bit address bus with 64 kilowords of memory... welcome to the fun of early digital computing.

"Coding in BASIC could, at the very least, hide the insanity from you."

Except TI-BASIC is a hell-riddled double-interpreted language. I had a 99/4A at the age of 6, learned how to use all of the TI-BASIC language by 8, and said screw that, hardware it is for me, dad's buying me a 286 for Christmas, time to learn how to build that!

As I recall at the time, very few people knew how to write assembly for that machine, as there just wasn't a lot to go on.

I enjoyed the sprites though, and that was something that was definitely different than Apple II, IBM, etc. at the time. Apple and IBM's graphics were definitely a step down.

C64 could do sprites with POKE statements apparently. But that was definitely not as nice as the TI.