3 ms·
Some one-instruction machines are surprisingly code-efficient. Consider an instruction with four fields: A B C D. Words and addresses are normal two's-complem
by retrac 4y ago
Some one-instruction machines are surprisingly code-efficient.
Consider an instruction with four fields: A B C D. Words and addresses are normal two's-complement integers. Every cycle, the machine takes the value at address A, subtracts the value at address B, and stores it in address C. If the result of this, as a signed integer, is 0 or negative, it jumps to address D. Otherwise it take the next instruction. Using temporary values in RAM, self-modifying code and some constants, everything can be implemented with this single instruction. And a lot of it surprisingly efficiently. Some assembly-style syntax for such a machine:
A B C D
#0 #0 tmp destination
Jump to destination. 0 - 0 = 0, so jump to D. The # is syntactic sugar for an immediate literal. The value is placed in an address and that address is used. Tmp is a memory address, a temporary scratch value. In my made-up syntax here this is implicit if there's no 4th field given:
// move is simple
src #0 dst
// subtract
srca srcb dst
// negate
#0 src dst
Addition is an exercise left for the reader :) Let's use * as the current address in the program, known at compile/assembly time. We can do a cheap subroutine call:
#0 (*+3) retaddress subroutine
Negative of the return address of the next instruction is in retaddress. Result will always be negative for sensible addresses, so jump to subroutine. To return, just write the negative again back to the D field of an instruction:
#0 retaddress (*+5)
#0 #0 tmp tmp // last field will now have return address, jump
Of course, writing self-modifying code without checking it is guaranteed to not work. I probably got the offsets and stuff wrong. But hopefully it gives the idea. Doing the same with the address fields lets you do arbitrary indirection and address calls and make a stack. Often 2 - 5 instructions. Everything a typical RISC machine can do can be done in 1 - 30 instructions. Except multiply, divide, and bitwise boolean operations on the whole word, because you have test and branch on each bit in an inconvenient way. I'm sure something more efficient is possible, but it's quite an improvement on the classic subleq code density.
One-instruction set computer: https://esolangs.org/wiki/OISC https://esolangs.org/wiki/OISC