ADSP-2191の面白い特徴のひとつとして、条件実行を挙げることができます。条件実行とは読んでその名のとおり、ある条件が満たされたときだけ実行される命令です。
大抵のプロセッサは条件分岐命令を持っています。たとえば、x86のJEQ、68000のBEQは演算結果が0のときに分岐します。変わったところではマイクロプロセッサではないものの、私のHP製電卓は条件が満たされると次の命令を実行しないという命令を持っています。次の命令を分岐命令にしておくと、反転条件の分岐命令を組めるわけです。
ADSP-2191は条件分岐だけでなく条件演算命令を持っています。たとえば2191の条件分岐は
IF EQ JUMP FOO;
のようになっています。前の演算結果が0であれば分岐する命令です。そして条件演算のほうは
IF EQ AR = AX0 + AY0;
のように条件節の後ろに演算命令を書くことで表記します。ちょっとしたコードでも条件分岐を多用するとすぐにストールまみれになってしまいますが、条件実行をうまく使うとストールを防ぐこともできます。
実行条件の指定は条件コードで行います。条件コードには以下のようなものがあります。
コード | 条件 |
---|---|
EQ | 等しい。あるいは0。 |
NE | 等しくない。あるいは0でない。 |
GE | 大きいか等しい。あるいは正か0。 |
LT | 小さい。あるいは負。 |
GT | 大きい。あるいは正。 |
LE | 小さいか等しい。あるいは負か0. |
AC | 桁上げがおきた。 |
NOT AC | 桁上げがおきなかった。 |
AV | あふれがおきた。 |
NOT AV | あふれがおきなかった。 |
MV | MRレジスタであふれがおきた。 |
NOT MV | MRレジスタであふれがおきなかった。 |
SWCOND | ソフトウェア条件が成立した。 |
NOT SWCOND | ソフトウェア条件が成立しなかった。 |
NOT CE | カウンターが0になっていない。 |
TRUE | 真 |
前半は比較的理解しやすいものですが、後半首をひねるようなものが顔を出します。SWCONDってなんでしょう?これは少ないビットフィールドで多くの条件を指定できるようアーキテクトが用意した機能です。
SWCONDはソフトウェア条件と呼ばれます。あまりいい名前ではありませんが、あえて言えばレジスタ間接条件です。ADSP-2191はCCODEという名前のレジスタを持っており、ここに拡張条件をセットすることができます。プログラマがSWCOND条件を参照した場合、ADSP-2191はCCODEレジスタの拡張条件が成立するかどうかを調べて、成立すればSWCOND評価結果を真、成立しなければ偽とします。
この機能によって命令の条件フィールドが許すより多くの種類の条件を使用することができます。実際には煩雑に現れる条件をここに指定するのはオーバーヘッドが大きすぎますので、やや特殊なものが用意されています。
ADSP-2191はCCODE用の条件として次のようなものを用意しています。
コード | 条件 |
---|---|
cond_PF0 | PF0ピンがHである |
cond_PF1 | PF1ピンがHである |
cond_PF2 | PF2ピンがHである |
cond_PF3 | PF3ピンがHである |
cond_PF4 | PF4ピンがHである |
cond_PF5 | PF5ピンがHである |
cond_PF6 | PF6ピンがHである |
cond_PF7 | PF7ピンがHである |
cond_PF8 | PF8ピンがHである |
cond_PF9 | PF9ピンがHである |
cond_PF10 | PF10ピンがHである |
cond_PF11 | PF11ピンがHである |
cond_PF12 | PF12ピンがHである |
cond_PF13 | PF13ピンがHである |
cond_AS | 飽和が起きた |
cond_SV | SRレジスタであふれがおきた |
組み込み用ということで、プログラマブルファンクションピンを監視する条件が多く用意されています。
SWCONDでPFピンを監視できるのは結構ですが、PFピンはFSPRレジスタで入力極性を切り替えることができます。SWCONDによる監視はこの影響を受けるのでしょうか。HRにはこの記述がないようなので下のようなコードで実験してみたところ、FSPRの値によって条件の真偽が影響を受けました。
SWCONDはFSPRの影響を受けます。
#include "def2191.h" .section/pm program; .global _main; _main: iopg=General_Purpose_IO; ax0=0x01; // PF0 out, others in; io(DIR)=ax0; #if 1 ax0=0x0010; // set PF4 negative logic #else ax0=0x0000; // set PF4 positive logic #endif io(FSPR)=ax0; ax1=1; ccode=cond_PF4; // check PF4 (SW3) looptop: if swcond jump clear; io(FLAGS)=ax1; // set PF0 jump looptop; clear: io(FLAGC)=ax1; // clear PF0 jump looptop;