In order to have a working CPU, you would need the following:
- ALU instructions
- immediate addressing
- indirect addressing
- condition flag manipulation
- branching
- interrupts
- subroutine calls and returns
- ability to have jump tables (make sure there is at least some way of doing this)
Am I missing anything?
for interrupts, you need a stack. For stacks, you want push and pop
not sure inc and dec is part of ALU.
You can probably avoid having a stack by having a call back register, and an interrupt call back register.
I guess you could have a CPU only working with basic MOVE instructions, mapping the ALU in memory. It would only need additional hardware to process conditionals.
This was done on x86, see
here.
Of course there are many considerations on how to design the CPU in order to know which instructions you need (eg. do you need a JMP instruction, or is PC accessible like General Purpose Registers so only MOV is required, see ARM CPUs where you can access PC like any other register if I recall correctly).
that's interesting - having all of the CPU:s registers on the addr space (if not accessed via special instructions). For example, you could modify a singular byte in the PC word/dword/whatever.
There are
"one" instruction set computers, usually with some sort of composite instruction like "subtract X from Y and if the result was negative branch to Z", but in order to be useful they end up giving specific memory locations side-effects, making a
transport-triggered architecture.
I've seen ISAs that only can operate on one bit at a time; those don't really have a full ALU.
MIPS (among others) have a register to hold the return address, but you still need some kind of stack in order to support calling more than one deep.
You don't need immediate addressing, although it does make your code bigger; ARM uses a "constant pool" for anything that doesn't fit into the 8-bit-constant-plus-5-bit-rotate literal format.
PIC provides native read/write access to the lower 8 bits of the program counter; this was intended for computed goto but the ability to say "just add N to the current value" is sometimes useful. The upper bits aren't directly exposed, though. (And the original 8086 had the basically useless
POP CS instruction)
The Super FX doesn't have a stack (RAM access is far too slow, and including a stack on-die would have been expensive). It has instead an instruction called LINK, which adds a 4-bit number to the program counter and stores it in R11.
This chip also puts the [bottom two bytes of the] program counter in R15, and you can do stuff to it like normal (though not all instructions work on all registers - they tried to do a RISC chip with single-cycle instructions while directly interfacing to 8-bit SNES-compatible cartridge memory, which kinda forced them to economize wherever possible). This means that the presence of IWT Rn, #xx (load immediate word to register) means there's no reason to have immediate jump instructions; accordingly, the only available versions of JMP and LJMP use the contents of specified registers rather than immediates.
I feel like you have a fully functional CPU if you have the following in it:
1- logical NAND and/or NOR (Sheffer's Stroke!)
2- Load
3- Store
4- Jump if Zero
4- Add (optional for convenience).
Don't quote me but I think that's all it takes to make your CPU an universal Turing machine.
I have been slowly working on a CPU design and the main thing is to be as convenient as possible for the programmer as there's never gonna be any compiler for it. The approach I took is fully orthogonal 32bit design, all instructions are equal and all registers are usable as general purpose ones, no distintction exists between regular and special registers for any of the instructions. In theory such approach takes less hardware due to ability to reuse single data access mechanism universally for everything but it is yet to be seen how that pans out once I start realizing it in an FPGA.
There's no dedicated stack other than for interrupts where there's a dedicated register for returns addressing. Call and return instructions specify where the return address goes/is. Most else is pretty mundane, there's about 40 instructions total, less if some special ones such as caching related things are removed. Instructions are 16 or 32bit depending on if they have one or two operands, with fixed RISC like decoding.
on the mv as only instruction thing. I suppose could work something like this?
overwrite_x_to_y;
mv x y
subtract_x_from_y;
mv 0 to [various flags, unrolled]
mv x to arithmetic register
mv 1 to subtraction flag
mv x to arithmetic register
mv result register to x
?
sounds pretty terrible in practice if it was the *only* instruction

even though you probably can do things a more hardwired cpu can't.
A CPU can be made with only one instruction (one kind is the "TOGA computer", which is mainly just a programmable counter and a gate), although it is generally useful to have more. Many instruction sets do not have status flags, such as MMIX (branch instructions check if a given register is zero, nonzero, positive, negative, even, odd, whatever). (It would also be helpful to specify what ALU instructions.) On some instruction sets (such as VAX), the program counter is just another register; you can do stuff with it like with any other register. Fully orthogonal is good. (I happen to like MMIX.)
Just do whatever RISC-V does...
Minimum Instruction Set Computer, on Wikipedia:
https://en.wikipedia.org/wiki/Minimal_i ... t_computerQuote:
In order to have a working CPU, you would need the following:
- ALU instructions
- immediate addressing
- indirect addressing
- condition flag manipulation
- branching
- interrupts
- subroutine calls and returns
- ability to have jump tables (make sure there is at least some way of doing this)
Am I missing anything?
I've brought a lot of products to market with PIC16 microcontrollers which didn't even have all of the above. Indirect addressing for example is just direct addressing going through the INDF (indirect register file) register which is not a physical register but has a physical address in the RAM space. What it accesses when you read/write/increment/etc. it is determined by what you stored in the FSR (file select register), again with direct addressing. It's a pain. Conditions and branching are only about skipping the next instruction if the condition is true, so if you really want to branch, the next instruction has to be a jump. Someone already mentioned the jump tables part which is really mickey-mouse. There's no direct stack access, including no push and pop (pull) instructions, although that was corrected in later PICs.
The 6502 is twice as efficient.Quote:
that's interesting - having all of the CPU:s registers on the addr space (if not accessed via special instructions).
That's almost what the 6502 has. Bill Mensch calls it "addressable-register architecture," or ARA. In a sense, all of ZP is processor registers.
Quote:
I have been slowly working on a CPU design and the main thing is to be as convenient as possible for the programmer as there's never gonna be any compiler for it.
Not a compiler, but the
Cross-32 assembler (which I use and like) comes ready to assemble for dozens of processors, plus comes with the information you need to write your own tables to make it assemble for a processor of your own design. (It is also available
here.)
zzo38 wrote:
Many instruction sets do not have status flags, such as MMIX (branch instructions check if a given register is zero, nonzero, positive, negative, even, odd, whatever).
Interesting. I guess I'm so used to seeing CPUs with status flags, I thought they were necessary. What if they need to disable interrupts?
On many such architectures, the interrupt control register still exists. It just no longer also contains status flags (NZVC), and mode bits (MXD) are instead part of the instruction. And unprivileged programs aren't allowed to access that register in order to prevent one program from denying other preemptively multitasked programs a chance to run.
I wish there was a 16-bit RISC CPU that competed in price with the 65816. I think a RISC architecture with 8 16-bit registers and both a 16 bit data and address bus would've been pretty close to the 65816 in price. If you think about, the 65816 actually has 15 8-bit registers, just not arranged in the most orthogonal way.
Look into the MSP430.
Admittedly, I don't think it ever saw a version that can operate from external memory, so it's pretty strictly a microcontroller instead of microprocessor.