On IBM 709/7090/7094 mainframes, the effective address of an instruction could be modified by the contents of an index register specified in the instruction encoding.

That much is a fairly standard feature, ever since the Manchester Mark 1 invented the 'B line'.

In the majority of computers, the content of the index register is added to the value in the address field of the instruction. However, in the IBM mainframes listed above, the index value was subtracted, rather than added.

What was the rationale for choosing subtraction rather than addition?

The 7090 reference manual on page 10 describes the indexing operation of the CPU as complementing the content of the index register and then adding that to the address field from the instruction, but I don't think that is useful as a rationale: "complement and add" is just a description of how subtraction is done in twos-complement.

  • On the PDP-8, it's cheap (single instruction) to increment a memory location used as index (and test for zero at the same time), but much more expensive to decrement it. That's why it was common to index by storing the two's complement of the size in the index location, and then use the end of the area as a base address. Possibly there's a similar instruction set related reason to do it that way on the IBM 709, but I am not familiar enough with this ISA and programming practices there. – dirkt Dec 8 '19 at 8:31
  • On the PDP-8 incrementation is a deliberate choice. Given a full adder, you do increment by adding 0x001 constant and decrement -- by adding 0xFFF constant. – lvd Dec 8 '19 at 17:11

The earlier 704 also had a decrement part in the instruction, and the 7090 can emulate the 704, so one should look at the smaller instruction set of the 704 for reasons for this design decision.

As the IBM 704 manual states on page 12, there are 5 "Type A" instructions which contain both a a decrement and an address field, namely TIX, TNX, TXH, TXL, TXI (those instructions also exist for the 709 series). The T in those instructions stands for "transfer", but that means "transfer of control" (modern jump/branch instructions), not "transfer of register contents".

In particular, TIX "transfer on index" and TNX "transfer on no index" decrement the index register, compare it with zero (though it's phrased as if the comparison is with the decrement value, but that's an implementation detail), and depending on the result, store the decremented value in the index register and/or take the branch to the new address.

The reason for this is that it's difficult to provide both an increment/decrement value and a limit to compare with in a single instruction (one would need enough bits for both fields).

If the limit is zero, then looping through indexes from the lower index to the upper limit requires a negation somewhere. And that's the reason indexing is done by subtracting the index, and increasing the index is done by decrementing the index register.

There's also an instruction to increment the index register (TXI, transfer with index incremented), but that's an unconditional jump, so for tight loops, the other indexing instructions would be preferred.

As mentioned in the comment above, the PDP computers used a similar technique for indexing, except the two's complement had to be calculated manually, and core locations served as index values.

Here's a typical routine (scalar product) that uses indexing, taken from the Coding for the IBM 704 document, so one can see how it was used:

        LXA COUNT,1       load index register
        FMP VECTB+3,1
        FAD ANSWER
        STO ANSWER
        TIX LOOP,1,1
COUNT   PZE 3             a constant
ANSWER                    originally contains 0
  • 2
    Ah, ok. The crucial step I missed is that (if we want to process a vector in the 'forward' direction) is that decrementing the positive index value which is then subtracted from the vector end address is going to increment the effective address. I'd been thinking in terms of loading the index reg with a negative offset. Thanks. – another-dave Dec 8 '19 at 13:57
  • Even on processors that add an index value, forward processing through a loop can be accommodated by loading the base with the address just past the data to be processed, starting the loop index with the two's complement of the size, and incrementing until the index hits zero. – supercat Sep 9 '20 at 22:18

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.