052001 opcode list

先日までの調査は 1 memory access に対し DTAC で CPU を停め PC へデータを送り、応答を出してから DTAC を出していたのですが、 DTAC を無視する memory cycle があることや memory wait がないのに AS の期間が長いという問題に対処出来ませんでした。

調査環境を新しくして、nonwait で計測出来るようにしました。前回の調査では AS の期間が長い待ち時間の記載がないことや単純に書き間違えで数値が異なる場合があります。
nonwait と wait ありで処理時間が若干違うこともある気がしますが、外からの端子からの計測にも限界があるのでどう判断すればいいかわからない状態です。
命令実行途中のメモリアクセスの途中で待ちが発生することが多々あり、リスト上に書かれた値はそれらを加算したものです。細かく分析する目的のために後日実行ログを公開します。ソフトウェアエミュレータなら深く調査せずに ~ と _ を加算してもいいと思います。

リストの見方

  • op: opcode (hex)
  • name: 命令名
  • mode: addressing mode
    • INH: inherent
    • IX8: indexed で ea を算出する
    • IX16: indexed で ea, ea+1 の2つを算出する
    • IM8: imm = [pc+]
    • IM16: imm.hi = [pc+]; imm.lo = [,pc+]
    • R8: if(cond){rel = signed([,pc+]); pc += rel}
    • R16: if(cond){rel.hi = [,pc+]; rel.lo = [,pc+]; pc += rel}
  • ~,_: addressing mode を除く待ちクロック数
    • ~: AS = H の時の待ちクロック数
    • _: AS = L の時の待ちクロック数
  • #: addressing mode を除く追加バイト数
  • <note>: 適用条件や注意
    • ここに条件が有る場合は1つのopcodeに複数の記述が存在する場合もあるので注意
    • illegal: 052001 では不正な命令 (053248 では有効な場合がある)
    • *: 待ちクロック数が特殊で1行で書けない
    • imm[7]: immdiate の bit[7] で変わる
    • c: cc の carry bit で変わる
    • renamed: 調査の結果適切でない名前か単純に長い名前を改名
  • operation: 実行内容 (演算子はC や Verilog や 6809 アセンブラに準拠)

opcode 0x00 から 0x1f

op|name  mode| ~  _   #|<note> operation
--+----------+---------+------------------
00|SRES  INH | 2  0   2|pc=[0xfffe].w
01|SYNC  INH |        0|wait interrupt
02|SNMI  INH | 5  0  14|<illegal> pushs all; pc=[0xfffc].w
03|SFIRQ INH | 5  0   5|<illegal> pushs cc,pc; pc=[0xfff6].w
04|SIRQ  INH | 5  0  14|<illegal> pushs all; pc=[0xfff8].w
05|SYNC  INH |        0|<illegal> wait interrupt
06|SYNC  INH |        0|<illegal> wait interrupt
07|SYNC  INH |        0|<illegal> wait interrupt
08|LEAX  IX16| 3  0   0|x=ea
09|LEAY  IX16| 3  0   0|y=ea
0a|LEAU  IX16| 3  0   0|u=ea
0b|LEAS  IX16| 3  0   0|s=sa
0c|PUSHS IM8 | 5  1  0+|<*> see:push operation
0d|PUSHU IM8 | 5  1  0+|<*> see:push operation
0e|PULLS IM8 | 4  2  0+|<*> see:pull operation
0f|PULLU IM8 | 4  2  0+|<*> see:pull operation
10|LDA   IM8 | 1  0   0|a=imm
11|LDB   IM8 | 1  0   0|b=imm
12|LDA   IX8 | 0  0   1|a=[ea]
13|LDB   IX8 | 0  0   1|b=[ea]
14|ADDA  IM8 | 0  1   0|a+=imm
15|ADDB  IM8 | 0  1   0|b+=imm
16|ADDA  IX8 | 0  0   1|a+=[ea]
17|ADDB  IX8 | 0  0   1|b+=[ea]
18|ADCA  IM8 | 0  1   0|a+=imm+c
19|ADCB  IM8 | 0  1   0|b+=imm+c
1a|ADCA  IX8 | 0  1   1|a+=[ea]+c
1b|ADCB  IX8 | 0  1   1|b+=[ea]+c
1c|SUBA  IM8 | 0  2   0|a-=imm
1d|SUBB  IM8 | 0  2   0|b-=imm
1e|SUBA  IX8 | 0  1   1|a-=[ea]
1f|SUBB  IX8 | 0  1   1|b-=[ea]
  • SNMI, SFIRQ, SIRQ は push される pc が increment されていないので、これを利用して rti をすると再度ソフトウェア割り込みが実行されてしまいます。
  • ここに記載されたソフトウェア割り込みは許可フラグには無関係に実行可能です。
  • lea は ea を直接代入します.
  • adc, sbc は c の有無で処理時間は変わりませんでした。

opcode 0x20 から 0x3f

op|name  mode| ~  _   #|<note> operation
--+----------+---------+------------------
20|SBCA  IM8 | 0  2   0|a-=imm+c
21|SBCB  IM8 | 0  2   0|b-=imm+c
22|SBCA  IX8 | 1  1   1|a-=[ea]+c
23|SBCB  IX8 | 1  1   1|b-=[ea]+c
24|ANDA  IM8 | 1  0   0|a&=imm
25|ANDB  IM8 | 1  0   0|b&=imm
26|ANDA  IX8 | 1  0   1|a&=[ea]
27|ANDB  IX8 | 1  0   1|b&=[ea]
28|BITA  IM8 | 1  0   0|a&imm
29|BITB  IM8 | 1  0   0|b&imm
2a|BITA  IX8 | 1  0   1|a&[ea]
2b|BITB  IX8 | 1  0   1|b&[ea]
2c|EORA  IM8 | 1  0   0|a^=imm
2d|EORB  IM8 | 1  0   0|b^=imm
2e|EORA  IX8 | 1  0   1|a^=[ea]
2f|EORB  IX8 | 1  0   1|b^=[ea]
30|ORA   IM8 | 1  0   0|a|=imm
31|ORB   IM8 | 1  0   0|b|=imm
32|ORA   IX8 | 1  0   1|a|=[ea]
33|ORB   IX8 | 1  0   1|b|=[ea]
34|CMPA  IM8 | 1  1   0|a-imm
35|CMPB  IM8 | 1  1   0|b-imm
36|CMPA  IX8 | 0  1   1|a-[ea]
37|CMPB  IX8 | 0  1   1|b-[ea]
38|LDP   IM8 | 1  0   0|<renamed> p=imm
39|LDP   IX8 | 1  0   1|<renamed> p=[ea]
3a|STA   IX8 | 1  0   1|[ea]=a
3b|STB   IX8 | 1  0   1|[ea]=b
3c|ANDCC IM8 | 1  1   0|cc&=imm
3d|ORCC  IM8 | 1  1   0|cc|=imm
3e|EXG   IM8 | 0  2   0|<imm[7]==0> (temp=src; dest=temp)x2
3e|TFR   IM8 | 0  1   0|<imm[7]==1> dest=src
3f|EXG   IM8 | 0  2   0|<imm[7]==0> (temp=src; dest=temp)x2
3f|TFR   IM8 | 0  1   0|<imm[7]==1> dest=src
  • EXG, TFR については opcode 0x3e, 0x3f に違いはないです。レジスタの扱いについては後日記載します。

opcode 0x40 から 0x5f

op|name  mode| ~  _   #|<note> operation
--+----------+---------+------------------
40|LDD   IM16| 0  0   0|d=imm
41|LDD   IX16| 0  0   2|d=[ea]
42|LDX   IM16| 0  0   0|x=imm
43|LDX   IX16| 0  0   2|x=[ea]
44|LDY   IM16| 0  0   0|y=imm
45|LDY   IX16| 0  0   2|y=[ea]
46|LDU   IM16| 0  0   0|u=imm
47|LDU   IX16| 0  0   2|u=[ea]
48|LDS   IM16| 0  0   0|s=imm, nmienable = 1
49|LDS   IX16| 0  0   2|s=[ea], nmienable = 1
4a|CMPD  IM16| 1  2   0|d-imm
4b|CMPD  IX16| 0  2   2|d-[ea]
4c|CMPX  IM16| 1  1   0|x-imm
4d|CMPX  IX16| 0  1   2|x-[ea]
4e|CMPY  IM16| 0  2   0|y-imm
4f|CMPY  IX16| 0  1   2|y-[ea]
50|CMPU  IM16| 0  2   0|u-imm
51|CMPU  IX16| 0  1   2|u-[ea]
52|CMPS  IM16| 0  2   0|s-imm
53|CMPS  IX16| 0  1   2|s-[ea]
54|ADDD  IM16| 1  2   0|d+=imm
55|ADDD  IX16| 0  2   2|d+=[ea]
56|SUBD  IM16| 1  3   0|d-=imm
57|SUBD  IX16| 0  3   2|d-=[ea]
58|STD   IX16| 1  0   2|[ea]=d
59|STX   IX16| 1  0   2|[ea]=x
5a|STY   IX16| 1  0   2|[ea]=y
5b|STU   IX16| 1  0   2|[ea]=y
5c|STS   IX16| 1  0   2|[ea]=s
5d|SWI   INH | 5  0  14|pushs all; pc=[0xfffa].w
5e|SWI2  INH | 4  0  14|pushs all; pc=[0xfff4].w
5f|SWI3  INH | 4  0  14|pushs all; pc=[0xfff2].w
  • nmienable は NMI 実行許可フラグで HARDWARE RESET で 0 が代入され、それを1にするには LDS 命令の実行が必要です。PULLS, TFR, EXG, LEAS では nmienable を変更出来ません。

opcode 0x60 から 0x7f

op|name  mode| ~  _   #|<note> operation
--+----------+---------+------------------
60|BRA   R8  | 0  0   0|cond:1
61|BHI   R8  | 0  0   0|cond:(Z|C)==0
62|BCC   R8  | 0  0   0|cond:C==0
63|BNE   R8  | 0  0   0|cond:Z==0
64|BVC   R8  | 0  0   0|cond:V==0
65|BPL   R8  | 0  0   0|cond:N==0
66|BGE   R8  | 0  0   0|cond:(N^V)==0
67|BGT   R8  | 0  6   0|cond:Z|(N^V)==0
68|LBRA  R16 | 0  0   0|cond:1
69|LBHI  R16 | 0  0   0|cond:(Z|C)==0
6a|LBCC  R16 | 0  0   0|cond:C==0
6b|LBNE  R16 | 0  0   0|cond:Z==0
6c|LBVC  R16 | 0  0   0|cond:V==0
6d|LBPL  R16 | 0  0   0|cond:N==0
6e|LBGE  R16 | 0  0   0|cond:(N^V)==0
6f|LBGT  R16 | 0  6   0|cond:Z|(N^V)==0
70|BRN   R8  | 0  0   0|cond:0
71|BLS   R8  | 0  0   0|cond:(Z|C)==1
72|BCS   R8  | 0  0   0|cond:C==1
73|BEQ   R8  | 0  0   0|cond:Z==1
74|BVS   R8  | 0  0   0|cond:V==1
75|BMI   R8  | 0  0   0|cond:N==1
76|BLT   R8  | 0  0   0|cond:(N^V)==1
77|BLE   R8  | 0  6   0|cond:Z|(N^V)==1
78|LBRN  R16 | 0  0   0|cond:0
79|LBLS  R16 | 0  6   0|cond:(Z|C)==1
7a|LBCS  R16 | 0  0   0|cond:C==1
7b|LBEQ  R16 | 0  0   0|cond:Z==1
7c|LBVS  R16 | 0  0   0|cond:V==1
7d|LBMI  R16 | 0  0   0|cond:N==1
7e|LBLT  R16 | 0  6   0|cond:(N^V)==1
7f|LBLE  R16 | 0  6   0|cond:Z|(N^V)==1
  • おそらく microcode のバグで一部命令に謎の待ち時間が発生します。

opcode 0x80 から 0x9f

op|name  mode| ~  _   #|<note> operation
--+----------+---------+------------------
80|CLRA  INH | 0  1   0|a=0
81|CLRB  INH | 0  1   0|b=0
82|CLR   IX8 | 1  0   1|[ea]=0
83|COMA  INH | 0  2   0|a=~a
84|COMB  INH | 0  2   0|b=~b
85|COM   IX8 | 0  0   2|temp=[ea];[ea]=~temp
86|NEGA  INH | 1  1   0|a=-a
87|NEGB  INH | 1  1   0|b=-b
88|NEG   IX8 | 0  0   2|temp=[ea];[ea]=-temp
89|INCA  INH | 0  1   0|a+=1
8a|INCB  INH | 0  1   0|b+=1
8b|INC   IX8 | 0  0   2|temp=[ea];[ea]=temp+1
8c|DECA  INH | 0  1   0|a-=1
8d|DECB  INH | 0  1   0|b-=1
8e|DEC   IX8 | 0  0   2|temp=[ea];[ea]=temp-1
8f|RTS   INH | 2  0   2|pc.hi=[,s+]; pc.lo=[,s+]
90|TSTA  INH | 0  1   0|a-a
91|TSTB  INH | 0  1   0|b-b
92|TST   IX8 | 0  0   1|temp=[ea];temp-temp
93|LSRA  INH | 0  3   0|a={1'b0, a[7:1]}
94|LSRB  INH | 0  3   0|b={1'b0, b[7:1]}
95|LSR1  IX8 | 0  1   2|<renamed> temp=[ea];[ea]={1'b0,temp[7:1]}
96|RORA  INH | 0  2   0|a={c, a[7:1]}
97|RORB  INH | 0  2   0|b={c, b[7:1]}
98|ROR1  IX8 | 0  0   2|<renamed> temp=[ea];[ea]={c,temp[7:1]}
99|ASRA  INH | 0  2   0|a={a[7], a[7:1]}
9a|ASRB  INH | 0  2   0|b={b[7], b[7:1]}
9b|ASR1  IX8 | 0  0   2|<renamed> temp=[ea];[ea]={temp[7],temp[7:1]}
9c|ASLA  INH | 0  1   0|a={a[6:0], 1'b0}
9d|ASLB  INH | 0  1   0|b={b[6:0], 1'b0}
9e|ASL1  IX8 | 0  0   2|<renamed> temp=[ea];[ea]={temp[6:0],1'b0}
9f|RTI   INH |11  1  12|<stack cc.E==0> pulls cc; pulls d,dp.hi,x,y,u,pc
9f|RTI   INH | 5  1   3|<stack cc.E==1> pulls cc; rts
  • 053248 では任意回数シフト動作の命令が追加されているので, 各シフト/ローテート命令の indexed は 1 回シフト動作ということで名前の末尾に1をつけました。
  • RTI は FIRQ とそれ以外の割り込み復帰で動作が変わります。

opcode 0xa0 から 0xb8

op|name  mode| ~  _   #|<note> operation
--+----------+---------+------------------
a0|ROLA  INH | 0  1   0|<C==0> asla
a0|ROLA  INH | 0  2   0|<C==1> a={a[6:0],c}
a1|ROLB  INH | 0  1   0|<C==0> aslb
a1|ROLB  INH | 0  2   0|<C==1> b={b[6:0],c}
a2|ROL1  IX8 | 0  0   2|<renamed> temp=[ea];[ea]={temp[6:0],c}
a3|LSRW  IX16| 2  1   4|temp=[ea];[ea]={1'b0,temp[15:1]}
a4|RORW  IX16| 2  0   4|temp=[ea];[ea]={c,temp[15:1]}
a5|ASRW  IX16| 2  0   4|temp=[ea];[ea]={temp[15],temp[15:1]}
a6|ASLW  IX16| 1  0   4|temp=[ea];[ea]={temp[14:0],1'b0}
a7|ROLW  IX16| 0  0   4|temp=[ea];[ea]={temp[14:0],c}
a8|JMP   IX16| 0  1   0|pc=ea
a9|JSR   IX16| 2  0   0|[,-s]=pc.lo; [,-s]=pc.high; pc=ea
aa|BSR   R8  | 0  0   0|[,-s]=pc.lo; [,-s]=pc.high; pc+=signed(r8)
ab|LBSR  R16 | 0  0   0|[,-s]=pc.lo; [,-s]=pc.high; pc+=r16
ac|DBBNE R8  | 0  2   0|<cond==0,renamed> b-=1; bne
ac|DBBNE R8  | 0  4   0|<cond==1,renamed> b-=1; bne
ad|DXBNE R8  | 0  2   0|<cond==0,renamed> x-=1; bne
ad|DXBNE R8  | 0  4   0|<cond==1,renamed> x-=1; bne
ae|NOP   INH | 0  0   0|no operation
af|SYNC  INH |        0|wait interrupt
b0|ABX   INH | 0  2   0|x+={8'h00, b}
b1|DAA   INH |4+  1   0|<*> see:daa operation
b2|SEX   INH | 0  2   0|d=signed(B)
b3|MUL   INH |12  2   0|d=a*b
b4|LMUL  INH |18  3   0|temp=x*y; x=temp[31:16], y=temp[15:0]
b5|DIV   INH |21  2   0|<b==0> x=0xffff, b=0xff
b5|DIV   INH |21  2   0|<b!=0> x=x/b, b=x%b
b6|BMOVE INH | 3  0 U*2|[,x+]=[,y+]; u-=1; bne
b7|MOVE  INH | 2  0   2|[,x+]=[,y+]; u-=1
b8|LDPC  IM16| 0  0   0|<illegal> pc=imm
  • ROLA, ROLB は2通りの動作です。
  • 乗除算は前回と待ち時間が結構違うので別の条件で実行時間が変わるかも知れません。
  • opcode b8 以降は不正な動作をしますので 052001 では illegal です。053248 では命令が追加されています。
  • 6809 にはあって 052001 では見つかっていない命令は LSL と CWAI の2つです。