Saturday, February 23, 2013

8085 instruction set: the octal table

The instruction set of the 8085 microprocessor has an underlying structure that becomes much clearer if expressed in an octal-based table, rather than usual hexadecimal-based table:

 \0_0\0_1\0_2\0_3\0_4\0_5\0_6\0_7\1_0\1_1\1_2\1_3\1_4\1_5\1_6\1_7
\00_NOPLXI B,d16STAX BINX BINR BDCR BMVI B,d8RLCMOV B,BMOV B,CMOV B,DMOV B,EMOV B,HMOV B,LMOV B,MMOV B,A
\01_dsubDAD BLDAX BDCX BINR CDCR CMVI C,d8RRCMOV C,BMOV C,CMOV C,DMOV C,EMOV C,HMOV C,LMOV C,MMOV C,A
\02_arhlLXI D,d16STAX DINX DINR DDCR DMVI D,d8RALMOV D,BMOV D,CMOV D,DMOV D,EMOV D,HMOV D,LMOV D,MMOV D,A
\03_rdelDAD DLDAX DDCX DINR EDCR EMVI E,d8RARMOV E,BMOV E,CMOV E,DMOV E,EMOV E,HMOV E,LMOV E,MMOV E,A
\04_RIMLXI H,d16SHLD a16INX HINR HDCR HMVI H,d8DAAMOV H,BMOV H,CMOV H,DMOV H,EMOV H,HMOV H,LMOV H,MMOV H,A
\05_ldhi r8DAD HLHLD a16DCX HINR LDCR LMVI L,d8CMAMOV L,BMOV L,CMOV L,DMOV L,EMOV L,HMOV L,LMOV L,MMOV L,A
\06_SIMLXI SP,d16STA a16INX SPINR MDCR MMVI M,d8STCMOV M,BMOV M,CMOV M,DMOV M,EMOV M,HMOV M,LHLTMOV M,A
\07_ldsi r8DAD SPLDA a16DCX SPINR ADCR AMVI A,d8CMCMOV A,BMOV A,CMOV A,DMOV A,EMOV A,HMOV A,LMOV A,MMOV A,A
\20_ADD BADD CADD DADD EADD HADD LADD MADD ARNZPOP BJNZ a16JMP a16CNZ a16PUSH BADI d8RST 0
\21_ADC BADC CADC DADC EADC HADC LADC MADC ARZRETJZ a16rstvCZ a16CALL a16ACI d8RST 1
\22_SUB BSUB CSUB DSUB ESUB HSUB LSUB MSUB ARNCPOP DJNC a16OUT d8CNC a16PUSH DSUI d8RST 2
\23_SBB BSBB CSBB DSBB ESBB HSBB LSBB MSBB ARCshlxJC a16IN d8CC a16jnk a16SBI d8RST 3
\24_ANA BANA CANA DANA EANA HANA LANA MANA ARPOPOP HJPO a16XTHLCPO a16PUSH HANI d8RST 4
\25_XRA BXRA CXRA DXRA EXRA HXRA LXRA MXRA ARPEPCHLJPE a16XCHGCPE a16lhlxXRI d8RST 5
\26_ORA BORA CORA DORA EORA HORA LORA MORA ARPPOP PSWJP a16DICP a16PUSH PSWORI d8RST 6
\27_CMP BCMP CCMP DCMP ECMP HCMP LCMP MCMP ARMSPHLJM a16EICM a16jk a16CPI d8RST 7

The large-scale structure of the instruction set is by quadrant (i.e. the top two bits): MOV instructions in the pink quadrant, arithmetic instructions in the cyan quadrant, increment, decrement, rotates in the yellow quadrant, and control flow (jump, call, return, push, pop, rst) in the purple quadrant. It's not totally regular, of course. Some instructions are wedged in where they can fit, for example the spot where memory-to-memory move (MOV M, M) would go is replaced by HLT.

Note how registers are controlled by an octal digit in the sequence B, C, D, E, H, L, M, and A. This is especially notable for the MOV instructions and arithmetic instructions. For instructions acting on register pairs, the structure is similar: BC, BC, DE, DE, HL, HL, SP, SP.

Although octal is unpopular now, early microprocessors were designed with octal in mind, using groups of three bits to select registers and operations. Now hexadecimal is popular, but when the opcodes are displayed in a hex-based table, the underlying structure of the instructions is obscured.

Note that the four blocks have been arranged for ease of display - strictly speaking they should be stacked vertically rather than a 2x2 grid. The table includes undocumented instructions, which are shown in lower case. Mouse over a cell to see the hex value of the instruction. Credits: original data from pastraiser.com 8085 instruction table.

How the 8085 decodes instructions internally

The 8085 uses a set of PLAs to decode and process instructions. In the first step of processing an instruction the instruction decode ROM (details) decodes the instruction into one of 48 different instruction groups. The grid below is colored according to the instruction group (0 through 47).

NOP
LXI B,d16
42
STAX B
40
INX B
36
INR B
38
DCR B
38
MVI B,d8
14
RLC
25
MOV B,B
45
MOV B,C
45
MOV B,D
45
MOV B,E
45
MOV B,H
45
MOV B,L
45
MOV B,M
44
MOV B,A
45
dsub
21
DAD B
20
LDAX B
41
DCX B
37
INR C
38
DCR C
38
MVI C,d8
14
RRC
25
MOV C,B
45
MOV C,C
45
MOV C,D
45
MOV C,E
45
MOV C,H
45
MOV C,L
45
MOV C,M
44
MOV C,A
45
arhl
24
LXI D,d16
42
STAX D
40
INX D
36
INR D
38
DCR D
38
MVI D,d8
14
RAL
25
MOV D,B
45
MOV D,C
45
MOV D,D
45
MOV D,E
45
MOV D,H
45
MOV D,L
45
MOV D,M
44
MOV D,A
45
rdel
22
DAD D
20
LDAX D
41
DCX D
37
INR E
38
DCR E
38
MVI E,d8
14
RAR
25
MOV E,B
45
MOV E,C
45
MOV E,D
45
MOV E,E
45
MOV E,H
45
MOV E,L
45
MOV E,M
44
MOV E,A
45
RIM
3
LXI H,d16
42
SHLD a16
12
INX H
36
INR H
38
DCR H
38
MVI H,d8
14
DAA
6
MOV H,B
45
MOV H,C
45
MOV H,D
45
MOV H,E
45
MOV H,H
45
MOV H,L
45
MOV H,M
44
MOV H,A
45
ldhi r8
23
DAD H
20
LHLD a16
13
DCX H
37
INR L
38
DCR L
38
MVI L,d8
14
CMA
6
MOV L,B
45
MOV L,C
45
MOV L,D
45
MOV L,E
45
MOV L,H
45
MOV L,L
45
MOV L,M
44
MOV L,A
45
SIM
3
LXI SP,d16
42
STA a16
8
INX SP
36
INR M
39
DCR M
39
MVI M,d8
16
STC
6
MOV M,B
43
MOV M,C
43
MOV M,D
43
MOV M,E
43
MOV M,H
43
MOV M,L
43
HLT
47
MOV M,A
43
ldsi r8
23
DAD SP
20
LDA a16
9
DCX SP
37
INR A
38
DCR A
38
MVI A,d8
14
CMC
6
MOV A,B
45
MOV A,C
45
MOV A,D
45
MOV A,E
45
MOV A,H
45
MOV A,L
45
MOV A,M
44
MOV A,A
45
ADD B
1
ADD C
1
ADD D
1
ADD E
1
ADD H
1
ADD L
1
ADD M
4
ADD A
1
RNZ
19
POP B
27
JNZ a16
29
JMP a16
30
CNZ a16
33
PUSH B
26
ADI d8
2
RST 0
5
ADC B
1
ADC C
1
ADC D
1
ADC E
1
ADC H
1
ADC L
1
ADC M
4
ADC A
1
RZ
19
RET
18
JZ a16
29
rstv
7
CZ a16
33
CALL a16
34
ACI d8
2
RST 1
5
SUB B
1
SUB C
1
SUB D
1
SUB E
1
SUB H
1
SUB L
1
SUB M
4
SUB A
1
RNC
19
POP D
27
JNC a16
29
OUT d8
17
CNC a16
33
PUSH D
26
SUI d8
2
RST 2
5
SBB B
1
SBB C
1
SBB D
1
SBB E
1
SBB H
1
SBB L
1
SBB M
4
SBB A
1
RC
19
shlx
10
JC a16
29
IN d8
15
CC a16
33
jnk a16
31
SBI d8
2
RST 3
5
ANA B
1
ANA C
1
ANA D
1
ANA E
1
ANA H
1
ANA L
1
ANA M
4
ANA A
1
RPO
19
POP H
27
JPO a16
29
XTHL
35
CPO a16
33
PUSH H
26
ANI d8
2
RST 4
5
XRA B
1
XRA C
1
XRA D
1
XRA E
1
XRA H
1
XRA L
1
XRA M
4
XRA A
1
RPE
19
PCHL
32
JPE a16
29
XCHG
46
CPE a16
33
lhlx
11
XRI d8
2
RST 5
5
ORA B
1
ORA C
1
ORA D
1
ORA E
1
ORA H
1
ORA L
1
ORA M
4
ORA A
1
RP
19
POP PSW
27
JP a16
29
DI
0
CP a16
33
PUSH PSW
26
ORI d8
2
RST 6
5
CMP B
1
CMP C
1
CMP D
1
CMP E
1
CMP H
1
CMP L
1
CMP M
4
CMP A
1
RM
19
SPHL
28
JM a16
29
EI
0
CM a16
33
jk a16
31
CPI d8
2
RST 7
5
Colors by iWantHue

The internal decoding shown above reveals a few interesting things. The NOP instruction is literally no operation - it doesn't get decoded into any instruction group. The MOV instructions are all decoded together, except for the memory operations. Similarly, the arithmetic instructions are all grouped together, except for the memory instructions. There are other smaller groups (e.g. INR/DCR, conditional jumps, conditional calls, returns), and 21 instructions that are handled uniquely(e.g. CALL, PCHL, XCHG, HALT, and 6 undocumented instructions). Surprisingly, DAA, CMA, STC, and CMC are handled together at this stage, despite having very different actions.

6 comments:

Mr Z said...

First, a typo of sorts: Shouldn't JK in your first table be lower case?

Second: I remember one of my EE profs (Dr. Donald Schertz) pointing out to me the octal nature of the 8085 ISA, and how what would be "MOV M, M" ends up being HLT. We had multiple EE labs at the time that required us to hand-assemble and hex-key code into SDK-85 boards, which is probably why Dr. Schertz was so keenly aware of the ISA's encoding properties.

(Our SDK-85s were fancier than most, with a bank of LEDs and toggles on the left side of the board; but, I digress.)

Anyway, that observation has caused me to look for octalness in other ISAs from the era. Indeed, the CP-1600 ISA is /very/ octal. I don't want to spam your 8085 entry with a dissertation on another processor. If anyone's interested in hearing more about the CP-1600, comment on this entry and it'll email me.

Ken Shirriff said...

Thanks, Mr Z. I've fixed the typo. Please feel free to post a long comment about the CP-1600 (which Wikipedia tells me is the processor in the Intellivision game).

Mr Z said...

Ken,

I'd be happy to. Blogger apparently doesn't like my post too much (it's too long, contains HTML markup it doesn't like), so I've just moved it here: http://spatula-city.org/~im14u2c/intv/comment_for_ken_shirrifs_blog.html

Enjoy!

--Joe

Mr Z said...

I put together a Google Docs spreadsheet with a similar breakdown of CP1600/CP1610 opcodes, with a complete expansion of the opcode space here:

https://docs.google.com/spreadsheet/ccc?key=0Ar_02usomyeqdDlESlZLZ0NKcGhzT0xYdmxYb29BTVE&usp=sharing

Anonymous said...

Sorry if my question is completely irrelevant, but I had to know.
In the Jump Statements of 8085, whenever the condition is satisfied, there are 3 Machine Cycles and 2 Machine Cycles if the condition isn't satisfied. I want to know what are these machine cycles? First one is Opcode Fetch, I'm confused about the rest. Please, do help.

Mr Z said...

@Anonymous: Each M cycle corresponds to a single memory fetch, if I recall correctly. Jumps are 3 bytes. You need all 3 bytes to take the jump, as the second and third bytes are the branch target address.

So then the question is "Why is it 2 M cycles when the jump isn't taken?" I imagine they're getting the first byte of the jump destination in the same M cycle as they're evaluating the jump condition, although I haven't traced through the PLAs to see if that's actually the case.