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 を除く追加バイト数
  • : 適用条件や注意
    • ここに条件が有る場合は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| ~  _   #| operation
                                                                                  • -
00|SRES INH | 2 0 2|pc=[0xfffe].w 01|SYNC INH | 0|wait interrupt 02|SNMI INH | 5 0 14| pushs all; pc=[0xfffc].w 03|SFIRQ INH | 5 0 5| pushs cc,pc; pc=[0xfff6].w 04|SIRQ INH | 5 0 14| pushs all; pc=[0xfff8].w 05|SYNC INH | 0| wait interrupt 06|SYNC INH | 0| wait interrupt 07|SYNC INH | 0| 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| ~  _   #| 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| p=imm 39|LDP IX8 | 1 0 1| 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| (temp=src; dest=temp)x2 3e|TFR IM8 | 0 1 0| dest=src 3f|EXG IM8 | 0 2 0| (temp=src; dest=temp)x2 3f|TFR IM8 | 0 1 0| dest=src
  • EXG, TFR については opcode 0x3e, 0x3f に違いはないです。レジスタの扱いについては後日記載します。

opcode 0x40 から 0x5f

op|name  mode| ~  _   #| 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| ~  _   #| 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| ~  _   #| 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| 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| 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| 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| temp=[ea];[ea]={temp[6:0],1'b0} 9f|RTI INH |11 1 12| pulls cc; pulls d,dp.hi,x,y,u,pc 9f|RTI INH | 5 1 3| pulls cc; rts
  • 053248 では任意回数シフト動作の命令が追加されているので, 各シフト/ローテート命令の indexed は 1 回シフト動作ということで名前の末尾に1をつけました。
  • RTI は FIRQ とそれ以外の割り込み復帰で動作が変わります。

opcode 0xa0 から 0xb8

op|name  mode| ~  _   #| operation
                                                                                  • -
a0|ROLA INH | 0 1 0| asla a0|ROLA INH | 0 2 0| a={a[6:0],c} a1|ROLB INH | 0 1 0| aslb a1|ROLB INH | 0 2 0| b={b[6:0],c} a2|ROL1 IX8 | 0 0 2| 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| b-=1; bne ac|DBBNE R8 | 0 4 0| b-=1; bne ad|DXBNE R8 | 0 2 0| x-=1; bne ad|DXBNE R8 | 0 4 0| 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| x=0xffff, b=0xff b5|DIV INH |21 2 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| pc=imm
  • ROLA, ROLB は2通りの動作です。
  • 乗除算は前回と待ち時間が結構違うので別の条件で実行時間が変わるかも知れません。
  • opcode b8 以降は不正な動作をしますので 052001 では illegal です。053248 では命令が追加されています。
  • 6809 にはあって 052001 では見つかっていない命令は LSL と CWAI の2つです。