並列に動作する複数の演算ユニットを持ち、プロセッサ内部は高速にパイプライン 動作する今日の高性能プロセッサでは、
性能が重要ならば、if 文や for 文を多用した「文学的」プログラミングスタイルよりも、 論理・算術演算による「ハードウェア的」プログラミングスタイルの方が適していると言えます。 演算ユニットが複数あるプロセッサでは並列に処理できる箇所を増やすことも大切です。
List1 に示すCプログラムは、タイマー割り込みで呼び出されるキーパッド読み込み関数です。 readkeypad() でデグリッチ処理を行い、keyevent() でキーパッド押し下げイベントの検出と処理を行っています。
List1 [キーパッド読み込み関数]
#define KEYPORT ((int *)0x80000040) static int readkeypad() { static unsigned int shifter[4] = {0,0,0,0}; static unsigned int shiftp = 0; static unsigned int q = 0; volatile register unsigned int *keyport = KEYPORT; shifter[shiftp++] = *keyport; /* JK-FlipFlop */ q = (~q & (shifter[0] & shifter[1] & shifter[2] & shifter[3])) |( q & (shifter[0] | shifter[1] | shifter[2] | shifter[3])); shiftp &= 0x03; /* equivalent to shiftp mod 4 */ return(q); /* returns key state */ } int keyevent() { static unsigned int d = 0; register unsigned int upedge; register unsigned int onevent; register unsigned int pressed; register unsigned int q; q = readkeypad(); onevent = 0; pressed = upedge = q & ~d; while(upedge ^= onevent){ /* Lower bit has higher priority */ onevent = (upedge & (~upedge + 1)); switch(onevent){ /* do key on process here */ default: break; } } return(pressed); /* returns pressed key */ }
readkeypad() の要は、キー入力ポートから読み込んだ各 bit の値が連続して4回 '1' であった場合にセットされ、 同様に連続して '0' であった場合にリセットされる、ある種のデジタルLPF付き JK-Flip-Flop を構成することにより、 条件判断を一切用いていないところです(実際にはコンパイラにより条件分岐が1つ入る可能性があります)。 また、& や | の演算箇所では、変数間に依存関係が無いためにプロセッサによっては並列処理ができるようになっています。
keyevent() の要は、ハードウェアから見ればほとんど起こる事の無いキー押し下げイベントを判断する為に
無駄に全ビットをスキャンすることなく、List2 のように、
List2 [最も下位の '1' の検出]
算術演算を用いて '1' の立っている最も下位のビットを検出している点です。 アセンブリ言語全盛の 1970 年代には、このようなハードウェアを意識したコーディングは当たり前でしたが、 今また、シンプルな命令を大量に処理するのに長けた今日のプロセッサの性能を活かすために、 まるでロジック回路を組むような「ハードウェア的」なプログラミングは如何でしょうか。
onevent = (upedge & (~upedge + 1));