6

A recent question on the PDP-10 "JUMP versus JUMPA" prompted this question.

For reference, see this page of instructions.

The SKIP instructions all skip based on the content of a specified memory location. The AC field is not used in deciding whether to skip. However, if the AC field is non-zero, then the content of the memory location is stored into the AC.

The AOS, SOS instructions (Add One to memory and Skip, Subtract One from memory and Skip) likewise can load a non-zero AC as a side-effect.

I can't recall if I knew this at the time I was writing MACRO-10; I assume I knew about it since I'd read the manuals :-) but now it seems strange and arbitrary to me.

What was the rationale for this behavior? Are there significant use cases? Is this simply the -10 equivalent of what I'd write on a condition-code machine as "LOAD REGISTER FROM MEMORY; JUMP IF RESULT WAS NEGATIVE" or similar?

  • Grepping some random ITS source files for uses of SKIP that also loads an accumulator, I get thousands of hits. It's a very useful feature. I wrote such an instruction myself the other day. – Lars Brinkhoff Feb 28 at 8:27
4

Some examples.

Compare memory contents against two bounds:

        SKIPG A,FOO      ;FOO GREATER THAN ZERO?
         JRST LOSE
        CAIL A,BAR       ;FOO LESS THAN BAR?
         JRST LOSE

A subroutine can have two entry points loading different values into an accumulator:

ONE:    SKIPA A,[1]
TWO:    MOVE A,[2]
        ;...

Convenient way to load memory contents plus one:

        AOS A,FOO
| improve this answer | |
  • It's possible you need a nop after your aos a,foo example; what if the addition rolls over to zero and the following instruction is skipped. – OmarL Feb 28 at 9:26
  • 1
    Oh wait, that's a skip never instruction! – OmarL Feb 28 at 9:26
  • It's looking like my MACRO-10 skills are totally atrophied. The two answers so far are kinda obvious now it's been pointed out to me. Too long spent waffling around in Java, no doubt. – another-dave Feb 28 at 12:40
  • 1
    Since I can only accept one, I'm going to accept this answer rather than @Wilson's, on the grounds I'm more convinced by the 0 < FOO < BAR test than £sd examples, Though I did appreciate Wilson actually answering the "why" question :-) – another-dave Mar 2 at 13:57
3

There are two reasons to have this group of instructions actually load the value that you're comparing.

The first is that the instruction word has a field that specifies an accumulator anyway, and the instruction set is very orthogonal so it only makes sense that a compare instruction also references an accumulator. The skip instructions compare a value to zero, but, it makes sense to have some additional implicit operation that works with the selected accumulator. Therefore, the skip instruction is better thought of as a load instruction that imposes a condition on the following instruction.

The second reason is If you are going to compare something with a value, then it's likely going to be useful to be able to load that value as well.

For example, It's handy for getting the minimum or maximum of several values, isn't it.

Or, say you're traversing a linked list: you need the pointer to the next node in some register, but you also need to know if that pointer is a valid one. You can now easily make arrange for an instruction to be executed only if the routine has reached the end of the list. Exactly the same thing applies to, say, a null-terminated array such as a C-string.

Or, say you have something like a sum of money (made up of pounds, shillings, pence) saved in separate registers, then you would need to check if pence > 11, because then you need to subtract 12 from this number and increment shillings. Then you need to check if shillings > 19, and if so, subtract 20 from shillings and increment pounds. In a scenario like that, after the comparison, it's very useful to have the actual number of pence or shillings or whatever in the register so you can proceed to do the subtraction and increment.

An example from the ITS source code at src/chprog/ocm.470, line number 1070:

RMPPT2: SKIPLE T1,BOARD+BW(A)
        SKIPLE T1,BOARD-BW(A)

What that's doing is loading BOARD+BW(A) into T1, unless that's a negative number or zero, then it loads BOARD-BW(A) into T1, and if that's also a negative number or zero, then the next instruction is skipped... You can see how this arrangement is useful for selecting one of many values.

| improve this answer | |
  • (Because if you remember, there's 20 pence to a shilling and 12 shillings to a pound. You'd have to be off your face to design a currency that way, but that's how it was when the PDP-10 was big, I think.) – OmarL Feb 28 at 7:20
  • And of course, if you don't want that behaviour, just choose AC0. – OmarL Feb 28 at 7:24
  • 1
    Re: the pound/shillings/pence example -- well, if you're using a primitive computer that doesn't have an instruction for mixed-base conversions :-) See KDF9, FRB and TOB. Specifically, work in pennies and convert to £sd on I/O. Also, since £ is a stylized 'L', the initialism '£sd' might relate to 'off your face'. – another-dave Feb 28 at 12:29
  • 1
    @LarsBrinkhoff I'll be interested to read your question! – OmarL Feb 28 at 13:57
  • 1
    @wilson - your latest edit is an interesting way to look at it; it flips my question of "why does this skip have load as a side-effect' to 'it's a load with a skip as a side-effect". – another-dave Mar 8 at 22:22

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.