課題5.マイクロプログラムを変更してMICRO-1機械命令の拡張を行う

課題:
文字列の長さを求めるプログラムを題材にして、 マイクロプログラム 'MICROONE' の変更によって機械命令を拡張することを考える。

このプログラムは ラベル DATA から並んだ最大16個のデータを文字列とみなし、 その長さ(終端記号(0x00)までの長さ)を求めている。 もし16個のデータのなかに終端記号がなかった場合には、0xFFとする。 その結果をラベル RESULT の場所に格納している。

このプログラムにおいて、 ループ処理により検索処理を行っている部分を機械命令化することで、 実行サイクル数が少なくすることができると考えられるので、 MICRO-1機械命令マイクロプログラム 'MICROONE' を元にして 検索処理命令を追加する。

追加する命令を機械語プログラムから使用する際には、EX命令を使う。 機械語プログラム中でEX命令を使う場合は、I型命令と同様の表記をする。

EX 1,16(2)     ; (Ra部=2, Rb部=1, ND部=16)
MICRO-1に追加する「文字列の長さを求める命令」は Raで指定したレジスタにデータの先頭アドレス、NDにデータの個数を設定すると、 Raから始まる文字列の長さを求め、得られた値をRbで指定したレジスタに格納する。

「文字列の長さを求める命令」を使った場合の機械語プログラムでは 元のプログラムのループ処理(NULLを検索する処理の部分)を 1つの機械命令(EX命令)に置き換えている。

このプログラムと命令追加の変更を行った 'MICROONE' を組み合わせて実行する。

'MICROONE' 中でEX命令を処理している部分を変更することで、 追加命令「文字列の長さを求める命令」を実現し、 シミュレータ上で実行せよ。

検索対象データの値(ラベル DATA 以降に格納されている値)を変えて、 それぞれについて動作確認を行うこと。

また、課題4と同様に、元のプログラム strlen と実行ステップ数を比較して、考察せよ。

実行ステップ数がどう変わったか? 何故そうなるのか? を必ず説明すること。
(ヒント: 専用命令を使う場合、1つの命令で多くの処理を担うことになるため、 命令サイクルのうちフェッチフェーズの処理回数が減ることになる)

注意1
'MICROONE'を修正するとその実行開始アドレス(デフォルトは101)も変わるため、 機械語プログラムを実行するときに指定する開始アドレスに注意する。 変更後の 'MICROONE' の実行開始アドレスを調べるためには、 'MICROONE.M' の中身を調べてラベル INIT のアドレス値を調べるとよい。
例えば、ラベル INIT のアドレス値が 10B であった場合は、 マイクロプログラムの実行開始アドレスも 10Bにすること。
※マイクロプログラム中の命令を追加あるいは削除した場合、このアドレス値も変化 するため、毎回確認すること。

注意2
マイクロプログラム 'MICROONE' の中では レジスタの6番と7番(R6, R7)はそれぞれ、 サブルーチン呼び出し時の戻り先PC値の保存の際に用いるスタックポインタ、 PUSH/POP命令でレジスタ値の保存の際に用いるスタックポインタ として使われているため、値を勝手に変更すると不具合を生じる場合がある。
またレジスタ0番から3番(R0〜R3)は機械語プログラムでも使用されるため、 これらのレジスタについても値を勝手に変更すると機械語プログラムが 正しく動作しなくなる可能性がある。

もしこれらのレジスタを使いたい場合は、 一旦レジスタの値をメモリ上に保存してから使用すること。 また、レジスタを使い終わったら、 メモリ上に保存しておいた値をレジスタにセットして元の値に戻すこと。

レジスタ4番と5番(R4, R5)については自由に使うことができる。
レジスタ4番(R4)にはフェッチフェーズにおいて 命令レジスタIRのND部の値が格納されているので、 必要に応じてこの値を使用することが出来る。

ヒント
'MICROONE' 内の(ファイルの最後の方にある)ラベル EX0 辺りから EX命令用のマイクロ命令を記述すればよい。
処理の内容としては以下のようなことを記述すればよいと考えられる。
※番号のついた各項目がそれぞれ一つのマイクロ命令に対応していると 考えてよい。

  1. EX0:
      RBにゼロを代入する。
  2.   レジスタ4番(R4=IRのND部が入っている)の値をカウンタCにセットする。
  3.   もしカウンタCが0ならば(データが0個なので)ラベルEX3へ分岐。
      同時にレジスタRAの値をレジスタ5番(R5)にセット
  4. EX1:
      メモリ読み出しサイクル開始
      同時にレジスタ5番の値を+1し、カウンタCの値を1減らす
  5.   カウンタが0ならばラベルEX2へ分岐
      同時にメモリからの読み出しデータをレジスタ4番(R4)にセット
  6.   レジスタ4番の値でフラグを更新する(SET BYを使う)
  7.   ゼロの場合ラベルEX3へ分岐
  8.   RBの値を1だけ増す
  9.   EX1へ分岐
  10. EX2:
      RBに0xFFを代入する
  11. EX3:
      (これで命令の実行が終了)命令サイクルの最初に戻る
※上記とは別のやり方で求めても構わない。

ヒントにおける注意点

文責:大津 (協力:横田)