6

According to pdp10.nocrew.org, the JSA and JRA instructions were invented for PDP-6 Fortran. It's a strange claim; now I don't know anything about Fortran, but I find it hard to convince myself that some random language could pressure such a CISCy hardware design enough to have a whole other calling convention put in.

It's quite a strange subroutine calling mechanism, as well. The PC is not stored on the stack, like most modern subroutine calling conventions, nor is the PC stored in the first word of the subroutine, like on some other PDP's. Instead, you pick an accumulator (there are 16 to choose from), and it's stored to the address you selected. Then the effective address and the current PC are stored in the accumulator. And then execution continues at the effective address + 1. And then there's JRA to undo this song and dance and resume the callee's execution.

So what is it about Fortran that made them need or want to include this in the PDP-6?

10
  • 1
    It’s not strange at all that you would consider the needs of (any/all) High Level Languages when designing a processor’s instruction set. For example, see related (retrocomputing.stackexchange.com/q/6959/4577) about the x86. Feb 27 at 10:19
  • BTW, quite a few CPU architectures used the register-PC-transfer way to do subroutines, because it's a lot easier to implement than the larger amount of microcode needed to manipulate the stack (if the architecture has a stack in the first place). So in reality, the stack-based approach is CISCy, while the register based approach is RISCy.
    – dirkt
    Feb 27 at 11:18
  • 1
    The JSA may have been inherited from the PDP-1 instruction architecture. It's worth noting that FORTRAN did not support recursive calls, and that earlier computers with FORTRAN did not support stacks. Stack oriented instructions were a novelty with the PDP-6, and maybe the specs for the FORTRAN compiler didn't contemplate using them. Feb 27 at 13:16
  • 1
    I am not sure, but I think the PDP-11 Fortran used the stack for the return address. VAX FORTRAN used the standard calling sequence, which was stack oriented, if I am not mistaken. Feb 27 at 14:19
  • 1
    My guess as to the timeline is that JSA/JRA had already been planned when the request came in to add PUSH/POP/PUSHJ/POPJ to the mix. Probably requested by the would be Lisp implementors. They weren't ready to get rid of JSA/JRA. Feb 28 at 0:51
6

It's not that FORTRAN required those particular instructions, but that they were the sort of instructions that existing FORTRANs tended to use.

At the time, calling conventions were somewhat unsettled, and different machines exhibited a fairly large variety of instructions to implement calls.

The link you gave cites the ostensible reason:

JSA, Jump and Save AC, stores the AC in word addressed by the effective address. Then the left half of the AC is set to the effective address and the right half of AC is set to the return PC. Then the PC is set to one greater than the effective address. The JRA instruction unwinds this call.

The advantage of this call is that a routine may have multiple entry points (which is difficult to do with JSR) and it's easy to find (and later to skip over) arguments that follow the calling instruction (which is possible to do with PUSHJ, but not quite so convenient). Among the disadvantages of this call is that it is non reentrant, and it doesn't save flags.

So, if I've got this right, the subroutine expects a JSA with a specific AC. Once you've entered the subroutine at one of its several entry points, the old AC content is stored at that entry point, and (this is the crucial part) the entry point address and return address both are in the AC.

The return address being in the AC allows return without knowing the particular entry point (which is not possible if the link is stored at the entry point). And (but this is common to the case where the link is saved in the AC) you can retrieve the arguments that are inline after the call, a fairly common parameter-passing mechanism at the time.

The entry point address being in the AC allows two things: (1) automatic restore of the AC on return - not possible with a simple "save link in AC" instruction, (2) you can find the previous content of the AC, though off-hand I can't think of why you'd need that. Possibly for "alternate exits" through labels passed as arguments?

Point (1) could have been done with PUSHJ/POPJ, but stacks were not really in the FORTRAN mindset at the time. From this vantage point, it looks like the PDP-6 designers included one of everything.


Per the PDP-6 handbook, page 36:

There are three reasons for the JSA-JRA pair: to provide for subroutines with multiple entries; to provide an easily-accessible referece for getting data; and to prevent loss of information, making it possible to nest subroutines.

2
  • 3
    Fortran was fairly unique among high level languages in having both multiple entry points to procedures and alternative returns specified by parameters in the procedure call. Multiple entry points allowed coding design using "modules" with shared internal variables (static but local) and multiple functions, long before OOP "re-invented" such concepts. Of course the Fortran version also allowed impenetrable rats-nest logic, but that was one of the dividing lines between Real Programmers and Quiche Eaters :)
    – alephzero
    Feb 27 at 16:18
  • The previous AC content would be needed for passing one of the parameters in the AC. I would guess that it was common based on the loose-ness of calling conventions at the time, maybe in intrinsic functions or with special parameters. Also, to return a value in the AC, you might store it into the "previous contents of the AC", which could correspond the function return value result as a variable that can be written, read, and rewritten in FORTRAN.
    – Erik Eidt
    Feb 27 at 16:31
7

I think you need to keep the context in mind to understand the decision.

The PDP-6 was introduced in 1964.

At the time, the number of high level languages in wide use could be counted on one hand with fingers left over. In fact, they were pretty much: Fortran, COBOL, and Algol.

Just about the only other obvious candidates would have been LISP and CPL. LISP was known, but not widely used. The first paper on CPL was published in 1963, so if they'd read it and seen something really earth-shaking, they could have tried to account for it, but it would probably have been late enough in the design cycle to lead to a likely delay in shipping.

Especially for the scientific/engineering market, Fortran was completely dominant.

As far as why those instructions were needed: Fortran didn't impose any restrictions that made those instructions really necessary. But at the time, all high level languages were viewed with a bit of suspicion. Anything that couldn't compete pretty well with hand-written assembly language was simply not going to sell.

These instructions did enough to support Fortran subroutine calls, while adding about as little overhead (either in terms of circuit complexity or execution speed) as possible. As such, they were cheap both to implement and to use.

2
  • 2
    Not relevant to the question, but the PDP-6 was claimed to be designed with LISP very much in mind - definitely not an afterthought. In particular I'd suppose the halfword instructions to be there for CAR and CDR. There was a strong association between MIT and the DEC of the time; Kotok had been one of McCarthy's students. Feb 27 at 12:47
  • 1
    @another-dave: good point. Feb 27 at 20:57
1

(Just a Remark about the being 'modern' or not)

It's quite a strange subroutine calling mechanism, as well. The PC is not stored on the stack, like most modern subroutine calling conventions, nor is the PC stored in the first word of the subroutine, like on some other PDP's.

Not really, it's a variant of Branch and Link like used not only in very old architectures, including the /360, but as well rather up to date one, like ARM.

The core function is jumping and loading the return address into a register, which makes it reentrant (unlike the linked description says).

Storing that AC before the entry point can be seen as a way to transfer a parameter both ways - if used that way it's no longer reentrant.

1
  • 1
    If you want to use JSA for 'return address in a register' without save/restore of AC, then you'd have to unconventionally use something like JRST (AC) to return. i.e., the old AC is still written to the entry point word, but never restored, which makes it sort-of reentrant. But if that's what you want, use JSP for the call. Feb 27 at 14:30

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.