LRONETWO
LRONETWO is single instruction machine created by SophiaCristina that uses a pretty simple logic to work. I think that it is very unlikely that this machine is remotely useful considering that there is no way to receive an input of its own without modifying it completely to the point of making the code unreadable for the correct operations. It would be interesting if someone could do something useful with this.
Logic
The logic is super simple, you read the program in a ROM and the ROM modifies a memory.
If the ROM bit is '1' it moves the memory pointer to the left, if it is '0', to the right;
If the value in the pointed memory location is '0', it flips and changes one position, and if the value is '1', it flips and changes two positions.
Memory works like a circular buffer, so if the pointer crosses the end or beginning of memory addresses, it will go back to the beginning or end of memory.
Example:
ROM bits:
[0,1,0,1]
Memory:
[0,0,1]
ROM[0] is '0', so it is set to move to the right.
Memory[0] is '0', so it flips and moves one space to the right:
The memory is now:
[1,*0,1]
ROM[1] is '1', so it is set to move left.
Memory[1] is '0', so it flips and moves one space to the left:
The memory is now:
[*1,1,1]
ROM[2] is '0', so it's set to move to the right.
Memory[0] is '1', so it flips and moves two spaces to the right:
The memory is now:
[0,1,*1]
ROM[3] is '1', so it moves to the left.
Memory[2] is '1', so it flips and moves two spaces to the right:
The memory is now:
[*0,1,0]
Machine implementation
This is a machine implementation in C++:
template <const uint64_t MemSize, const uint64_t ROMSize> class LRONETWOMachine { private: uint8_t* MEM = nullptr; uint8_t* ROM = nullptr; uint64_t MEMByte = 0, ROMByte = 0; int8_t MEMBit = 0; uint8_t ROMBit = 0; public: LRONETWOMachine(uint8_t* InsertMem, uint8_t* InsertROM) { MEM = InsertMem; ROM = InsertROM; } ~LRONETWOMachine() {} int Run() { for (uint64_t n = 0; n < ROMSize * 8; ++n) { if (!MEM || !ROM) { return(-1); } if (ROM[ROMByte] & 1 << (7 - ROMBit)) { if (MEM[MEMByte] & 1 << (7 - MEMBit)) { MEM[MEMByte] ^= 1 << (7 - MEMBit); MEMBit -= 2; } else { MEM[MEMByte] ^= 1 << (7 - MEMBit); --MEMBit; } ++ROMBit; } else { if (MEM[MEMByte] & 1 << (7 - MEMBit)) { MEM[MEMByte] ^= 1 << (7 - MEMBit); MEMBit += 2; } else { MEM[MEMByte] ^= 1 << (7 - MEMBit); ++MEMBit; } ++ROMBit; } if (MEMBit > 7) { ++MEMByte; MEMByte %= MemSize; MEMBit %= 8; } else if (MEMBit < 0) { --MEMByte; if (MEMByte >= MemSize) { MEMByte = MemSize - 1; } MEMBit += 8; } if (ROMBit > 7) { ++ROMByte; ROMByte %= ROMSize; ROMBit %= 8; } } ROMByte = 0; ROMBit = 0; MEMByte = 0; MEMBit = 0; return(0); } };
Intuitive explanation
How to issue a "Hello" from the machine:
MEM ROM 10000000 0 * 11000000 1 * 01000000 0 * 01100000 0 * 01110000 1 * 01010000 0 * 01011000 1 * 01001000 0 * 01001100 0 * 01001110 1 * 01001010 0 * 01001011 1 * 01001001 0 00000000 * 10000000 l 01001001 * 01001000 0 = H 10000000 * 11000000 1 * 01000000 0 * 01100000 0 * 01110000 0 * 01111000 1 * 01101000 0 * 01101100 1 * 01100100 0 * 01100110 0 * 01100111 l * 01100101 0 = e 00000000 * 10000000 0 * 11000000 1 * 01000000 0 * 01100000 0 * 01110000 0 * 01111000 1 * 01101000 0 * 01101100 0 * 01101110 0 * 01101111 1 * 01101101 0 00000000 * 10000000 1 01101101 * 01101100 0 = l 10000000 * 11000000 1 * 01000000 0 * 01100000 0 * 01110000 0 * 01111000 1 * 01101000 0 * 01101100 0 * 01101110 0 * 01101111 1 * 01101101 0 00000000 * 10000000 1 01101101 * 01101100 0 = l 10000000 * 11000000 1 * 01000000 0 * 01100000 0 * 01110000 0 * 01111000 1 * 01101000 0 * 01101100 0 * 01101110 0 * 01101111 0 = o 00000000 * ROM: 010010100101010 H 10001010010 e 0100010001010 l 100010001010 l 10001000 o 01001010 01010101 00010100 10010001 00010101 00010001 01010001 000 74 85 20 145 21 17 81 0