Page 1 of 1

68K inner workings

Posted: Fri Jan 04, 2019 8:46 pm
by Gigasoft
Hi, I just wanted to share some of my notes I made a while back. This is based on Galibert's schematic, so in these notes the chip is assumed to be oriented such that the A13 pin is on the upper left. A lot of this is probably well known already, but I thought it'd be nice to have it all in one place.

On the left side of the chip we find the registers and their associated data processing circuitry. It is divided into three sections that can be connected together, each containing two separate lanes for transferring data. This means that the chip can execute up to 6 general purpose data transfers per cycle.

In addition to the architecturally visible registers, there are seven general purpose registers for use by the microcode, which I have given the names A through G.
- Register A is a 32-bit register that can be used as a memory address, and can be copied into PC. It can be loaded with the sum of two registers, or one register plus or minus a constant, which can be 4, 2 or the size specified by the current instruction.
- Register B is a 32-bit register that can retrieve the last accessed memory address (LAST).
- Register C is a 16-bit register that can retrieve an ALU result and be written to memory.
- Register D is a 16-bit register that can be loaded from memory.
- Register E is a 16-bit register that can be the second operand of an ALU operation.
- Register F is a 16-bit register that can be loaded with the immediate field of an instruction (IMM), the requested interrupt level (IPL), the status register (SR), the current instruction (IR), the current function code (FC), or an exception vector (Vec). It can also be copied into the status register (SR or CCR).
- Register G is a 16-bit shift register.
- There is also a 32-bit register that holds an immediate value.

From the top, we have:
(High section)
- high D0-D7, A0-A6, USP, SSP, immediate register, memory address register, A, PC.
- high adder
- high B
(Low section)
- low adder
- low A, PC, memory address register
- MOVEM register list (List)
- next bit in register list
- F
- low immediate register, SSP, USP, A6-A0
(Data section)
- low B, D7-D0
- Bit selection register (BIT#)
- Selected bit (BIT)
- D
- Output register
- G, C
- ALU flag output: carry 16, overflow 16, sign, carry 8, overflow 8, carry 4
- ALU
- ALU operands
- E

The vertical section in the center of the chip takes the current instruction as an input, and determines such things as instruction operands and exception vectors. This also extracts fields such as shift counts or the target of a branch instruction. The slightly wider section at the bottom selects which ALU functions to perform. Below this is the ALU control logic, with the CCR at the upper left.

At the bottom of the chip is the instruction decoder, which outputs a 10-bit microcode starting address. The left side determines whether an instruction is word or long sized. Instructions can consist of up to three stages, so above this is another instruction decoder. The left side recognizes invalid instructions, and the right side outputs addresses for the second and third stage of the instruction.

Above the invalid instructions we have the condition code evaluator. This produces two bits that form part of the next microcode address for a branching microcode instruction.

The large ROM on the right side of the chip contains the microcode. It is divided into two sections, each with their own address decoding. The left section produces a 68-bit output which specifies the operations to perform. The right section produces a 17-bit output which contains the next microcode address and a few other control bits. Some addresses may map to the same column in one or both sections, thus allowing operation words to be reused. You'll see some redundant operations throughout the code because of this.

To the right of the microcode, at the very top, is the 8-bit bus state machine. At the bottom is a circuit that determines which exception to raise, and the microcode address to jump to, based on which conditions are present at certain points during execution. At the very bottom right is the logic that handles the bus during 16-bit operation. I haven't deciphered how this one works yet.

On the VPA pin you'll notice a funny little circuit. Somehow, using the VPA pin, perhaps with a voltage outside the normal operational range, you can activate a test mode which outputs the 68-bit operation word on the address pins. Presumably, the instruction is input with the data pins, while selecting one of the three stages with IPL0 and DTACK. BR and BGACK control which branch to take for a branching instruction. IPL1 and IPL2 select which part of the operation word to output.

Let's look at some microcode. In the following, each step will appear on one line, with a list of operations performed during the step.
"x<=y" indicates that the previous value of y is copied into x, with sign extension where appropriate. "x.H" and "x.L" indicate the high or low part of a register. "x:y" indicates the 32-bit value formed by concatenating x with y. "[s:x]" indicates memory location x in address space s, where s is either DATA, PROGRAM or ACK. If an address is suffixed with ".B", it is accessed in byte mode if the current instruction is a byte instruction. Multiple registers may be given as a transfer destination, separated with commas. If an address appears alone, the address is prefetched. Math1, Math2 and Math3 invokes the ALU to perform an operation which differs depending on the instruction. Am/Dm/Rm refer to the register selected by the register field of an instruction, or the immediate register in the case of addq, subq, dbcc, trapcc, scc or an immediate ALU instruction. An/Dn/Rn refer to the register in the EA field, or the immediate register if an immediate or absolute addressing mode is used. Xn refers to the index register of an indexed addressing mode.

Other words that may appear on a line are:
FETCH - load next instruction word from prefetch buffer
PREFETCH[x] - prefetch instruction word from x
UPPER, LOWER - transfer upper or lower byte only
NEXT - get the next register of a MOVEM instruction
INT - load IPL, set S, clear T, no trace
FAULT - set S, clear T, no trace
TRAP - set S, clear T
RESET - assert the reset signal
HALT - assert the halt signal
CHECK - check for exception conditions
NEXTI - check interrupts, trace, illegal instruction etc.
End - end the current instruction
Stage2 - go to stage 2
Stage3 - go to stage 3

I'll start with the code that deals with various exceptional conditons.

Code: Select all

Exceptions:
 (1)  F<=SR A<=PC-2
 (2)  PC<=A C<=A.L FAULT A<=SSP-2
 (3)  C<=F [DATA:A]<=C A<=A-4
 (4)  SSP<=A C<=PC.H [DATA:A]<=C F<=Vec A<=A+2
 (5)  B<=F C<=E [DATA:A]<=C A<=A-4
 (6)  PC<=B D<=[DATA:B] A<=B+2
 (7)  B.H<=D D<=[DATA:A] A<=A+2
 (8)  PREFETCH[PROGRAM:B.H:D] A<=B.H:D+2
 (9) 
 (10)  PC<=A A<=A+2 CHECK [PROGRAM:A]
 (11)  D<=[LAST] PREFETCH[LAST] FETCH F<=IMM
 End
Interrupt:
 (1)  F<=SR A<=PC-2
 (2)  PC<=A E<=F C<=A.L INT
 (3)  F<=IPL A<=SSP-2
 (4)  B<=F C<=E [DATA:A]<=C A<=A-4
 (5)  PREFETCH[ACK:B]
 (6)  CHECK
 (7)  FETCH F<=IMM
 (8)  SSP<=A C<=PC.H [DATA:A]<=C F<=Vec A<=A+2
 (9)  B<=F C<=E [DATA:A]<=C A<=A-4
 (10)  PC<=B D<=[DATA:B] A<=B+2
 (11)  B.H<=D D<=[DATA:A] A<=A+2
 (12)  PREFETCH[PROGRAM:B.H:D] A<=B.H:D+2
 (13) 
 (14)  PC<=A A<=A+2 CHECK [PROGRAM:A]
 (15)  D<=[LAST] PREFETCH[LAST] FETCH F<=IMM
 End
Bus error:
 (1)  B<=LAST F<=SR A<=PC
 (2)  PC<=A C<=A.L FAULT A<=SSP-2
 (3)  C<=F [DATA:A]<=C A<=A-4
 (4)  C<=PC.H [DATA:A]<=C F<=IR A<=A+2
 (5)  C<=F [DATA:A]<=C A<=A-4
 (6)  PC<=B C<=B.L [DATA:A]<=C FETCH F<=FC A<=A-2
 (7)  C<=F [DATA:A]<=C A<=A-4
 (8)  SSP<=A C<=PC.H [DATA:A]<=C F<=Vec A<=A+2
 (9)  B<=F C<=E [DATA:A]<=C A<=A-4
 (10)  PC<=B D<=[DATA:B] A<=B+2
 (11)  B.H<=D D<=[DATA:A] A<=A+2
 (12)  PREFETCH[PROGRAM:B.H:D] A<=B.H:D+2
 (13) 
 (14)  PC<=A A<=A+2 CHECK [PROGRAM:A]
 (15)  D<=[LAST] PREFETCH[LAST] FETCH F<=IMM
 End
Reset:
 (1) 
 (2)  FETCH F<=IMM
 (3)  F<=Vec
 (4)  INT A<=F
 (5)  SSP<=D D<=[PROGRAM:A] A<=A+2
 (6)  SSP<=D D<=[PROGRAM:A] A<=A+2
 (7)  SSP<=D D<=[PROGRAM:A] FAULT A<=A+2
 (8)  B.H<=D D<=[PROGRAM:A] A<=A+2
 (9)  PREFETCH[PROGRAM:B.H:D] A<=B.H:D+2
 (10) 
 (11)  PC<=A A<=A+2 CHECK [PROGRAM:A]
 (12)  D<=[LAST] PREFETCH[LAST] FETCH F<=IMM
 End
Double fault:
 (1)  HALT
 Go to (1)
Reset+fault:
 (1)  HALT
 (2)  F<=SR A<=PC-2
 Go to (1)
As you can see, at the start of an instruction, the PC register points two bytes ahead of the current instruction, and the A register points four bytes ahead. The second word is in the prefetch queue and is also loaded into the D register, and F is loaded with the immediate field of the current instruction, if any. It is noteworthy that the reset routine fetches the initial SSP and PC from program memory rather than data memory like the other vectors. There is also an undocumented behaviour that occurs if a bus error occurs during reset processing, where the HALT signal will continuously toggle on and off.

Here are some examples of actual instructions.

Code: Select all

bclr Dm,Dn and the second phase of bclr #imm,Dn:
 (1)  B<=Rm BIT#<=Rm.L PC<=A A<=Rn CHECK [PROGRAM:A]
 (2)  E<=Rn.L C<=Math1(BIT,Rn.L) D<=[LAST] PREFETCH[LAST] A<=PC+2 NEXTI
 High word:
  (3)  E<=Rn.H C<=Math1(BIT,Rn.H)
  (4)  C<=Math3(BIT,C)
  (5)  Rn.H<=C C<=BIT&E CCR<=Flags.L FETCH F<=IMM
  End
 Low word:
  (6)  C<=Math3(BIT,C)
  (7)  Rn.L<=C C<=BIT&E CCR<=Flags.L FETCH F<=IMM
  End

Same for btst:
 (1)  B<=Rm BIT#<=Rm.L PC<=A A<=Rn CHECK [PROGRAM:A]
 (2)  E<=Rn.L C<=Rn.L D<=[LAST] PREFETCH[LAST] A<=PC+2 NEXTI
 High word:
  (3)  C<=BIT&Rn.H CCR<=Flags.L FETCH F<=IMM
  End
 Low word:
  (4)  Rn.L<=C C<=BIT&E CCR<=Flags.L FETCH F<=IMM
  End

scc Dn:
 (1)  PC<=A C<=0 NEXTI [PROGRAM:A]
 Condition false:
  (2)  Rn.L<=C D<=[LAST] PREFETCH[LAST] FETCH F<=IMM A<=PC+2 W
  End
 Condition true:
  (3)  C<=Math1(-1,C) D<=[LAST] PREFETCH[LAST] A<=B
  (4)  Dn.L<=C FETCH F<=IMM A<=PC+2 W
  End

jsr.l:
 (1)  B.H<=D D<=[PROGRAM:A] A<=A+2
 (2)  B.L<=D PREFETCH[PROGRAM:B.H:D] PC<=A A<=Am-4
 (3)  [DATA:A]<=PC.H Rm<=A A<=A+2
 (4)  [DATA:A]<=PC.L A<=B+2 CHECK
 (5)  PC<=A A<=A+2 CHECK [PROGRAM:A]
 (6)  D<=[LAST] PREFETCH[LAST] FETCH F<=IMM
 End
 
I have made a program which dumps all the instructions, but the output for complex instructions with a lot of branching needs to be polished a bit. More is to come. In the meantime, if someone needs to know how something works, feel free to ask.

Re: 68K inner workings

Posted: Sat Jan 05, 2019 9:09 pm
by Mask of Destiny
Have you had a look at the 68K patents? Looks like you've managed to figure out a lot from the schematic, but the US4325121 patent specifically has a lot of information about how the microcode/nanocode works and includes micro/nanocode listings for a pre-release version of the processor which might be useful for cross-referencing things. Oliver Galibert has also taken his own shot at decoding the micro/nanocode using mnemonics/labels from the patents which you can find here which might also be interesting to compare with.
Gigasoft wrote:
Fri Jan 04, 2019 8:46 pm
- Register A is a 32-bit register that can be used as a memory address, and can be copied into PC. It can be loaded with the sum of two registers, or one register plus or minus a constant, which can be 4, 2 or the size specified by the current instruction.
This sounds a lot like what the patents refer to as the address unit (referred to as au in the listings), or I guess the register that stores the result of address unit additions (listings don't really distinguish between the two).
Gigasoft wrote:
Fri Jan 04, 2019 8:46 pm
- Register B is a 32-bit register that can retrieve the last accessed memory address (LAST).
Based on the micro/nanocode you've listed, this might be what the patents call address temporary (at in the listings)
Gigasoft wrote:
Fri Jan 04, 2019 8:46 pm
- Register C is a 16-bit register that can retrieve an ALU result and be written to memory.
Not sure if this one has a separate name in the patents. In the listings, this is just referred to as if it's part of the ALU. (i.e. in places where you have an ALU op assigned to C, that transfer is implicit in the patent listings and in places that you list it as a source, the listings just use "alu").
Gigasoft wrote:
Fri Jan 04, 2019 8:46 pm
- Register D is a 16-bit register that can be loaded from memory.
This might be what the listings refer to as dbin, but I'm not sure
Gigasoft wrote:
Fri Jan 04, 2019 8:46 pm
- Register E is a 16-bit register that can be the second operand of an ALU operation.
I think this is referred to as alub in the listings.
Gigasoft wrote:
Fri Jan 04, 2019 8:46 pm
- Register G is a 16-bit shift register
I think this might be alue in the patent listings.
Gigasoft wrote:
Fri Jan 04, 2019 8:46 pm
- Bit selection register (BIT#)
- Selected bit (BIT)
I think the listings refer to these as dcr and (dcr) respectively.
Gigasoft wrote:
Fri Jan 04, 2019 8:46 pm
On the VPA pin you'll notice a funny little circuit. Somehow, using the VPA pin, perhaps with a voltage outside the normal operational range, you can activate a test mode which outputs the 68-bit operation word on the address pins. Presumably, the instruction is input with the data pins, while selecting one of the three stages with IPL0 and DTACK. BR and BGACK control which branch to take for a branching instruction. IPL1 and IPL2 select which part of the operation word to output.
According to a book quoted in this thread, the magic voltage is 8 volts. The pins used to control the output were a complete mystery though, so this is a really nice find.

The physical location of the various registers is also a very nice bit of work that I don't think there has been any public info on previously. The presence of result registers for the ALU and AU also explains how the 68K is able to safely read results of a previous operation in the same micro-cycle that it is supplying new parameters which is something I was wondering about.

Thanks for sharing your findings!

Re: 68K inner workings

Posted: Mon Jan 07, 2019 12:26 pm
by ijor
Gigasoft wrote:
Fri Jan 04, 2019 8:46 pm
Hi, I just wanted to share some of my notes I made a while back. This is based on Galibert's schematic, so in these notes the chip is assumed to be oriented such that the A13 pin is on the upper left. A lot of this is probably well known already, but I thought it'd be nice to have it all in one place.
Nice work. You definitely need to check the patents and the book already mentioned above :
https://www.amazon.com/Microarchitectur ... 940108775X

Note that as we discussed somewhere else, there seems to be at least one "trap" (copy protection) on the circuit and it's located at the bus arbitration state machine PLA.

Also check my signature if you are familiar with Verilog.

Re: 68K inner workings

Posted: Tue Jan 08, 2019 4:53 pm
by ijor
Mask of Destiny wrote:
Sat Jan 05, 2019 9:09 pm
The physical location of the various registers is also a very nice bit of work that I don't think there has been any public info on previously. The presence of result registers for the ALU and AU also explains how the 68K is able to safely read results of a previous operation in the same micro-cycle that it is supplying new parameters which is something I was wondering about.
The physical location of the registers in the execution unit is described in the "Microarchitecture of VLSI computers" book mentioned above. I'm not sure, but I think Olivier also has this already labeled at the schematics in his tools.

Not sure how you thought ALU and AU could not be registered. If they were just combinatorial logic without storage, then they couldn't be used a transfer destination. If what you meant is that there are two separated sets of registers, AU result register in addition of AU register, then not, there is only one set of registers. The rest is just combinatorial logic.