When one thinks in terms of using a 12-bit word length, the famous PDP-8 from the legendary Digital Equipment Corporation comes immediately to mind.
Because of how it achieved more with less, though, it inevitably had limitations. And, thus, one might consider how, at the cost of some additional complexity, those limitations might be removed.
On the PDP-8, the DCA (Deposit and Clear Accumulator) instruction was present instead of a store instruction, so that the TAD (Two's Complement Add) instruction could do double duty, avoiding the need for a load instruction.
The first three lines in the illustration above shows a way to obtain more opcodes.
First, there are load and store memory-reference instructions which have both an indirect bit and a page bit:
000IP LDA Load Accumulator 001IP STO Store
Then, the various arithmetic instructions get a page bit, but no indirect bit:
0100P ADD Add 0101P SUB Subtract 0110P MUL Multiply 0111P DIV Divide 1000P AND And 1001P ORA Or Accumulator 1010P XOR Exclusive OR 1011P ISZ Increment and Skip if Zero
thus allowing opcodes for a full complement of instructions.
But this does mean that the opcode for the IOT instruction is still foregone, in order to have two jump instructions, which have an indirect bit, but no page bit:
110I0 JMP Jump 110I1 JMS Jump to Subroutine
Another improvement involves the operate instructions. Instead of having several possible useless combinations from setting the two bits for shifting right and shifting left at the same time, the bit used for switching the interpretation of the bits is used to select the direction instead of shift one or shift two.
Setting bits for shift one and shift two at the same time gives the obvious and useful meaning of shift three.
Having explicit multiply and divide instructions allows the same instruction set to be used if the computer is switched into alternate modes to operate on 24 bit integers, or on floating-point numbers. Of course, some of the operate instructions - and the bitwise logical operations - would not apply to floating-point numbers. One possibility is to use the codes for the elementary transcendental functions.
Another improvement that suggests itself in association with the change to the memory reference instructions is to have the page bit switch between two pages indicated by the contents of two page registers, instead of switching between page zero and the current page. Assuming pages are still within a 4K field, each page register would be five bits in length.
One could use a 12-bit register, with one bit reserved, as follows:
(reserved bit) 5 bits: page if page bit is zero 1 bit: if 1, current page used if page bit is one 5 bits: page if page bit is one (and previous bit is zero)
A bit isn't required to select page zero for when the page bit is zero, since the five bits giving the page can be zero to specify the page.
In the case of the jump instructions, with no page bit, though, they would always use the current page, since their requirements differ from those of instructions that operate on data.
The next question that comes up - aside from the one of which opcode might be used to load the page register - is about how to improve the jump to subroutine instruction. Storing the return address at the effective address, and then continuing excution with the following word, prevents its use for re-entrant code, and mixes data with instructions.
The obvious solution would be to introduce a stack, as most 8-bit microprocessors did.
However, instead of adding a new register, one could add only a single bit of machine state: when branching to a subroutine, initially, the instructions are interpreted in a different fashion.
000 LDA Load Accumulator 001 STO Store 010 LMQ Load Multiplier Quotient 011 SMQ Store Multiplier Quotient 100 LPR Load Page Register 101 SPR Save Page Register 110 INC Increment * 111 SRA Store Return Address
where the instructions marked with an asterisk cause an exit from this alternate mode of interpretation, but the others do not.
Thus, an indirect store return address, following an increment operation on the pointer used, allows a stack to be implemented.
To make the instructions for loading and saving the page register more useful, the load page register instruction moves the former page register contents to a buffer, and the save page register instruction actually saves the contents of that buffer - so that on return, the former value of the page register can be found. Of course, the return address is stored from a buffer in which the program counter contents were placed by the JMS instruction.
This suggests that a modified version of these instructions, ending like this:
110 DEC Decrement * 111 RJP Return Jump
should be offered as a mechanism to return from a subroutine.
In order that subroutines may be called from routines having different values contained in the page register, when the computer is in either of these modes, the page bit, if 1, will select the current page, from which indirect addresses may be used if required. But if it is zero, the appropriate bits from the page register will still be used; this will be useful if those bits do not change, and avoids the overuse of page zero as a limited resource.
So, let's go to the one un-needed opcode, rotate zero left, which remains for the shift instructions, and see how we might use it:
7002 ETS Enter Single (return to normal 12-bit integer operation) 7022 ETD Enter Double (24 bit integer operation) 7042 ETT Enter Triple (36 bit integer operation) 7102 ETF Enter Floating (36 bit) 7122 ETI Enter Intermediate (48 bit) 7142 ETL Enter Long (60 bit) 7162 ETE Enter Extended (72 bit) 7222 EAD Enter Auxilliary Double (24 bit integer operation) 7242 EAT Enter Auxilliary Triple (36 bit integer operation) 7302 EAF Enter Auxilliary Floating (36 bit) 7322 EAI Enter Auxilliary Intermediate (48 bit) 7342 EAL Enter Auxilliary Long (60 bit) 7362 EAE Enter Auxilliary Extended (72 bit) 7003 ESR Enter Subroutine Return 7023 EXM Enter Index Mode 7043 ECM Enter Compatible Mode 7063 ERM Enter Reference Mode
where the Enter Auxilliary instructions shift to an instruction format similar to that of the FPP-12, similarly to the Start instructions in the FPP-12 instruction set, while the plain Enter instructions remain within the normal instruction format.
The FPP-12 used seven from a group of eight memory locations as index registers.
Index mode permits indexing without an index register. A portion of the possible instruction opcodes are interpreted normally. Another portion operate on the effective address of the following instruction instead of on the accumulator, thus achieving the effect of indexing without an index register. This technique was used in one early computer, the Elliott 803, but through the use of an extra bit for each pair of instructions.
The Jump, Jump to Subroutine, and operate instructions are only intelligible if they work normally. But the only really useful modified instructions are Add and perhaps Subtract. The ISZ instruction is associated with looping, and looping is where indexing is most useful, and so replacing it with the modified Add is not really the right way to go.
Upon reflection, it would be useful to allow the alternative of modifying the instruction itself rather than its effective address; in that case, even operate instructions could usefully be modified.
So, leaving the other instructions unmodified, the group of arithmmetic instructions with a page bit but no indirect bit will be changed like this:
0100P AEA Add to Effective Address 0101P SEA Subtract from Effective Address 0110P ADI Add to Instruction 0111P SUI Subtract from Insruction 1000P ANI And to Instruction 1001P ORI Or to Instruction 1010P XOI Exclusive OR to Instruction 1011P ISZ Increment and Skip if Zero (unmodified)
Only when an instruction is modified to perform an action of changing the following instruction is the following instruction then interpreted conventionally after the change; unmodified instructions are interpreted as singletons.
Enter Compatible Mode allows the computer to execute PDP-8 programs. Aside from an IOT instruction for switching to this improved mode, there is one other incompatibility: the floating-point formats accessed by instructions of the FPP-12 type are the modified IEEE-754 formats shown here (72-bit long floating point numbers will be the Extended precision, having a 12-bit exponent and no hidden bit, but the exponent will be offset in the IEEE-754 fashion, so they, also, will not be fully compatible).
Enter Reference Mode leaves the operate instructions in their improved form, but it also brings back the IOT instruction. As well, the operate instructions that skip the next instruction are modified so that they skip the next two locations in memory.
In that mode, memory reference instructions take the form:
thus allowing both the field registers and the page registers to be ignored, while making the whole 32K word virtual address space directly accessible.
Of course, it is envisioned that a chip implementing this instruction set would have more than 32K of on-chip memory, never mind how much RAM it might be connected to.
Hence, presumably the first three bits of a 15-bit address would be used to select the actual prefix to the physical address from a group of registers. Or, to avoid adding too many registers to the architecture, the prefixes could be retrieved from memory locations, as the physical translation of a virtual field value would only need to be refreshed when a program is loaded back into memory: changing it in the middle of execution, since that would produce invalid results, does not need to be supported.