We are still actively working on the spam issue.
/aig/ Alternative ISA General
Alternative ISA General is a discussion thread about non x86 hardware. "Alternative" doesn't mean "unpopular" it means "alternative to x86". While there have been such threads in the past, they were usually sporadic and not very well connected with one another, which meant that whatever transpired in one thread wasn't carried over to the next one.
Due to the rise of desktop-class ARM chips, interest in alternative hardware has risen, with many Anons even coming up with projects of their own. Therefore, a centralised place was needed, where we could keep track of the development and goals of the community.
While discussion of Intel or AMD hardware is not absolutely prohibited (and even if it were, who is gonna enforce this? LOL), due to the ubiquity of x86 hardware, it is assumed that whatever concerns such architecture can be discussed in any of the other gorillion threads on the board.
- 1 Ongoing projects
- 2 Resources
- 3 ISA Overview
- 4 ISA Features
- 5 Microarchitecture
- 6 Weird ISA Types
- 7 ISA Implementations
- 7.1 Processors
- 7.1.1 4 Bit Processors
- 7.1.2 8 Bit Processors
- 7.1.3 16-bit Processors
- 7.1.4 32-bit Processors
- 7.2 VLIW
- 7.3 Home Made Processors
- 7.1 Processors
- 8 Making your own ISA
- 9 Alternative OS for Alternative ISA
- 10 Simulators
- 11 News
- 12 Links
- 13 To Do
Anons are currently interested in porting several open source projects to the PowerPC architecture. Currently the following proposals have been made:
Grand Theft Auto III
Re3 is a homebrew engine intended to replace proprietay RenderWare with an open source implementation. Anons have been discussing making a port for the 32-bit PowerPC version of Mac OS X.
The Elder Scrolls III: Morrowind
OpenMW is a free and open source modern re-implementation of the Gamebryo engine.
OpenLara is a Classic Tomb Raider open-source engine.
Anon has been kind enough to put together a small reference library.
A collection of brief infocards for many different processors is available on TextFiles which also holds huge archives relating to programming and microcomputers, especially 8-bit processors. Also WikiChip and CPU Shack have a lot of information on alternative ISAs, even though the front page is dominated by mainstream processors.
Wikipedia has a Comparison of instruction set architectures. There was also a List of instruction sets which was decided to merge with the Comparison article, but in typical Wikipedia fashion a redirect was made without anyone doing the real work of merging the articles. Thus the archived List of instruction sets is still worth a review.
Also many universities have relevant course work material on ISA online, such as Computation Structures from MIT, with details on Instruction Set Architectures. Many such courses use MIPS or MIPS like examples. There are also How to design your own CPU from scratch blog series, with interactive design examples.
Also the Bootstrapping wiki has a lot of information on ISA types, operating systems and how to bring up your system from scratch.
There are also books available on how to put your processor into a complete computer.
ISA simply means Instruction Set Architecture. This is what the programmer sees from the outside, which these days is very different from the microcode and state machines operating inside the processors, normally inaccessible for normal programmers. The mid 1970's saw a Cambrian explosion of architectures that later fossilised into what we see today. Any assembly programmer and academics such as Hennessy and Patterson agree that x86 stinks, but as usual inertia and money trumps speed, efficiency and elegance. Those three qualities are what we instead celebrate in this general.
The same ISA can be implemented by many different internal architectures and microcode. The ISA is the main topic but since many architectures are DIY, we discuss both. The best way is to illustrate by examples of processors. An ISA is defined by a fairly large set of parameters.
Much can be summarised as CISC (Complex Instruction Set Computer) that is complex, or RISC (Reduced Instruction Set Computer) which is simple. The RISC definition has drifted over the decades, and changed from "simple" to register-to-register based operations with load-store memory handling with greatly reduced and simplified addressing modes.
There is also VLIW (Very Long Instruction Word) processors, where instructions are bundled in long words that can be 128 bit wide. In each bundle there are multiple fixed width instructions. The idea is that the compiler is free to spend a lot time in analysing instruction inter-dependencies, and does explicit and optimised compile time instruction scheduling by placing instructions into bundles. The alternative is that the processor itself does scheduling during run-time. For all the promises, VLIW has turned out to be an excellent idea that compilers are unable to realise. For this reason VLIW processors are not commercial successful but remain obscure niche products such as media processors and DSPs such as Hexagon.
The question is simply few or many. Few is good for low latency, many registers are good for lazy programmers and poor compilers. 6502 managed with just one accumulator plus a handful other registers. Compiler writers prefer at least 16 registers. A few processors have 128 registers or more. One cannot avoid noting modern processors have tons of registers but still seem sluggish.
Operations are performed on registers of some form.
Accumulator based where all processing is via one (or 2, rarely more) main register, examples are most early 8-bit processors.
- Advantage: Efficient, the destination register is implied and saves space in instructions.
- Disadvantage: Too much pressure on a single register, can be harder for parallelism such as out-of-order (ooo) processing.
- Workaround: use two accumulators such as in 6809, at the cost of needing a single bit bitfield in the instructions.
Stack based where everything is performed on a stack.
- Advantage: Efficient, the destination is implied and makes for compact implementations
- Disadvantage: Too much pressure on the stack, can be harder for parallelism such as out-of-order (ooo) processing.
- Workaround: use TOS (top of stack) in a register for fast access and operations, possibly also next on stack (NOS), examples are Novix NC4000 and many virtual processors.
Register file where many registers can be used in similar ways, examples are 68K and many modern processors.
- Advantage: Great freedom in register use, ease of parallelism.
- Disadvantage: Costs a lot in bitfield space in instructions, especially for 3-op ISA.
- Workaround: Split register bank in data- and address registers and cut down on bitfield width, as seen in 68k.
Early designs used a register window where sub routine calls shifted registers in and out of the visible window of accessible registers. The idea appeared to be good but was difficult to use in practice and is not much in use these days.
Registers were originally closely tied to their functions in a CPU, so accumulators were in the ALU while index and address registers were in the address data generators. This is performant and is still used in DSPs but inelegant and awkward. This was replaced by the register file where registers were in an array like a tiny bit of extremely high speed RAM. The specific registers were addressed by a bit field in the instructions.
Modern register files mostly comprise data registers that also can double as address registers.
- Accumulator that is the default destination(s) of operations, usually tightly coupled to the ALU (Arithmetic Logic Unit)
- Data Register similar to accumulator, but on processors with register files such as 68K that had 8 data registers
- Address Registers used for addressing into memory, usually tightly coupled to the data address generators. Stack pointers can be a form of an address register
- Index Registers used for indexing into memory from an offset that may come from an address register
- Status Register is typically a collection of flags set by various ALU or load instructions, the specifics can vary and is a trap for the unwary. Normal flags are Sign, Overflow, Carry, and Zero. These are often used in branch instructions such as Branch on equal (BEQ) which is followed if the zero flag is set.
- Control Register is typically a collection of flags set by user (such as Decimal mode) or in supervisor mode (such as privilege levels)
- Zero Register is a register that always reads zero, frequently seen in RISC ISAs where register 0 (r0) is hardwired to zero.
- Instruction Pointer is hardwired to the part of the processor reading the next instruction. There is a philosophical debate of it should be part of the register file or not. Having it part of the register file makes position independent code simpler.
- Stack Pointer is hardwired to the part of the processor handling the stack.
1-op instructions of the form
2-op instructions of the form
A += X; or
3-op instructions of the form
A = B + C.
The use of 2-op instructions requires a little extra thought but 3-op is simple for lazy programmers and poor compilers. One cannot avoid noting modern processors drift towards 3-op instructions.
In earlier architectures there were also 1-op instructions where the implied target was the target register of the previous instruction. Thus
A += X;
prev += Y; would be equivalent to
A += X;
A += Y; just more compact.
|Accumulator||The instruction operates on the accumulator (and not, say, memory)||6502: ROL A|
|Absolute||The instruction operates on memory defined by a full width address||6502, 16-bit address: LDA $FF00|
|Absolute, X||The instruction operates on memory defined by a full width address, with offset defined by index register X||6502, 16-bit address: LDA $FF00, X|
|Absolute, Y||The instruction operates on memory defined by a full width address, with offset defined by index register Y||6502, 16-bit address: STA $FF00, Y|
|Immediate||The instruction uses data in program memory subsequent to the instruction||6502: LDX #$FD|
|Implied||Data is implied the instruction||6502: SEI|
|Indirect||Data is accessed indirectly via a pointer||6502: JMP ($F000)|
|Indexed Indirect||Data is accessed indirectly via a pointer where the pointer is offset by the X register||6502: LDA ($C0, X)|
|Indirect Indexed||Data is accessed indirectly via a pointer where the target of the pointer is offset by the Y register||6502: LDA ($D0), Y|
|Relative||Data is accessed or program counter is accessed by an offset from present position||6502: BNE $F300|
|Zero Page||Data is accessed from the zero page, addressed by a single byte||6502: LDA $A0|
|Zero Page, X||Data is accessed from the zero page, addressed by a single byte, with offset defined by index register X||6502: LDA $A2, X|
|Zero Page, Y||Data is accessed from the zero page, addressed by a single byte, with offset defined by index register Y||6502: LDA $A4, Y|
|Post Increment||Data is accessed via an address register that is incremented after access||68K: MOVE.L (A0)+,D3|
|Pre Decrement||Data is accessed via an address register that is decremented before access||68K: MOVE.W -(A7),D4|
Implied, immediate, absolute, absolute indexed, zeropage, zeropage indexed, stack relative, index indirect, indirect indexed, all with or without pre/post increment/decrement. Much can be combined. Stack relative addressing is very helpful for C programming, where variables are often transferred to the stack when calling a function. Relative addressing makes it possible to make relocatable code, which is useful when running several programs without MMU.
Zero page was an addressing mode where the address was a single byte and it was implied this related to addresses 0x00 - 0xff where the high byte of the address (the "page") was set to zero. This saved space and time, typically 30 percent. This was later improved by Direct page wherein the page was set by a separate 8-bit register, such as on the 6809. This allowed moving the active page around and reduced the zero page pressure enormously. Lately zero page and direct page have fallen out of fashion.
Von Neuman which is an unified memory architecture for program and data.
Harvard Architecture where program and data are located in different memory spaces. Some DSP processors use multiple independent data busses, for instance DSP56300 and SHARC, the latter meaning Super Harvard Architecture.
Recent designs are often hybrids, in that ISA seen by programmers is von Neumann, while at cache 1 level there is a Harvard architecture. This means self modifying code will fail to work.
And important part of the ISA is the set of instructions used to handle the available registers and memory. One may think it would be handy with 128 instructions, 16 addressing modes, 256 instructions and 3-op instructions. Summing the necessary bits to express this in one instruction is the sum of log2 of those numbers (with 3x for 3-op design), that is 7 + 4 + 3*8 = 35 bits. In addition to failing to fit into a 32 bit instruction, the useful expressiveness is low compared to the cost of code bloat that eats into memory and all cache levels. Clearly one has to be sober in the design, and also use a few tricks.
8-bit CISC used 8 bit wide instructions with variable number of subsequent bytes for auxiliary code or data. Loading a register with a 16 bit immediate value, would be 1 byte for the instruction plus another two bytes for data. If more than 256 different instructions were needed (and were often desired), one could use prefix codes to indicate the next byte was an instruction in a different opcode map and/or access to more registers as in 6309. Both 6502 and 1802 lacked prefix codes, otherwise that was very common. This meant variable with instructions with added complexity in the processor instruction decoder. VAX and x86 were both very complex in this regard. 16-bit CISC processors usually had 16 bit base instructions and thus less need for prefix instructions, at the expense of needing more memory for the code.
RISC simplifies this with fixed instruction width where the base instruction bits indicate the class of the instruction such as register-to-register, immediate data, or jump to address; where the meaning of rest of the instruction word depends on the class.
The instruction design is therefore crucial for code density, which varies a lot.
There are several types of instructions:
- Load-store: moving data between register file and memory
- Register-register: calculations, data manipulations and possibly flow control, that involves registers, typically 3 register OPs for RISC, see below for further details.
- Register-memory: calculations, data manipulations and possibly flow control, that involves registers and data in memory without first loading memory data into registers. This is common in CISC and DSPs, see below for further details.
- ALU: arithmetic (add, subtract etc. with or without carry), boolean logic (and, or, xor), bit operations (shift, rotate, left or right, with or without carry)
- Flow control: absolute jump or relative branches, unconditionally or conditionally
Register-register and register-memory can be used in ALU and flow control operations.
CPU that we are all familiar with
DSP are Digital Signal Processors that tend to use Harvard or super Harvard architecture, with separate memory buses for X-, Y-, and program memory. These are optimised for processing long series of numbers, typically sampled signals from an ADC, low power consumption and hard real-time requirements. Typically a DSP is an accumulator based design tightly coupled to the MAC (Multiply and Accumulate) unit, which is the heart of the DSP. In a typical clock tick, the DSP loads a parameter from X-memory and a parameter from the Y-memory, multiplies these and sums this with the accumulator, while incrementing the pointers into X- and Y-memory. Optionally there is also a shift and rounding in every tick. The pointer incrementing typically takes place in the data address generators that serve to feed the MAC at maximum speed. A well known C equivalent is
A += *x++ * *y++
GPU are more recent design where competition drives towards an all out performance design no matter the thermal issues.
Summery of CISC - RISC Differences
(work in progress...)
|Registers||Few general purpose registers, 1 - 16||Many general purpose registers, 16 - 128||Many registers makes it easier for compilers, but task switching means moving a lot of registers around, increasing latency.|
|Register Use and Types||Often many separate types of registers (data, address, counters, stack...)||Nearly all registers are in a general purpose register file and can do data and address functions. Register r0 is normally hardwired to zero.||RISC style registers mean the register width also has to be the same width as the address bus. A hardwired zero register consumes opcode space but is less onerous for large register files.|
|Operands||1-op and 2-op are normal for CISC, a result of limited memory sizes at that time.||3-op instructions are normal, and 2-op instructions such as
||RISC instructions are easy to decode but at the cost of code density.|
|Addressing Modes||Many, often more than 10 differnt nodes, including directly processing on memory||Load and store only. All processing is on register to register only. Some allow for automatic pointer incrementing, but the most orthodox ISAs such as RISC-V does not have this.||This is one of the differences that makes RISC more verbose and possibly slower. RISC-V proponents allege that uOPS fusion saves their day.|
The microarchitecture (μArchitecture) is what implements the ISA. Typically instructions are decoded and executed using state machines running microcode (μCode). Some allege that microcode is RISC but that is a misnomer; RISC and CISC are types of ISA and visible to the programmer - what is inside the μArchitecture is normally not visible to programmers. Processors are often upgraded and much involves changing the μCode, including adding new instructions.
One notable exception is the Gigatron where the μCode is accessible to everyone.
CPUs nowadays use instruction pipelining. Instructions cannot be performed in just one clock cycle. Without pipelining, a particular instruction will hog the entire CPU for many cycles. However, instructions need not use every single part of the CPU at the same time (they don't need to fetch something from memory and use the ALU and access the register file etc. all in the same clock cycle). To that end, we split up the CPU into stages. Imagine you were doing laundry, and you had a washer and a dryer, and multiple loads of laundry to wash. You could put the first load into the washer, wait until it's done washing, then put that load into the dryer, wait until it's done drying, and then after the first load is completely finished, start washing the second load. But when the first load is drying, no one is using the washer. So why not put the second load into the washer while the first is drying? That's the basic idea behind pipelining. We have multiple stages, and keep pushing instructions through the pipeline so we're always making full use of the CPU. This way your instruction throughput is 1 instruction per cycle - every cycle, you complete 1 instruction (though is isn't true for the first few instructions - no instructions get completed until the very first instruction gets to the final stage). You can imagine this will cause some problems depending on how you divide the pipeline. Say we divide our pipeline to have an instruction fetching stage, an instruction decoding/register reading stage, an execution/ALU stage, a memory read/write stage, and a register writing stage. What if we have an instruction that writes a value to a register, and an instruction right after that that reads that register to do some other computation? Take this example:
ADD R1, R2, R2 //r1 = r2+r2
ADD R3, R1, R1 //r3 = r1 + r1
The second instruction will be in the register reading stage while the first instruction will only be in the execution stage. So, we'll read in the old value of R1 in the second instruction and get incorrect behavior. The class of problems that arise from pipelining are called pipeline hazards. To fix this, we can add a metadata bit to the register file that indicates whether the current value of the register is stale or not. Then, we can just completely stall the pipeline - stop the instruction that's reading a stale value from proceeding to the next stage and stop all previous instructions from doing so as well. So, in the previous example, we would have the second instruction and all subsequent instructions stop and wait until the first instruction progresses to and finishes the register writing stage. Doing this is pretty expensive performance-wise; we're making all instructions wait and do nothing until that first instruction finishes. A better way we might be able to use is register forwarding, where we implement a way for an earlier stage to read the result of a future stage. In the previous example, the execution stage is where the value of R1 is calculated. So, we can add a connection between the result of the execution stage to the register reading stage. This way, if the register reading stage sees that a register is currently stale, it can try reading the forwarded register from the execution stage instead. So ADD R3, R1, R1 can read R1 not from the register file, but from the result of the execution stage where the result R2+R2 is calculated for the sake of the ADD R1, R2, R2 instruction. This method is preferable, since we don't have to stall the pipeline for as many cycles.
You might wonder how branches are handled with a pipelined architecture. Say you have code like the following:
BLT R0, R1, END
ADD R1, R0, R0
END: ADD R2, R1, R0
The branch instruction will be loaded into the pipeline. Again, let's assume a 5-stage pipeline like so. We'll only find out whether we need to branch to END or not once during the execution stage - the third stage. So when the branch instruction gets to the second stage, what should we load into the first stage? We can only know what instruction comes next once the branch is evaluated. One thing we could do is stall the pipeline - wait until the branch instruction reaches the execution stage. This way, we know what instruction to load in next. But we'd like to avoid stalls wherever possible. So instead, we could just guess. Load in either the second instruction or the third instruction. If we happen to be wrong - that's ok. Before the execution stage, notice that we don't actually write anything to memory or the register file. So, if we find out we guessed the wrong branch when the branch instruction gets to the execution stage, we can clear out all the previous stages - zero out the internal registers, etc, so the instructions become bubbles in the pipeline - NOOPs that don't do anything. Then, in the next clock cycle, we can load in the correct branch.
This is called speculative execution - we're speculating about what branch is going to be taken and starting the execution of the instructions at that branch.
Instead of just randomly guessing or always assuming that branch is taken or not taken, we can use branch prediction. Modern CPUs will use advanced techniques to guess what branches are taken, based on the history of branches taken and other factors. This way, we usually guess correctly, and we don't have to erase instructions we've already started executing. Branch prediction can have real effects even in high level, compiler-optimized code. Take this code, for example.
Weird ISA Types
It is possible to eliminate most of the above, and instead implement a One Instruction Set Computers (OISCs - pronounced "whisks"). Essentially the CPU executes a single instruction (with varying parameters) over and over. One such example is
SUBLEQ (SUbtract and Branch if Less or EQual). A typical example would be
SUBLEQ *a, *b, addr, which executes
*b -= *a; if (*b < 0) goto addr. It can be shown that this ISA is Turing complete. And indeed Geri was so upset with Intel processors that in righteous fury he made a big-endian 64-bit SUBLEQ CPU and also DawnOS running this CPU, and driving the dial way past 11, he also implemented a windowing system with apps.
4 Bit Processors
These arrived in the early 1970's with Intel 4004, but were soon overtaken by 8-bit processors. This format still exists, is used in huge volume markets where cost is extremely sensitive and consequently these chips are remarkably cheap.
The Saturn processor that powered some HP calculators, had a 4-bit external word size, but also a lot of other uncommon widths.
Viktor's amazing 4-bit processor is tiny, yet has a microcode design, implemented using TTL gates.
8 Bit Processors
These usually have 8 bit registers and a 16 bit program counter or instruction pointer (terminologies vary) and can access 64 KB memory. Most are accumulator based which worked well in the 1980's since in this era memory and CPUs were equally slow.
This is a weird and wonderful processor implemented as bit serial architecture, which made it slow. It was popular for machines such as Cosmac ELF. The fabrication made it radiation resistant and it was also popular for satellites, and is still in production. A modern and compact machine is the 1802 Membership Card in the credit card form factor. Later RCA 1805 was introduced, using the single previously undefined opcode 0x68 as a prefix code and added several more new instructions.
CHIP-8 was a popular virtual processor or very low level language, popular on the 1802 platform, and fast enough for making games. It has been extended and ported to many platforms.
The 6502 was introduced in 1975, and has one accumulator (A), two index registers (X and Y), a stack pointer (S) and a processor status (P), all 8 bit wide; plus a 16 bit program counter (PC). It also has a zero page that could be used as address registers. It entered the market at a much lower price than 6800 and quickly won a following. It was used in many popular computers of that era including Apple 2, BBC and Commodore 64. For all the limitations it was powerful enough in the hands of skilled programmers to power the first spreadsheet (VisiCalc) which was also the first killer application, as well as 3D space games with hidden line wireframe graphics such as Elite.
The 6502 still has many loyal fans, hugely active communities and dozens of implementations. Complete development platforms, simulators, debuggers, operating systems, libraries and more are available, most for free. It is still supported commercially by The Western Design Center, founded by the original designer. An estimated 200 million chips are made annually for an installed base estimated at 2 billion. Not bad for a nearly 50 year old design. This time span also means it is proven, and is therefore used in applications such as pacemakers, where lifetime guarantees take on an entirely new meaning. It is also seen in robots and the occasional terminator. The 6502 has an extremely low transistor count which makes it interesting for new opportunities such as a flexible version (details).
The 6502 has two weaknesses. First of all it is awkward for 16 bit pointer handling, which is why The Woz overcame this by making SWEET-16 virtual processor. The second is that the 6502 is not suited for stack intensive languages such as C. This has been overcome by other virtual processors such as the p-code for the UCSD p-System and VTL-2 (source), both of which exist for several ISA. A more recent virtual CPU for the 6502 is AcheronVM, self described as the successor to SWEET-16.
Several OS have been made for 6502, including LUnix (Little Unix), Minikernel, GeckOS/A65, ACE by Craig Bruce (alternative on Github) and many more. GEOS was an add-on OS for C64 that provided windowing system plus many applications such as text processing, spreadsheets and more - all of this complex system fitting in 64 KB RAM. GEOS was not multi tasking, that extension came with Wheels, which also had a web browser, but increasing RAM requirement to a whopping 128 KB.
Recently a 6502 backend for LLVM has been launched.
This was introduced in 1974 and was thus an early design. It has dual accumulators and one 16-bit index register.
This was the peak of 8-bit architectures with dual accumulators (A and B) that could be merged to a 16 bit accumulator (D), and even featured an opcode for multiplication. Hitachi got a license and made the 6309 variant that includes more registers including another set of dual accumulators (E and F) that could be merged to a 16 bit accumulator (W).
Motorola made an extensive monitor for 6809 called Assist09.
This is an offshoot of Intel's 8080 by Zilog and hugely popular in business applications thanks to CP/M. Z-80 was also used in the MSX range of home computers. Zilog played evil games and won evil prizes.
While the chip may be old, people are still making new multi tasking windowing operating systems for it.
Three Sega video game consoles used the Z80: The Sega Master System and Sega Game Gear used it as a CPU, whereas the m68k-based Sega Genesis had an onboard Z80 for backwards compatibility with Master System games, and was often used for audio control.
The Z80 enjoyed widespread use in embedded and handheld applications well into the 21st century. Many of Texas Instruments' once-ubiquitous graphing calculators (specifically the TI-81 through TI-86) were built around the Z80; the TI-84 plus is still in production.
Typical 16-bit architectures support 20- or 24-bit addressing and 16-bit data. Typical clock speeds are in the megahertz to low tens of megahertz range.
Intel x86-16 (8086, 80186, 80286)
16-bit offerings from Intel included the 8086, 80186, and 80286.
WDC 65816 (65C816)
The '816 is essentially a 16-bit 6502 with some additional enhancements, such as a relocatable zero page. This processor was used in the Apple IIgs and the Super Famicom (SNES). Significant compatibility with the 6502; on reset, the processor is in compatibility mode, wherein it behaves substantially like a 65C02. The processor is not pin-compatible with the 6502, however.
Zilog Z8000 (Z8001, Z8002, Z8003, Z8004)
Introduced in 1979. Sixteen 16-bit general purpose registers that can be used in 32-bit or 64-bit combinations. Not compatible with the earlier Z80.
The 16-bit generation had a short reign before being overtaken by 32-bit processors.
Motorola 68k series (68000, 680x0)
Motorola's evolution of the 6800, introduced in 1979. The first generation processors (68000, 68010, 68012) are generally described as being mixed 16-/32-bit CPUs (the 68008 is described as mixed 8-/32-bit). This is due to the width of its data and address ALUs, and internal and external data buses. Later generations are all fully 32-bit.
The first Apple Macintosh computers used the 68000. Apple continued to use m68k CPUs until transitioning to the PowerPC in the mid-1990s. It is said that WDC was designing at 32-bit successor to the 65C816, but Apple chose to go with Motorola chips and the rest is history. The Amiga, Atari ST, and Sega Genesis also used m68k CPUs.
This ISA brought high performance with many registers (8 data registers and 8 address registers) and numerous addressing modes. The complexity might at first glance seem overwhelming, nevertheless it was very popular and performant with assembly programmer.
This was an early 32-bit processor but troubled by bugs. More recently it has been recreated in Verilog with many improvements.
PowerPC (PPC) architecture
PowerPC was conceived in 1991 by a consortium of Apple, IBM, and Motorola (called AIM) and based on IBM's POWER ISA. The two were developed along side one another through the '90s before PowerPC slowly taking over. POWER2 was the last true POWER ISA, with POWER3 being a PowerPC ISA with POWER2 backwards compatibility. POWER4 was merely a PowerPC processor under the old branding. In 2006 PowerPC was renamed to Power ISA with subsequent POWER ISAs being PowerPC implementations under this Power ISA umbrella.
PowerPC-based Apple Macintosh computers—dubbed "Power Macintosh"—entered the market in 1994, and all m68k-based Macintosh computers were discontinued by mid-1996. Apple used PowerPC until transitioning to Intel x86 processors in 2006.
PowerPC was also used in a variety of video game consoles, such as Nintendo's GameCube (180nm Gekko), Wii (Broadway, essentially an overclocked Gekko with a die shrink to 90nm), and Wii U (Espresso, more or less a triple-core Broadway processor running at an even higher clock thanks to a further die shrink to 45nm); and Microsoft's Xbox 360 (Xenon). The 64-bit Cell Broadband Engine (commonly shortened to "Cell" or "cell BE") processor—developed by a consortium of Sony, Toshiba, and IBM—was notably used in the PlayStation 3 console. The Cell BE was a single PowerPC core with two-way SMT paired with eight Synergistic Processing Elements ("SPEs", basically high performance SIMD units). The Xbox 360's Xenon processor is actually a triple-core Cell without the SPEs.
As for the other two companies in the STI consortium, IBM's PowerXCell 8i processors can be found in various blade servers and was also used in the IBM-built Roadrunner supercomputer at Los Alamos National Laboratory, the first LINPACK500 supercomputer to sustain 1PFLOP/s. Toshiba's part in the venture was to have a highly parallel processor to build into their TVs for effects such as handling many picture-in-picture video streams simultaneously and generating 3D video content (to be used with active-shutter 3D glasses) from 2D source material using a technology they called Tri-Vector in TV models such as the Toshiba ZX900 Cell TV.
This is probably the peak of CISC and powered VAX computers, typically running the VMS operating system with a reliability where uptimes was measured in 10+ years. This can be simulated by SimH, see below.
The British military research establishment Royal Signals & Radar Establishment (RSRE) saw the need for reliability, and designed the Viper using mathematical verification, hence the name "Verifiable Integrated Processor for Enhanced Reliability". It has A X Y and PC, all 32 bits, and a 20 bit address range, and thus seems suspiciously like a wide version of 6502. The the great Brisish tradition it was a great idea, a great project and a commercial failure, and duly collapsed before getting far.
Not to be confused with RISC-V, this processor is part of Project Oberon, and documentation as well as source code in Verilog is available at prof Niklaus Wirth's home page.
Very Long Instruction Word (VLIW) processors are much discussed, but successes are far between. Compilers that can fill all slots in the instruction bundles are easily promised but so far not delivered. One example of a spectacular failure is Intel's Itanium. The GCC backend was only capable of filling one of the three slots, resulting in disastrous performance. The Russian Elbrus design is still active, but information is hard to come by. Some documentation can be found in a Platform document and in an architecture document for Linux
Home Made Processors
Making a CPU chip requires a lot of work and infrastructure. Thankfully there are alternatives. The first is to use several chips, and TTL (Transistor-Transistor-Logic) chips were popular, and also used to prototype processors. Later FPGA (Field Programmable Gate Arrays) made things even simpler and faster.
These can be wire wrap monsters but work surprisingly well. A well known example is the Home Brew CPU complete with an adapted C-compiler and a port of Minix. It is accessible from the net. Other home built processors can be found at the Homebuilt CPUs WebRing.
A very recent and interesting case is the Gigatron TTL Computer that has a micro code system that can emulate a 6502 processor and a 16-bit processor, at a speed sufficient for simple games. The Gigatron can be simulated using the Gigatron Simulator running on the Digital an easy-to-use digital logic designer and circuit simulator designed for educational purposes.
There is also the scamp-cpu which has its own ISA implemented with microcode.
PISC (Pathetic Instruction Set Computer) is a 16-bit design for educational and home use.
Not to be confused with pr0n, a softcore is a description (typically in languages such as VHDL or Verilog) that is compiled and then downloaded into a FPGA. In the raw state an FPGA is a large collection of primitive components such as adders, MUX etc. that are connected together by the bitstream from the compiler, and then turns into nearly any kind of digital devices such as a CPU, DSP, GPU, state machine or similar. A large collection of open source designs can be found on Github and OpenCores. These tend to be a lot faster than TTL processors, both in building/programming and in operations.
It should be noted that the FPGA companies also provides softcores, such as
- Picoblaze for the Xilinx range of products,
- Mico8 from the Lattice range,
- Nios for the Altera (acquired by Intel) range
Gartner alleges that Nios is the most widely-used softcore tech in the FPGA industry.
There are also relay computers such as the Single Board Relay Computer "Trainer"
Making your own ISA
This is where things get exciting!
Start simple. Tempting as it may be to make the definitive ISA that once and for all will kick Intel off the market is not a good first project. And face it, if you are here reading this you are fairly new to ISA design. Start simple and get a feel for how it works. Like C or assembly programming, also this is about skill, experience and elegance that only comes from experience. And if you don't want to make it elegant, well, Intel has shown even that can have utility. So start simple, perhaps 8-bit or even 4-bit. Reimplement an existing ISA, the 6502 is very popular in this respect. Some information can be found in the Nand to Tetris courses. Some guidelines have been posted, though some of the points are noted by the author to be controversial.
Going for a TTL design on breadboard or wirewrap, is an exercise in patience. FPGA might be simpler and avoids short circuiting pins, especially if you use development boards with FPGA and some auxiliary parts such as display, switches and LEDs. You may have done software debugging using printf, now you might have to do debugging using a LED...
FPGAs are configured using designs in VHDL or Verilog. More information on that can be found in this thread over in Anycpu.org, including links to books. There is also the Zero to ASIC course that promises you can learn to design your own ASIC and get it fabricated.
Alternative OS for Alternative ISA
Many cross platform operating systems are available. Contiki OS is available for 6502, AVR and more. Microware OS-9 is available for 6809, 68K and more. FUZIX is a UNIX like OS available for many 8-bit processors and 68K. Also see the Writing a Simple Operating System — from Scratch document. There is also CollapseOS with support for many types of small processors. Also see OSDev.
Often it can be impractical to run the actual hardware in order to test old software, such as ordering a large VAX to test VMS. The solution is a simulator, such as SimH, which is capable of simulating a large number of architectures.
Just a list of sites that provide various news on chip and ISA development:
LinuxGizmos provide news on chips and boards, especially single board computers (SBC)
EE Times is also more business oriented with some tech news.
Tux Phones provides news and resources about Linux on phones, tablets and wearables. Some of this relates to Linux on nontraditional platforms
Hackaday has news on many things including ISA, old and home made alike.
See also Tech News Sites.
The following is mostly a list of bookmarks.
Amiga (Motorola 68k)
Atari (Motorola 68k)
Other Motorola 68k Links
Symb-OS is a multitasking windowing OS for Z-80
Raspberry Pi (arm)
Apple Silicon (arm)
DCPU-16 was a virtual processor intended for the game 0x10c.
The p-code machine was a stack based virtual processor used by UCSD Pascal on Apple 2 and other machines.
"Dynamic Branch Prediction with Perceptrons" - Jimenez, 2001
This document is in need of a lot more material. Information and references for
- specific architectures such as
- micro architecture, including
- out of order execution
- uOPS, including fusion
We are also looking for more in depth sources on ISA work and ISA development/news.