Last update $Id$
(c) 2007 BakaOyaji

インストラクション・セット

今日のお題は、「インストラクションセットを眺める」です。
PICmicro Mid-Range MCU Family Reference Manual(文書番号33023A)のSection 29. Instruction Set、Table 29-1: Midrange Instruction Setを見ていきます。思っていたより、キレイではありませんね(笑)。
「BYTE-ORIENTED系の命令とLITERAL系の命令で,bit8-11あたりが共通になっていれば、ALU用の命令デコーダが簡単になるの に…」と一人ごちたりしますが、今回はVerilog-HDLで書くので、実際にはちょっとコーディング量が増えるだけです。
以下、Instruction Setを眺めていて感じたことを、とりとめもなく・・・


CLRF命令とCLRW命令は、ビットで表現すると下記のようになっています。
CLRF 00 0001 1fff ffff
CLRW 00 0001 0xxx xxxx
BYTE-ORIENTED系の命令は、ビット7の0/1で、ディスティネーションを、Wレジスタ/ファイルレジスタのいずれにするかを選択します。それ を考慮すればこの2つは同じニーモニックしてもよいと思うのですが、なぜ独立しているのかしら?


MOVWF命令とNOP命令は、ビットで表現すると下記のようになっています。
MOVWF 00 0000 1fff ffff
NOP 00 0000 0xx0 0000
おそらく、NOPはもともと MOVWFと共通で、ディスティネーションをWレジスタとする、すなわちW → Wとして実装するつもりだったのじゃないだろうか? と想像できます。


引き算命令
SUBWF
 W (or f) <= f - W
SUBLW
 W <= Literal - W
以前、PIC16のアセンブラでプログラムを書いていたとき、なんで、「Wから引く」のではなく、「W引く」になっているのか、頭 きましたが、これには意味があります。-Wですが、これは「2の補数」ですね。2の補数は、ビット反転(1の補数)に1を加えたものになります。2の補数 ができれば、引き算は「2の補数を加算」することで実現できます。ソフトウエアの世界では、「へぇ、それで?」ですが、ハードウェアでは非常に意味があり ます。つまり、「引き算回路」はちょっと工夫すれば「加算回路」と共通化できるのです。このような考え方を「リソース・シェアリング」といいます。
ビット反転は、簡単な回路ですが、さらに「1を加える」も工夫の余地があります。
PIC16系の場合、加算命令(引き算命令も)、はキャリー(または、ボロー)付の演算しかありません。加算では演算は、

 OpLand(8bit) + W(8bit) + Carry(1bit)                                … 式1

となるわけです。PIC16では、ステータス・レジスタのCarryは、加算命令の時は「1」で繰り上がりあり、「0」ではなしと解釈します。引き算の場 合 に、「0」で繰り下がりあり、「1」ではなしと解釈します。つまり、

 OpLand(8bit) + (W(8bit) のビット反転) + Carry(1bit)          … 式2

で引き算は実現できるのです。式1と式2は、2番目のオペランドが異なるだけなので、加算器だけで両方の演算をこなすことができます。ここでの議論をもと に、ブロックダイアグラム(図1)のALUとW Reg付近を拡大し、ALUの中を透かして見たのが、下の図3です。
加減算のリソースシェアリング
図3 加減算のリソースシェア(クリックして拡大)

このあたりをVerilogのソースコードの切れ端で書くとこんな感じになります。

リソースシェアを意識した記 述
リソースシェアされないかも しれない記述

    case ( instruction )
             :
             :
       `ADD, `SUB : begin
          if( instruction == `ADD)
             temp = W_reg ;
          else
             temp = ~W_reg ;
          result = Operand + temp + Carry ;
       end
             :
             :
    endcase

  case ( instruction )
             :
             :
       `ADD : begin
result = Operand + W_reg + Carry end
       `SUB : begin
result = Operand + ~W_reg + Carry
end

             :
             :
    endcase

左の記述では、加算は1ヶ所のみですが、右のような記述では、加算は2ヶ所に書かれています。したがって、加算回路が2つ生成される可能性があります。
一部の商用の論理合成ツールでは、右のような記述からも、加算器を共通にして論理合成を行うことができますが、XilinxのISEではダメでした。

ここでのポイントはもう一つあって、MUX/Bit反転がALUの左側の入力信号に入っているところです。右側に入れれば、W-f または W - Literal の計算ができるのですが、右側の入力は、クリティカルパスの検討 (図2)で、かなり長いパスになっていることがわかっています。そこにさらに 「MUX/Bit反転」を加えては、ますますクリティカルパスが長くなってセンスの悪い設計になってしまうのです。
リソースシェアリングのテクニックは、一般的に回路を小さくする可能性がありますが、動作速度的には不利に働きます。クリティカルパスでないところで使う のが吉ですね。


リターン系の命令は、NOPの命令を削ってというか残った未定義の命令から選んで決めた感じがします。


こうしてみると命令の拡張の余地はあまり無いですね。もともとWレジスタが1つなので、BYTE-ORIENTED系の命令でないとあまり拡張する意味は なさそうです。CLRW命令は、 「MOVLW 0 」で代用(正確にはZフラグの立ち方が違う)を潰して、代わりの命令をつくることはできそうですが、これでは「拡張」にはならないですね。



<<前に戻る   Index へ  次へ>>