ステータスレジスタ

ステータスレジスタは、コンピュータのプロセッサなどにおいて、フラグのビットの集まったワードをその内容とするレジスタである。フラグレジスタやフラグバイト、コンディションコードレジスタなどとも呼ばれる。
その仕様は一般に、プロセッサの命令セットと密接に結びついており、命令セットアーキテクチャ（ISA）毎に決まっている。
一般的なステータスレジスタの構成.
一般にステータスレジスタは、そのプロセッサの命令による様々な演算などの結果などに関して「あふれが生じた」であるなどといったような対処が必要な場合がある事象に関する状態(ステータス)を示すフラグと、割込みなどといったシステムを制御する状態を示すフラグとから成る。但し、6502のように演算でなく、レジスタへのロードのみでステータスレジスタが変化するものもある。
演算結果を反映するものは、その後に条件分岐などとして参照される場合が多いが ARM のように全命令に条件フィールドがあり、条件付き実行が可能となっているCPUもある。条件分岐命令と組み合わせるか、条件付き実行命令との組み合わせにするか状況に応じて選択が可能である。割込み禁止などのシステムを制御するフラグへのアクセスはOSなど（のみ）がおこなう「センシティブ命令」であるため、仮想化要件などが重視される近年のプロセッサでは（詳細は「PopekとGoldbergの仮想化要件」を参照のこと）扱いやすさのために同一のレジスタ内に共存させたりすることは避けられる（ないし、仮に実際のハードウェア内では共存していたとしても、システム的にユーザプロセスからは隔離されている）。
組込用や8ビット時代のパソコンのプロセッサなど、あるいはリセット直後で保護モードに入る前のモード等、区別が無い場合もある。
ステータスレジスタの実例.
以下にいくつかのマイクロプロセッサでのステータスレジスタの例を挙げる。ビット位置はそれぞれのアーキテクチャでの慣例を無視し、LSBを0に統一している。「セット」は 1 の書き込み、「クリア」は 0 の書き込みである。説明がないフラグは既出の同じ名前のフラグと同じ働きである。フラグは一般にビット操作で扱う。マスクの記事も参照のこと。
また、命令とフラグの変化の仕方についてについての関係も、命令セットアーキテクチャ（ISA）ごとに異なる。各命令種について、一般に「フラグに影響を残さない命令の種類」「全てのフラグに影響を残す命令の種類」の2種類はほぼ全てのISAにあるが、他に「一部のフラグには影響し、残りのフラグには影響しない」という命令種があるISAも多い（しかし、そのような命令はOoO実行などを妨げるなど「悩みのタネ」になりやすく、Intel ADXのように拡張命令などで、従来の命令と基本的な動作は同じだがフラグへの影響範囲が異なる、といった命令が作られることもある）。
6502.
6502のステータスレジスタのサイズは8ビットであり、フラグバイトと呼ばれた。
Z80.
Z80のステータスレジスタのサイズは8ビットであり、フラグレジスタと呼ばれた。
8086.
8086のステータスレジスタのサイズは16ビットでありフラグレジスタと呼ばれ、Bit 7 ～ Bit 0 は 8080/8085 の持つフラグとビットも内容も全く同じ。Bit 15 ～ Bit 8 は、8086 特有のフラグビットで構成される。
Pentium.
Pentiumのステータスレジスタのサイズは32ビットであり、EFLAGSレジスタと呼ばれた。
68020.
68020のステータスレジスタは16ビットで、上位8ビットをシステムバイト、下位8ビットをユーザバイトまたはコンディション・コード・レジスタ(CCR)と呼ぶ。
R3000.
MIPSアーキテクチャでは、ステータスレジスタが存在しない。
これは、プログラムの流れを制御するにあたっては、分岐命令が条件付となっていて、レジスタ間の大小比較やゼロとの大小比較をした結果で分岐するかしないかを決めるために、ネガティブフラグやゼロフラグに相当するフラグを必要としない。
この設計方針には以下のような思想がある。
また、オーバフローやキャリーに相当する分岐条件はないが、これらは例外トラップを発生させることでオペレーティングシステムに処理を任せている。ただし、ユーザプログラムがオーバーフローの発生時に対応する例外処理をOS側に事前に登録しておかなければならない。そうでなければそれらの例外を発生させたプロセスを停止させることになる。また、OSが介在するため頻繁にオーバフローを起こすと性能低下を招くため、基本的にはそれらの例外が発生しないようにプログラムを組むことになる。
PowerPC.
PowerPCのステータスレジスタは、4ビットのフラグ8組から構成されており、コンディションレジスタ(CR0 - CR7)と呼ばれる。以下の一覧の左側は四則演算などの命令にupdate condition registerの指定（命令の後にピリオドを付ける。例えば符号付き16bit即値加算 addi なら addi. と指定する）でセットされる。
演算命令実行時にCR0 - CR7のどのコンディションレジスタに結果を反映させるか(またはどこにも反映させないか)を指定できる。
また、指定した2つのコンディションレジスタ同士でビット単位の論理演算が可能で、その結果を反映させるコンディションレジスタも自由に指定でき、複数の大小比較と論理演算を事前に行っておき、ひとつの条件分岐で済ませてしまうことができる。
条件分岐時にもどのコンディションレジスタのどの組を参照するかを指定できる。
これにより、フラグ更新を伴う複数の演算を先に実施しておき、後で条件分岐を行うということが可能となる。
Itanium.
Itaniumでは、従来のようなステータスレジスタは存在しない。というのもEPICアーキテクチャによって、複数の命令を同時に並行して実行するため、単一のステータスレジスタでは結果を保持することができないためである。そこで、Itaniumでは64ビット幅で各ビットが汎用のフラグとして使えるプレディケートレジスタを用意している。この使用方法は次のようになる。
このように、プレディケートレジスタを使うと、基本的にひとつのプロシージャ(サブルーチン)内では分岐命令を使わずに済む。
これにより、分岐によるパイプラインの乱れを減らすことになり、高速化に寄与する。C言語の if文の then 部と else部を同時に実行するようなものだが、たとえばelse部が非常に短い場合や存在しない場合、then部を通る場合はよいが、通らない場合には実行しない命令をずっと実行ユニットに送り続けることになるため、分岐したほうが有効な場合もある。
なお、ItaniumのIA-64モードでは前述のとおりだが、IA-32モードでは従来とおりPentium相当のステータスレジスタが存在する。
キャリーとオーバーフロー.
「キャリー」と「オーバーフロー」という用語の使い分けは、必ずしも以下のようでなければならないというわけではないが、以上で示したように、このようにして使い分けられていることが多い。パソコンに多いx86プロセッサでもこのような使い分けである。
キャリー.
キャリー（）は、繰り越す、とか、繰越し、といった意味であり、ここではワード演算において、その端のビットから出てくるキャリービットが、その演算におけるキャリーである。以下例として、ワードを4ビットとして説明する。
4ビットで表せる符号なしの数値は 0 から 15 までである。たとえば、 1001 (9) と 0111 (7) の加算は次のようになる。
 1001
 + 0111
 = 10000
このように桁があふれてしまう。キャリーフラグを持つプロセッサでは、このあふれたビットがキャリーフラグに入る。
そして、加算命令として「加算の際に、キャリーフラグの内容も最下位ビットに加算する」という命令を持っている（唯一の加算命令が、そのような加算を行う、という命令である場合もある）。これを使うことで、複数ワードの加算が簡単にできる。たとえば、00101001 (41) と 00010111 (23) の加算は、次のようである。
 1 <- キャリー
 0010
 + 0001
 = 0100
この結果をつなげると 01000000 (64) となる。
減算の場合は、繰り上がりではなく、桁借り（ボロー）が発生したか否か、となる。ボローが発生した場合はそれを次の減算でさらにボローのぶんを引くことで上の桁の計算に反映していく。アーキテクチャにより、ボローの情報を示すボローフラグがキャリーフラグと別にあるもの、キャリーフラグとボローフラグが兼用で、加算の時にはキャリーフラグがキャリーを示し減算の時にはキャリーフラグがボローを示す、といったものがある。
後者にはさらに、ボローが発生した時にフラグが立つものと、逆のものがある。なぜ逆のものがあるかというと、加算器で2の補数を使って減算を行った場合（加算器#減算器も参照）その加算器のキャリー入出力をそのまま扱うとそうなるためである。逆になっているプロセッサとしては、6502・POWER・ARM・PICなどがある。
逆になっていても、長桁加算が「ADD → ADD with-carry」で行えるのと同様、普通は単に「SUB → SUB with-borrow」で計算すれば辻褄が合うように設計されているのが普通である。
オーバーフロー.
一方オーバフローは「あふれ」という意味である。これは符号付数値の場合に意味を持つ。4ビットで表せる符号付整数は −8 から 7 までである。そこでたとえば 7 に 1 を加算すると次のようになる。
 0111
 + 0001
 = 1000
このようになり、符号付整数として解釈した場合、−8 という答えになる。これはもともと 8 という答えを4ビットの符号付整数では表せないために発生するもので、このようなときにオーバフローフラグがセットされる。これを符号なし整数と解釈すれば桁あふれは起きていないので、この演算ではキャリーフラグはセットされない。
最上位桁への繰り上がり（あるいは、最上位桁からの借り（ボロー））があり、かつ同時に、最上位桁より上の桁への繰り上がり（あるいは、最上位桁より上の桁からの借り）が無い時がオーバフローである（といったようにして、ALU等は設計すればよい）。
なお、プロセッサのビット幅以上の符号付整数の演算は、最上位桁だけ符号付と解釈して、それ以外は符号なしと解釈する、といったようにして扱えばよい。