old processor architectures [was Re: The Strange Birth and Long Life of Unix - IEEE Spectrum]

D. Hugh Redelmeier hugh-pmF8o41NoarQT0dZR+AlfA at public.gmane.org
Wed Dec 7 04:05:13 UTC 2011


| From: James Knott <james.knott-bJEeYj9oJeDQT0dZR+AlfA at public.gmane.org>

| D. Hugh Redelmeier wrote:
| > | Actually, most CPUs can use memory mapped I/O.
| >
| > Not before the PDP-11.  My recollection is that it wasn't the first,
| > but it made the idea popular.
| 
| Other computers had separate I/O instructions and signals on the bus.

Generally separate busses even.

|  Since
| the PDP-11 didn't have those, it had to use memory mapped I/O.  However, you
| could generally use memory mapped I/O on any CPU.

You are right, but I have a different picture.

Most computers before the PDP-11 had a set of instructions for dealing
with memory and a disjoint set of instructions for dealing with I/O.
Examples include the PDP-7, PDP-8, and Nova.

The PDP-11 elegantly unified those sets and had one bus: the
Unibus(TM).

"Less is more."

There are costs to this design.  The bus has to work for the slowest 
peripheral AND the fastest RAM.  The bus has to support a lot of 
fan-out/fan-in.  The semantics of reading or writing memory is somewhat 
different from the semantics of reading or writing a device register. 
Precious chunks of address space are lost (but a notional instruction bit 
is gained).

On systems with separate I/O an memory busses, I/O device registers
were almost always on the I/O bus.  Some devices could also do DMA
transfers to RAM, but only of buffers, not registers.

| I recall reading up on the PDP-8 instruction set.  IIRC, self modifying code
| was recommended!  This was to get around limitations of the instruction set.

Subroutine call was "JSR dest".  It stored the return address at the
destination word and transferred control to the word after that.
Certainly not re-entrant.

It was easy to modify instructions themselves, but not usually
necessary: every memory reference could be indirect (one level).  I
think that the Nova's rep of pointer had a spare bit that was used to
indicate "one more level of indirection" so I presume that you could
even have an infinite indirect addressing loop within a single
instruction.

I/O instructions didn't have indirection.  So if you wanted the same
code to handle multiple devices, you had to build the instruction
dynamically, probably as self-modifying code (in other words, probably
within the instruction stream).

That's a case where unifying the two address spaces is a win.  Then
the rich addressing facilities would work for selecting I/O registers
too.

The PDP-11 had a stack, recognized in hardware, and certainly in the
description of the hardware.  It was one of the first to have that
(certainly Burroughs machines had stacks about a decade earlier).

The PDP-7, PDP-8, and the Nova did not.  The Nova architecture was
later extended to have a stack (infered from the page you mentioned
<http://users.rcn.com/crfriend/museum/doco/DG/Nova/base-instr.html>).

| The Nova had conditional jump relative instructions.  It also had skip
| instructions, where you could skip over an instructions.

I don't think that the original Nova hardware had conditional relative
jumps.  The assembler might have synthesized one out of two machine
instructions (conditional skip over relative jump).  See again
<http://users.rcn.com/crfriend/museum/doco/DG/Nova/base-instr.html>

| > If so, how could you have a one instruction conditional loop?
| > Perhaps you meant a loop with one instruction in the body.
| 
| It's been *MANY* years since I've look at this, but you could do a "NO I/O"
| instruction, which would test the device status flags and then do a jump -1 on
| a specified status.  The jump -1 would put you back to the instruction again,
| so you'd keep on executing that one instruction until the status bit changed.
| 
| Here's a link to the Nova instruction set.
| http://users.rcn.com/crfriend/museum/doco/DG/Nova/base-instr.html

Yes, that's nice.  It shows the layout of machine language
instructions.


| IIRC, you'd do something like:
| 
| NIO SKPDN <device code>
| JMP .-1
| 
| I guess it was 2 instructions, not one.  With the above, if the "Done" flag
| was set, you'd skip over the next instruction and execute whatever followed.
| If it wasn't set, you'd jump back the NIO instruction and run it again.
| However, IIRC, you could do a JMP .0, which would loop on that single
| instruction.  The "." made it a jump relative instruction.

All non-indexed, non-page-zero jump instructions were relative.
Assembly notation might disguise this.

The "." means current location in DG and DEC assemblers.  Assemblers
generally allow fairly complex assembly-time expressions in operands.

	loop:	jmp loop
and
		jmp .

both would generate the same relative jumps (unless, perhaps, we are
currently on Page 0).

| One interesting feature the Nova had was auto increment and decrement memory
| locations.  If you did an indirect memory access, using the contents of those
| locations as the final address, the contents would increment (or decrement) so
| the next time you did that, you'd go to the next address.

The PDP-8 had a simpler form.  Locations 0010 through 0017 were "auto
indexing": when you indirected through them, they incremented.

The Nova's instruction set was quite a nice upgrade to the PDP-8's:

- 16 bit words instead of 12 bit.  Lots of variables fit in 16 but not
  12.

- 15 bit addresses instead of 12.  Too bad it wasn't 16.  I've
  programmed in assembler on machines that had unbounded indirection
  but it isn't as valuable as an extra address bit :-)

- 4 accumulators instead of 1

- indexed addressing

- JSR stuffs return address into AC3, not first word of subroutine

- ALC instructions are quite a bit richer than PDP-8's equivallent.
  The way of combining a whole bunch of operations into one
  instruction is like the PDP-8's OPR instsrcution, and
  like horizontal microcode.

  I was proud to have coded a word in a PDP-8 program that was
  simultaneously
  	a) an instruction to clear the accumulator
	b) the address to indirect through when exiting
	   the program (i.e. the OS entry point)
	c) a constant for the negate of the length of a buffer
	   for a loop.
  I would not code like that now.  But programs then had to
  fit in less than 4k words of 12 bits.

The PDP-11 was considered way more elegant in its day.  But with RISC
glasses on, the Nova wins in some ways.

The PDP-8 line's instruction set didn't evolve much.  The PDP-11's and
Nova's did.

The PDP-8 CPU was reimplemented in a single chip quite
early and probably could have killed off the 8080 if DEC hadn't been
scared that it would have killed off their mini business
<http://en.wikipedia.org/wiki/Intersil_6100>.

Most 16-bit and 32-bit micros followed the path of the PDP-11 but
"ought" to have been wiped out by the 32-bit and 64-bit RISC machines
which are closer to the Nova.
--
The Toronto Linux Users Group.      Meetings: http://gtalug.org/
TLUG requests: Linux topics, No HTML, wrap text below 80 columns
How to UNSUBSCRIBE: http://gtalug.org/wiki/Mailing_lists





More information about the Legacy mailing list