14

Many mainframe instruction set architectures (ISAs) in the 1960s included an Execute instruction, which would treat data as an instruction.

I haven't found an architecture designed after 1976 which includes such an instruction. The Wikipedia article (which I wrote) speculates that this is because the Execute instruction interferes with various CPU optimizations like pipelining, but provides no source. That predates RISC architectures.

So:

  • Were there any ISA designs after 1976 that included Execute instructions?
  • Is there any published discussion of the design decision to not include them?

The Wikipedia article has many footnotes, but none resolve these questions.

16
  • If a processor has a "load data with post-increment" instruction, the simplest way of handling instruction fetching may be to have an instruction that performs as "load instruction register using PC with post-increment", and making it so that the instruction register has that instruction's bit pattern forced into it after executing each any other instruction. This would avoid the need to have dedicated circuitry to increment the program counter. If one wants to allow an instruction to be fetched while the previous instruction executes, however, one will need dedicated circuitry...
    – supercat
    Aug 17 at 16:52
  • ...to handle the instruction fetching, and supporting an execute instruction would make it necessary to support two entirely different means of loading the instruction register.
    – supercat
    Aug 17 at 16:54
  • 2
    @Raffzahn What are the "very different instructions" you're referring to? Aug 17 at 18:42
  • 1
    @StavrosMacrakis - StackExchange has a bible and we who find discussion useful are but sinners. Aug 19 at 22:30
  • 1
    TMS-9900 came out 1976 and several of its derivative much later. It had the X instruction which would execute the instruction which opcode is in the given register. Not a difficult thing for the CPU as the register were placed in memory. Oct 11 at 7:37
11

The HP-3000 first introduced in 1972 was a 16-bit stack-based architecture that included an XEQ instruction that would treat a word on the stack (between TOS and 7 words below that as selected in the instruction) as a regular instruction and execute it.

This was utilized in some calling conventions where you needed to execute a different version of the EXIT procedure return instruction based on how the function was called. The instruction EXIT n would return and pop n words off the top of the stack in the process, and the programmer would do something like (in SPL):

     TOS := %031400 + N; << Create appropriate EXIT instruction >>
     ASSEMBLE(XEQ 0);    << Return from function >>
8

TL;DR Too complicated for not much benefit.

You ask why not include an execute instruction. The reason is quite simple. Since around the time you observed the absence of this kind of instruction, the CPU's got more and more optimized in their memory access. Code access was separated from data access as the access pattern are quite different.

To execute a data word as an instruction would require to place that datum in front of the decoder requiring complicated bypass networks, busses and buffers, then the instruction must be inserted in the right place but, how many instruction have already entered the pipelines when it executed the EXEC instruction? The CPU would need to cancel all the instructions already partially executed, etc. i.e. something extremely costly. It is simpler to just write new instruction in memory and jumping to that address. It does not require supplemental plumbing besides what is already necessary for cache coherence.

For a TMS-9900 which already has its register in normal memory, it is extremely simple to add the X instruction, which will fetch the instruction contained in the given register (which is a simple memory fetch), for other CPU's it is more involved.

6
  • I'm not sure I understand why it's easier on the TMS-9900, than on, say, the 6502 or the Z80 or whatever. Of course, variable-width instructions also come into play here as well.
    – OmarL
    Oct 13 at 8:50
  • TMS-9900 only has 3 real CPU register. PC (program counter), WP (workspace pointer) and a status register. The WP register is an address in memory where register R0 to R15 are stored. This mean that the instruction X Rn, which executes the instruction in register n, fetches the instruction from memory at the address WP+2*n instead of PC. A Z80 or a 6502 would have to store the content of the register with the instruction somewhere in memory and use a call/jsr/jump instruction. Oct 13 at 14:06
  • The simplicity in the TMS-9900 comes from the reason why it was a dead end. The registers in RAM, which makes it quite slow (see TI-99/4A for example where a simple ADD of 2 registers taking between 14 and 22 cycles). Oct 13 at 14:06
  • Are you saying that an instruction fetch from memory is easier to do for hardware than move from general purpose register to an instruction register?
    – OmarL
    Oct 13 at 14:56
  • On the PDP-10, the registers were part of the address space and were executable. And yet, the XCT instruction was useful. ... .... Also, on the cheapest original models of the PDP-10, the registers were not part of the CPU, but fetched from core every time (!!). Oct 13 at 17:07
7

I haven't found an architecture designed after 1976 which includes such an instruction.

TL;DR: There is no use case for next to all later GP architectures.

The Long Story:

Because next to all general purpose (GP) architectures developed since then followed a rather simplified structure that holds all parameters that can/may be modified in registers (or alike structures) (*1). There is no need to create synthetic (modified) instructions if all parameters of an instruction can be created dynamic anyway.

When it comes to dynamic instruction adjustment, there are usually two main parameters that need to be adjusted: memory addresses and data length (*2).

Let's for example take a look at parameters of instructions of the eventually most widely used architecture with an execute instruction (where use was rather common), the IBM /360:

  • Memory addressing could be easy made dynamic,

    as each and every memory reference was register relative (base register + offset). Using an Offset of Zero essentially meant to use 'modify' an instruction to use that registers content as address.

  • Data length for string operations (character or BCD) on the other hand was fix coded into the second byte of such instructions.

    Changing that - for example to move a variable length input string or pack a variable length number was not possible. Sure, one could have used self modifying code, but while it was clear to everyone that this is a real bad idea (*3), it is as well simply impossible in a read only setup. So code executed from a ROM stack needed a way to vary the length field (*4).

    The EX instruction was created to solve this by alowing to executing an arbitrary instruction from program memory (*5) while at the same time ORing the lower 8 bits of a register with the second byte of the to be executed instruction.

    For example EXINST MVC 0(1,R4),0(r5) executed via EX R3,EXINST would essentially transfer as many bytes as R3 holds from the address pointed to by R5 to the one pointed to by R4.


*1 - In fact, one could even note that most post 1970 ISA are based on instructions so primitive that the only part that may need modification is are addresses which in turn are anyway held in registers, thus disabling all need for synthetic instructions.

*2 - A Third may be some constant (like the character in a CLI), but that's usually a rare case, as any constant can usually be replaced by a memory reference.

*3 - Already in the 1960s and way before any considerations about caching or performance at all. It adds countless pitfalls in usability, especially in stateless and/or multitasking situations, calling for synchronisation and so on.

*4 - No, noone in his right mind wants to write a multi instruction loop to handle strings - even less if the machine is able to do this in a single instruction, letting the microcode perform at maximum speed.

*5 - No not data memory. The Instruction to be executed is not data, but an instruction that has to follow all necessary rules for instructions, like aligned to half word, being in instruction memory, being in an executable section, addressing only reachable memory and so on.

19
  • 1
    What do you mean by GP architectures, and how does that relate?
    – knol
    Aug 17 at 17:53
  • 1
    In your final example of EXINST the amount of data moved would only be the value in the last byte of the register and not 'transfer as many bytes as R3 holds' which would be 32 bits ... just the low order 8 bits.
    – Hogstrom
    Aug 17 at 18:16
  • 1
    On the PDP-10 (which I'm most familiar with), XCT was rarely used to execute dynamically constructed instructions -- which were not necessary, as it had index registers. The most common use was to support what we'd now call virtual methods which were normally very short. Aug 17 at 18:35
  • 2
    For example, the process scheduler in ITS would XCT RR(P), where P is the location of the process information block and RR is the offset of the "runnable" instruction. If the instruction skipped, the process was runnable. So a runnable process would have SKIPA (skip always) in RR(P). A process which was waiting for some counter to go down to zero would have SKIPZ <counter>. A non-runnable process would have a NOP. (How do you enter multi-paragraph comments?) Aug 17 at 18:39
  • 3
    ICL 1900 used OBEY for general parameter access. The subroutine call would be followed by a 1-word instruction for each actual-argument, which left the result in a register agreed by convention. The called routine would OBEY the relevant instruction to load/store the argument. I suppose thunk-style arguments were automatically possible. (Side note: OBEY, while authoritarian, is not as final as EXECUTE). Aug 17 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.