数学・情報理論

2015/02/24

位相空間について

位相空間の定義(公理)について最初は全然理解できなかったのですが、ちょっと分かった気になってきました。

一般的な位相空間の定義は、以下のようなものです。(同値な定義はいろいろとできますが、下記の開集合を基にした定義が一般的と思います)

-----------------------------------------------------
集合 X の部分集合からなる族 τ で、以下の条件(公理)

1) 空集合 φ および全体集合 X は τ に属す
φ∈τ, X∈τ
2) τ に属する集合の有限個の共通集合はふたたび τ に属す
∀A,B∈τ ⇒ A∩B∈τ
3) τ に属する集合の任意個(無限濃度をも許す)の合併は τ に属す
∀A_λ∈τ ⇒ ∪A_λ∈τ (λ∈Λ(任意の添え字集合ラムダ))

を満足するものが与えられるとき、集合 X に τ の元を開集合とする位相が定まるといい、組 (X,τ) を X を台集合とし τ を開集合系とする位相空間と呼ぶ。

-----------------------------------------------------
Wikipediaの定義の項をもとに編集しました。
なお、τ(タウ)は位相(Topology)の頭文字Tに対応するギリシャ文字です。


いきなりこんな定義を書かれてもなんのことか分かりません。

また、Wikipediaには以下のような記述もあります。

-----------------------------------------------------
数学における位相空間(いそうくうかん、topological space)とは、集合に要素どうしの近さや繋がり方に関する情報(位相、topology)を付け加えたものである。この情報は関数の連続性や点列の収束といった概念の源といえる。

ユークリッド空間やその部分集合においては、点の間の距離をもちいて異なる点の間の近さを測ることができ、それに基づいた位相空間の構造が得られる。一般に、距離空間は最も想像しやすい種類の位相空間の例を与えているが、一方で距離空間の枠組みは柔軟性に欠ける面もある。
-----------------------------------------------------

ということで、位相空間とは距離空間で議論される連続や連結といった概念を距離を用いずに一般化したもの、ということになります。
私にはなかなか理解できませんでしたが、数学の本やサイトを乱読した結果、なんとなく分かったような気がしてきました。
今回もやはり単なる勘違いという可能性もありますが。


以下、私なりの理解をまとめてみます。

距離空間(X,d)から定義される開集合について

ε>0とし、点x∈Xの「ε近傍 Bε(x)」とは、
Bε(x)={y∈X | d(x,y)<ε}
すなわち、xから距離がε未満の点の集合であり、 「ε開円盤」「ε開球」といわれることもある。 (円盤/球は、二次元/三次元ユークリッド空間を想像するとよい)

集合A⊆Xが「開集合」であるとは、
∀x∈A, ∃ε, Bε(x)⊆A
すなわち、Aに属する任意の点xに対して、Aに含まれるようなε近傍が(xのそれぞれ毎に)存在する。


上記のように定義した開集合から、閉集合、開近傍、閉包、内部、境界、連続写像などの位相的概念の定義と定理が導かれます。例えば、

・閉集合とは、開集合の補集合
・x∈Xの近傍とは、xが属するような開集合
・Aの内部とは、Aに含まれるような近傍が存在する点の集合
・Aの境界とは、Aの内部でなく、Aの補集合の内部でもない点の集合
・Aの閉包とは、Aの内部とAの境界の和集合

など。


上記のように、開集合の最初の定義以外は、距離(から定義されるε近傍)を直接使わずとも、開集合さえあれば定義できます。


また、連続写像は、距離空間では最初はεδ論法を用いて、ε近傍で定義しますが、「写像が連続であることの必要十分条件は、開集合の逆写像が開集合であること」が導かれます。


距離から導かれる位相(開集合とそこから導かれる数学的概念)では、距離は(開集合の定義を導く以外には)直接的には不要ということが分かりました。


さらに、ε近傍から定義される開集合から以下の定理が成り立ちます。

Aが開集合 ⇔
∀x∈A, ∃B:開集合, x∈B⊆A
すなわち、Aに属する任意の点xに対して、xが属しAに含まれるような開集合Bが存在する

循環論法的な定理ですが、逆にいえば「最初に開集合ありき」とすれば、距離がなくても位相の議論ができることを示しています。


⇒開集合が満たすべき本質的性質(公理)はなにかと考えると、突き詰めると以下の三つの性質(開集合の公理)になる

1) X 自身および空集合は開集合である
2) 有限個の開集合 A_1, ..., A_n の共通部分は開集合である
3) 開集合の族 {A_λ|λ∈Λ}について,その和集合は開集合である
(非加算無限個であってもよい)

| | コメント (0) | トラックバック (0)

2014/07/12

命令セットアーキテクチャを考える(番外編) 飽和演算

「ぼくのかんがえたさいきょうのめいれいせっと」では、SIMD演算(ベクトル演算)モードでは、自動的に飽和演算(サチュレート演算ともいう)となります。その6の整数加算命令ではSIMDモードについて以下のように書きました。

> ・condition code bitは変化しない。加算結果が最大値を超えた場合には最大値が、最小値(負数で絶対値が最大のもの)を超えた場合は最小値がセットされる(飽和演算)。

同様に、その7の浮動小数点加算命令のSIMDモードでも、以下のように書きました。

> ・SIMDモードの場合、CCR1は変化しない。結果の絶対値が最大値を超えた場合には符号付きの最大値が、計算できない場合にはNaNが返る。

飽和演算って言葉は普通は整数データにしか使わないような感じもするのですが、浮動小数点データだって、最大値付近のデータを加算すれば指数ビットがオーバーフローすることもありえます。ましてや乗算なら。

このような仕様にしたのは、演算結果の状態に応じてフラグをセットするためのCondition Code Registerが1組しかないのに、SIMD演算命令では同時に複数の演算結果が得られるため、CCRをセットしなくても良いようにしようという発想からであり、積極的に飽和演算機能を備えようと思ったからではありません。CCRが複数あると、条件付き分岐命令の際にどのCCRを見ればいいかとか、ややこしくなることも頭にありました。

普通の計算処理においては、計算結果がオーバーフローなどしたら変に丸めたりしないで、別の処理をとる必要があることがほとんどと考えています。その場合にはSIMDモードは使用できず、スカラーモードで繰り返し計算をしていただく必要があります。

つまり、「ぼくのかんがえたさいきょうのめいれいせっと」アーキテクチャではSIMD演算命令は自動的にすべて飽和計算モードになってしまい、それが嫌ならスカラーモードで繰り返し計算してください、という考え方です(でした)。


前置きが長くなってしまいましたが、「これでよかったのかなぁ」というのがこの番外編のテーマです。

「飽和演算になってしまうのは嫌だけど、SIMD(ベクトル)演算は必要だ」というニーズが多ければ、考え直さなければなりません。

その場合には、CCRをスカラー演算用セットの他に、ベクトル演算用にあと7セット(SIMD演算モードは最大8個のデータ処理を同時に行なうため)または8セット(スカラー演算用CCRとは別にする場合)追加すれば可能です。演算結果のどれかが例外割り込みが必要になった場合には、割り込み処理を呼び出し、あとは割り込みルーチン内でどの演算結果が(複数個の場合も含めて)例外になったのかどうかを判断して処理してもらえればいいでしょう。そのためには、CCRの内容を汎用レジスタに転送する特殊命令も必要そうです。
なお、条件付き分岐命令ではSIMD命令でセットされるCCRは見ないことにしてしまいましょう。


逆に、SIMDではない普通の(スカラー)演算で、飽和演算モードは必要でしょうか。
飽和演算モードが必要な場合、別の命令コードを起こしたり命令モードビットを立てるのは、命令フォーマットに余裕がないことから避けたいです。

その3の丸めモード指定レジスタを拡張して、飽和演算モードビットを追加するのが良さそうです。

> [Rounding Mode Register(Read/Write)]
> ・浮動小数点演算の丸め処理のモードを指定する
> ・特権モードでのみ設定可能、ユーザプログラムからは読み取りのみ可能。

その3を書いた時点では、この特殊レジスタはシステムに1個(各スレッドで共通)という想定でしたが、プログラムで丸めモードを変更するということになると、ユーザプログラムからも設定可能で、スレッド切り替え時には退避されるようにする必要があります。

| | コメント (0) | トラックバック (0)

2014/06/29

命令セットアーキテクチャを考える (番外編) 積和演算命令について再考

その4(命令コード)で、

> ・積和演算命令は備えない(4オペランド必要になるので)

としていますが、積和演算命令は科学技術計算や画像処理・信号処理などで多様されるので、やはり実装したほうがいいのかなと考えてみました。

「ぼくのかんがえたさいきょうのめいれいせっと」では、積和演算が必要な場合、特に短精度データ(単精度の間違いではありません)の場合には、SIMDモード命令と水平演算命令を組み合わせることで、比較的高性能(少ない命令数と少ないクロック数)で実現できると考えていました。

例えば、単精度実数による4次元ベクトルA=(a1,a2,a3,a4)とB=(b1,b2,b3,b4)の内積を計算する場合には以下のようにプログラミングできます。

アドレスAから連続する4ワードにa1,a2,a3,a4が格納され、アドレスBから連続する4ワードにb1,b2,b3,b4が格納されており、その内積をアドレスCに格納するとします。

A: dc float"a1","a2","a3","a4" # dcは定数を定義する(define constant)アセンブラ命令
B: dc float"b1","b2","b3","b4" # 同上
C: da float # daは領域確保を定義する(define area)アセンブラ命令

lea R0,=A,R1 # R1にアドレスAを格納する : offset値(=A)は、アセンブラがPC相対アドレスを計算する
lea R0,=B,R2 # R2にアドレスBを格納する : 同上
lea R0,=C,R3 # R3にアドレスCを格納する : 同上

fldm 2 R1,=0,FR2 # FR2,FR3にベクトルAを格納する
fldm 2 R2,=0,FR4 # FR4,FR5にベクトルBを格納する

fadd v sp FR0,FR0,FR6 # FR6,FR7,FR8,FR9に単精度実数0.0×8個を格納する
fmul v sp FR2,FR4,FR6 # FR6,FR7にa1*b1,a2*b2,a3*b3,a4*b4を単精度実数として計算し、格納する
fhadd sp FR6,FR1 # FR1の下位32bitに、FR6,FR7,FR8,FR9に格納されているa1*b1,a2*b2,a3*b3,a4*b4と0.0*0.0×4個の総和を計算して格納する

fstore sp R3,=0,FR1 # FR1の下位32bitの内容をアドレスCに格納する

アドレス計算やload/store、それにSIMDモード命令のパックドデータ数の調整のためのレジスタクリアを除けば、SIMDモード乗算命令と水平加算命令の計2命令で実現できます。積和演算というくらいなのでベクトル演算を除けば乗算と加算命令で実現できるのは当たり前ですが。ただ、ややこしいといえばややこしいので、積和演算命令(SIMDモード付き)ができれば当然そのほうがプログラマ的にも便利でしょう。


積和演算命令を備えない理由として、4オペランド必要になることを挙げていました。
が、上記の内積計算のように、多くの積和計算処理では各要素データの乗算結果の総和をとるような計算が多いので、A×B+C→DでなくてA×B+C→Cでも、多くの場合、Cの元の値を別レジスタに保存しておく必要はなさそうです。ディストネーションオペランドの意味が微妙に違ってきてしまいますが、眼を瞑ることにして、命令コードフォーマットの問題はひとまず解決とします。


ところが、浮動小数点演算命令はすでに16種類あり、命令コードを「綺麗な形式」で浮動小数点積和演算命令を追加することができません。整数演算命令も命令コードのビットパターンに空きがありません。
命令コードが綺麗な形式で定義できないと、前提条件で書いたような「ダンプデータをみてもプログラムが読める」目的からはずれていってしまいますので好ましくありません。

浮動小数点演算命令の場合は、番外編の「本当の汎用レジスタセット」に書いたように、汎用レジスタと浮動小数点レジスタ間の単純データ転送命令(ビットパターンのままの転送命令)を省略することができれば、この問題は解決します。

(修正)命令数を数え直したら、浮動小数点演算命令は全部で15種類でした(その13は修正しました)。ということで、上記のような変更を加えなくても、命令の追加は可能です。また、逆数の近似値命令と平方根の逆数の近似値命令を、即値ビットを使ってモード指定するようにすれば、命令コードをもう一つ空けることもできます。


整数演算命令の命令コードビットパターンは、load/store/分岐命令が7種類、ビット演算命令も7種類なのでここに埋め込むことも可能です。あまり「綺麗な形式」とはいえませんが。できれば、四則演算命令のパターンのところに追加したいのですが、四則演算というくらいなので命令4種類、それぞれに符号付き二進数と符号なし二進数の場合があるので合計8種類になり、空きがありません。
符号付きと符号なしをどこかの空きビットを使ってモード設定できればいいのですが、その空きビットもありません。即値を10bit指定から減らせば可能ですが、分岐命令のoffset範囲が半分に減っちゃうのは結構影響が大きいように思います。

スワップ命令(1)をビット演算命令(7)のグループと一緒にして、水平演算命令(7)のグループに積和演算命令を追加するのが、比較的綺麗そうですね。


ところで、整数の積和演算命令って必要ですかね。
信号処理などのデジタル化データの場合は浮動小数点データではなくて整数の場合も多いと思います。この命令セットではDSPのような用途は想定していませんけど、静止画像処理とか動画像処理とかは、「普通の」PCやワークステーションでも多く利用される用途でしょう。ってことはやはりあったほうがよさそうです。それに、浮動小数点データのみに積和演算命令を追加というのは、綺麗じゃないですよね。

結論はでないまま、今日のところはここまで。

| | コメント (0) | トラックバック (0)

2014/06/28

命令セットアーキテクチャを考える (番外編) 本当の汎用レジスタ

ほとんどのCPUアーキテクチャでは、整数演算/論理演算/ビット操作等用の汎用レジスタと、浮動小数点レジスタは別構成となっています。「ぼくのかんがえたさいきょうのめいれいせっと」シリーズでもそれにならって、汎用レジスタ×64本と浮動小数点レジスタ×64本の構成としました。

汎用レジスタと浮動小数点レジスタを別構成にするというのは、おそらく浮動小数点演算ユニットが電子回路的に複雑でチップ面積をたくさん必要とするとか、処理クロックもたくさん掛かるとかなどで、浮動小数点演算ユニットが使うレジスタも、汎用レジスタとは別回路として演算回路の近くに配置しよう、というような理由じゃないかと想像しています。というか、浮動小数点演算はコプロセッサとして別チップだったという歴史的な背景もあるように思います。

一方で、アプリケーションプログラマからみると、汎用レジスタも浮動小数点レジスタも、演算用にデータを一時的に置いておくところという意味では同じです。別になっていなければならない理由はありません。むしろ、load/store型アーキテクチャでは、浮動小数点レジスタにどのようにデータを詰め込むか、あるいは取り出すかということを、汎用レジスタとは別に考えなければならなくなります。
「ぼくのかんがえたさいきょうのめいれいせっと」アーキテクチャでも、浮動小数点レジスタ用のメモリデータアクセス(load/store)命令と、汎用レジスタ⇔浮動小数点レジスタ間のビットパターン転送命令を追加しました。

電子回路的なことは無視すると、同一のレジスタを整数演算命令が操作するときは整数データとして、浮動小数点数演算命令が操作するときは浮動小数点数データとして扱うようにできれば、便利になりそうです。

「ぼくのかんがえたさいきょうのめいれいせっと」アーキテクチャは、64本ものレジスタを持っており、最近主流のCPUアーキテクチャはだいたい32本であることを考えると、64本が汎用/浮動小数点レジスタ兼用という「本当の汎用」レジスタにしても、レジスタ本数が少なくて不便ということは少ないと考えられます。

| | コメント (0) | トラックバック (0)

2014/06/21

命令セットアーキテクチャを考える13 (命令コード)

命令コードフォーマットのうちopcode 6bitの割り当て概略案です。

opcodeの構成(上位3bit)

000 : load/store(4) + 分岐(branch/jump)命令(3)
001 : 整数演算命令(四則演算)(8)
010 : 水平演算(7) + スワップ命令(1)
011 : 論理演算命令(3) + シフト命令(5)
100 : 浮動小数点演算命令(15)
101 : 同上
110 : bit操作命令(7)
111 : special

これで上位3bitを見るだけで、どういった命令かがわかるようになります。

その4で書いた、命令コードフォーマットのちょっと変態なビット割り付けの理由がここでわかります。

最初の前提条件で書いたように、「16進ダンプを見てもプログラムがわかるのが理想」なのですが、いろいろとやって見ても難しかったので、それじゃぁ「8進ダンプならどうか」って考えました。実は、64本というレジスタ本数も6bitで表現できるということが理由です。8bit(256本)にしたらもっと良かったのですが、残念ながら3オペランド命令形式では、レジスタ指定ビットだけで24bit使っちゃうので、命令コードが入りません。

その4で書いた命令コードフォーマットですが、ちょっと変則的に16bit(2バイト)単位に下位から3bitずつ区切ると区切りやすいようなっています。


[命令コードフォーマット]

bit[31:28] : Mode(1+1+2) :vector/PC相対/increment,imm/offset,データ長
bit[27:22] : OPcode(6)
bit[21:16] : Rs(6)
bit[15:6] : imm/offset(10) : imm/offsetとRtはどちらか一方
bit[11:6] : Rt(6)
bit[5:0] : Rd(6)


とりあえず、このシリーズはいったん終了です。

| | コメント (0) | トラックバック (0)

2014/06/20

命令セットアーキテクチャを考える12 (特殊命令)

その他、特殊命令関係です。知識がないため未検討です。多分こんな命令が必要なはず、と想像しています。


[モード遷移命令群]
・supervisor-mode/user-mode切り換えなど

[同期/排他制御用命令群]
・セマフォ、バリア命令など

[暗号化支援]
・暗号化/復号化、キー生成

[仮想化支援]
・よくわかりません

[特殊レジスタアクセス命令]
・よくわかりません

[省電力支援]
・よくわかりません


とりあえず、前提が、アプリケーションプログラマから見た命令セットということで始めましたので、上記のような機能はOSのサービスを呼び出すということでゴニョゴニョ…

| | コメント (0) | トラックバック (0)

2014/06/16

命令セットアーキテクチャを考える11 (分岐命令)

ようやく終わりに近づいてきました。分岐命令です。


[Jump/Branch]:3命令

条件付き分岐はbranch(br)、無条件分岐はjump(jmp)と称する

brl [pc] Rs,=imm,Rd

・CCR0/CCR1の状態がimmで指定される条件に合致する場合に、Rsで指定したアドレスに分岐し、Rdには戻りアドレスとして現在のPCの値が格納される(branch and link)。
・pcモードの場合は、PCの内容とRsの内容を加算したアドレスに分岐する。
・CCR0/CCR1は変化しない。

・imm(10bit)による分岐条件の詳細は以下の通り。
・bit9:CCR0かCCR1を指定(どちらか一方のみ)
・bit8:bit0-bit7が、CCR0/CCR1の各ビットと複数マッチした場合に、その論理積(and)をとるか論理和(or)をとるかを指定
・bit7-bit0:CCR0またはCCR1の対応するビットが"1"である場合に条件成立とする

・ここで、CCR0とCCR1の内容を再掲しておきます。

[CCR0]
bit4: Overflow/Carryover(o) : Overflow
bit3: Underflow/Borrow(u) : Underflow
bit2: positive/plus(p) : Positive
bit1: zero(z) : Zero
bit0: negative/minus(m) : Minus

[CCR1]
bit7: 非正規化数(s) : Subnormal number
bit6: 無限大(i) : Infinite number
bit5: NaN(n) : Not a number
bit4: Overflow : Overflow
bit3: Underflow : Underflow
bit2: positive/plus(p) : Positive
bit1: zero(z) : Zero
bit0: negative/minus(m) : Minus


・戻りアドレスを格納しない(branch and linkではない)branch命令はない。戻りアドレスが不要な場合はRdとしてR0を指定する。


jmpl [pc] Rs,{Rt|=offset},Rd

・Rs及びRtまたはoffsetで指定したアドレスに分岐し、Rdには戻りアドレスとして現在のPCの値が格納される(jump and link)。
・分岐先アドレスの計算は、RsとRtの和、またはRsと(offset値の4倍)の和となる。
・アセンブラ言語ソースプログラムではoffsetの値はそのまま記述し、アセンブラが1/4してoffset領域に設定する。
・pcモードの場合は、さらにPCの内容を加算したアドレスに分岐する。
・CCR0/CCR1は変化しない。

・戻りアドレスを格納しない(jump and linkではない)jump命令はない。戻りアドレスが不要な場合はRdとしてR0を指定する。


lea Rs,{Rt|=offset},Rd

・分岐ではないが、おなじようにアドレス計算するということで、ここの括りに入っています。
・PCとRsとRtの和、またはPCとRsと(offset値の4倍)の和を計算し、Rdに格納する。
・アセンブラ言語ソースプログラムではoffsetの値はそのまま記述し、アセンブラが1/4してoffset領域に設定する。


[擬似命令]

nop → jmpl pc R0,R0,R0

・PCの指すアドレス(次の実行番地)にジャンプするのでnop(No Operation)となる。
・そもそも、すべて固定長命令フォーマットであり、かつ遅延スロットもないのでnopは不要なような気もしますが…
・copy R0,R0,R0でも代用可能。但し、condition codeが変化する


opfch → brl Rs,=#3ff,R0 :

・opfch(operation code fetch)命令は、必ず不成立となる条件付き分岐命令に変換される。
・分岐は必ず失敗するが、分岐先アドレスの命令データfetch処理が途中まで進むため、L1命令キャッシュが読み込まれる。

br [r] Rs,=imm → brl [pc] Rs,=imm,R0
jmp [r] Rs,Rt → jmpl [pc] Rs,Rt,R0

・戻りリンク無しの分岐命令はないが、アセンブラ言語ソースプログラムの見やすさのため、リンク無し分岐命令のような擬似命令を用意した。アセンブラがリンクアドレス格納レジスタをR0と設定する。


branch命令の条件コードをimm値として記述するのはややこしいため、アセンブラで以下のような擬似命令を備える。

brleq Rs,Rd → brl Rs,=#102,Rd : z-flg on
brlne Rs,Rd → brl Rs,=#005,Rd : p-flg on or m-flg on
brlge Rs,Rd → brl Rs,=#006,Rd : p-flg on or z-flg on
...
breqf Rs → br Rs,=#302 : z-flg on
brnef Rs → br Rs,=#105 : p-flg on or m-flg on
brgef Rs → br Rs,=#106 : p-flg on or z-flg on
...

| | コメント (0) | トラックバック (0)

2014/06/13

命令セットアーキテクチャを考える10 (浮動小数点数演算命令)

ようやく、浮動小数点演算命令にたどり着きました。


[浮動小数点数演算命令]:6命令

fadd [v] [sp|dp|qp] FRs,FRt,FRd

・FRsとFRtの内容を浮動小数点数として加算した結果をFRdに格納する。
・単精度モードの場合、FRs及びFRtの下位32ビットを単精度浮動小数点数として計算し、FRdの下位32ビットに格納する。
・倍精度モードの場合、FRs及びFRtの64ビットを倍精度浮動小数点数として計算し、FRdの64ビットに格納する。
・四倍精度モードの場合、FRs及びFRtのそれぞれ連続する二本のレジスタを連結した128ビットを四倍精度浮動小数点数として計算し、FRdの連続する二本のレジスタに格納する。FRs,FRt,FRdはすべて偶数レジスタでなくてはならない。
・計算結果によって、CCR1の内容がセットされる。

・SIMDモードの場合、FRs及びFRtのぞれぞれ連続する四本のレジスタを使って、32bit*8、64bit*4、128bit*2のデータとして演算に使用される。結果は、FRdの連続する四本のレジスタに32bit*8、64bit*4、128bit*2として格納される。
・SIMDモードの場合、CCR1は変化しない。結果の絶対値が最大値を超えた場合には符号付きの最大値が、計算できない場合にはNaNが返る。
・SIMDモードの場合、レジスタ番号はすべて偶数でなくてはならない。(4の倍数でなくてもよい) レジスタ番号としてFR62は指定できない。

fsub [v] [sp|dp|qp] FRs,FRt,FRd

・FRsの内容からFRtの内容を減算するほかはfaddと同様。

fmult [v] [sp|dp|qp] FRs,FRt,FRd

・FRsの内容とFRtの内容を乗算するほかはfaddと同様。

fdiv [v] [sp|dp|qp] FRs,FRt,FRd

・FRsの内容からFRtの内容を除算するほかはfaddと同様。


・正規化数以外(最大値、非正規化数、NaNなど)を含む四則演算結果については別途検討が必要。基本的にはIEEE754に準拠する。


frcp [v] [sp|dp|qp] FRs,FRd

・FRsの逆数(reciprocal)の近似値をFRdに格納する。
・単精度モードの場合、FRs及びFRtの下位32ビットを単精度浮動小数点数として計算し、FRdの下位32ビットに格納する。
・倍精度モードの場合、FRs及びFRtの64ビットを倍精度浮動小数点数として計算し、FRdの64ビットに格納する。
・四倍精度モードの場合、FRs及びFRtのそれぞれ連続する二本のレジスタを連結した128ビットを四倍精度浮動小数点数として計算し、FRdの連続する二本のレジスタに格納する。FRs,FRt,FRdはすべて偶数レジスタでなくてはならない。
・計算結果によって、CCR1の内容がセットされる。FRsの内容がゼロ(正負ともに)の場合は0除算例外が発生する。

・SIMDモードの場合、FRs及びFRtのそれぞれ連続する四本のレジスタを使って、32bit*8、64bit*4、128bit*2のデータとして演算に使用される。結果は、FRdの連続する四本のレジスタに32bit*8、64bit*4、128bit*2として格納される。
・SIMDモードの場合、CCR1は変化しない。0除算例外割り込みも発生しない。(最大値が返る)計算できない場合にはNaNが返る。
・SIMDモードの場合、レジスタ番号はすべて偶数でなくてはならない。(4の倍数でなくてもよい) ただし、FR62は指定できない。

frsqrt [v] [sp|dp|qp] FRs,FRd

・FRsの平方根の逆数(reciprocal of square root)の近似値が格納されるほかはfrcpと同様。
・FRsの内容が負(-0を除く)であった場合には、例外が発生する。FRsの内容がゼロ(±0)の場合にはゼロ除算例外が発生する。


[擬似命令]

fcopy [v] [sp|dp|qp] FRs,FRd

・FRsの内容をFRdにコピーする。
・アセンブラが「fadd [v] [sp|dp|qp] FRs,FR0,FRd」に変換する。

fclear [v] [sp|dp|qp] FRd

・FRdの内容をゼロクリアする。
・アセンブラが「fadd [v] [sp|dp|qp] FR0,FR0,FRd」に変換する。


[水平演算命令]:2命令

fhadd [sp|dp|qp] FRs,FRd

・ニーモニックの先頭の"h"はhorizontalを意味する。
・FRsから連続する四本のFRレジスタの内容を、single*8またはdouble*4またはquad*2の浮動小数点データとして、その総和を計算し、FRdに格納する。FRsは偶数レジスタでなければならない。quadモードの場合はFRdも偶数レジスタでなければならない。

fhmult [sp|dp|qp] FRs,FRd

・乗算であることの他はfhaddと同様。


[特殊定数値ロード命令]:1命令

fspcnum [v] [sp|dp|qp] =imm,FRd

・特殊な定数値(special number)をFRdに格納する。特殊な定数値はimmで指定する。
・imm=0:+0.0、imm=1:+1.0、imm=2:e、imm=3:π …
・immは10ビットあるので、ROMの容量に余裕があれば、最大1024個まで定義できる。
・アセンブラソースプログラム上、即値を直接記述しても分かりにくいので、
zero equ 0
one equ 1
e equ 2
pai equ 3

のように定義しておくと、アセンブラソースプログラムを読みやすく理解しやすくできる。

・四倍精度モードの場合、FRdから連続する二本のレジスタに格納される。FRdは偶数レジスタでなければならない。
・SIMDモードの場合は、FRdから連続する四本のレジスタに、32bit×8、64bit×4、128bit×2個の同じ値が格納される。FRdは偶数レジスタでなければならない。(4の倍数である必要はない)
・ロードした値に基づいてCCR1がセットされる。SIMDモードの場合もCCR1がセットされる。


[精度変換命令]:2命令

fup [sp|dp] FRs,FRd

・FRsの浮動小数点数の精度を拡張し(単精度→倍精度、倍精度→四倍精度)、FRdに格納する。
・倍精度→四倍精度の場合、FRdから連続する二本のレジスタに格納される。FRdは偶数レジスタでなければならない。
・変換後の値に基づいてCCR1がセットされる。

fdown [dp|qp] FRs,FRd

・FRsの浮動小数点数の精度を縮小し(倍精度→単精度、四倍精度→倍精度)、FRdに格納する。
・四倍精度→倍精度の場合、FRsから連続する二本のレジスタに格納されたデータを変換する。FRsは偶数レジスタでなければならない。
・変換後の値に基づいてCCR1がセットされる。

・SIMDモードは必要か。レジスタの使い方が他の命令のSIMDモードとはちょっと変則的になるが。


[擬似命令]

fsp2dp FRs,FRd → fup sp FRs,FRd
fdp2qp FRs.FRd → fup dp FRs,FRd
fqp2dp FRs,FRd → fdown qp FRs,FRd
fdp2sp FRs,FRd → fdown dp FRs,FRd


[汎用レジスタ転送命令]:4

gr2fr [1|2|4|8] Rs,FRd

・Rsで指定される汎用レジスタの内容を、FRdで指定される浮動小数点レジスタにビットパターンとしてコピーする。
・CCR1の内容は変化しない。

fr2gr [1|2|4|8] FRs,Rd

・FRsで指定される浮動小数点レジスタの内容を、Rdで指定される汎用レジスタにビットパターンとしてコピーする。
・CCR0の内容は変化しない。

・複数レジスタ指定は、アセンブラが複数命令に展開したほうがいいか?

int2fp [hw|w|dw] Rs,FRd

・Rsの内容を符号付き二進数とみなし、浮動小数点数に変換し、FRdに格納する。
・half-wordモードの場合はRsの下位16ビットを単精度浮動小数点数に、wordモードの場合はRsの下位32bitを倍精度浮動小数点数に、double-wordモードの場合はRsの64bit全体を四倍精度浮動小数点数に変換する。double-wordモードの場合には、FRdは偶数レジスタである必要がある。
・変換結果に応じて、CCR1をセットする。

fp2int [sp|dp|qp] FRs,Rd

・FRsの内容を整数(符号付き二進数)に変換し、Rdに格納する。小数点以下は切り捨てる。
・単精度/倍精度/四倍精度の浮動小数点数を、すべてdouble-wordの整数に変換する。
・変換結果に応じて、CCR0をセットする。

・丸め方法はIEEE 754の仕様を確認しないといけない…

| | コメント (0) | トラックバック (0)

2014/06/12

命令セットアーキテクチャを考える9 (ビット操作命令)

どんどんいきます。次はビット操作命令です。

[ビット操作命令]:6命令

setbit [v] [b|hw|w|dw] Rs,{Rt|=imm},Rd

・Rsの内容を、Rtまたはimmで示されるビット位置を"1"にセットし、Rdに格納する。
・セットする元の値によってCCR0を設定(正/零)する。(結果ではなくて、元の値によってCCR0がセットされることに注意)
・byteモード/half-wordモード/wordモードモードの場合、Rsの下位8ビット/16ビット/32ビットのうちの指定ビットのみがセットされ、残りの上位ビットは変更されない。
・byteモード/half-wordモード/wordモード/double-wordモードの場合、Rtまたはimmの下位3ビット/4ビット/5ビット/6ビットのみが有効であり、符号無し二進数とみなされる。

・SIMDモードの場合、Rsレジスタ内のデータを8bit*8、16bit*4、32bit*2のデータとしてそれぞれセットされる。
・SIMDモードの場合、Rtまたはimmの下位ビットが用いられ、すべてのパックドデータに対して同じビット位置がセットされる。
・CCRは変更されない。

clrbit [v] [b|hw|w|dw] Rs,{Rt|=imm},Rd

・"0"にクリア(clear)するほかはsetbitと同様。

revbit [v] [b|hw|w|dw] Rs,{Rt|=imm},Rd

・もとのビットを反転(reverse)する("0"→"1"、"1"→"0")ほかはsetbitと同様。


[擬似命令]

tstbit [b|hw|w|dw] Rs,{Rt|=imm}

・指定位置のビット状態をテストする。結果はCCR0にセットされる。(正/零)
・アセンブラが「setbit [b|hw|w|dw]Rs,{Rt|=imm},R0」に翻訳する。Rdにゼロレジスタを指定しているため、CCR0以外はなにも変更されない。


[ビットカウント命令]:4命令

ctzero [v] [b|hw|w|dw] Rs,Rd

・Rs内の"0"ビットの数をカウントし(count zero bits)、Rdに格納する。
・byteモード/half-wordモード/wordモード/double-wordモードでは、Rsの下位8ビット/16ビット/32ビット/64ビット内の"0"ビットの数のみをカウントし、Rdの下位8ビット/16ビット/32ビット/64ビットに格納する。Rdの余った上位ビットは変化しない。
・"0"ビットのカウント数によって、CCR0をセットする。(正/零)

・SIMDモードの場合、Rsレジスタ内のデータを8bit*8、16bit*4、32bit*2のデータとしてそれぞれゼロビットの個数がカウントされ、Rdの対応する領域に格納される。
・CCRは変更されない。

ctbit [v] [b|hw|w|dw] Rs,Rd

・Rs内の"1"ビットを数える(count bits)ほかはctzeroと同様。
・反転してから"0"ビットを数えても同じ結果が得られるので不要とも言えるが…

ctlzero [v] [b|hw|w|dw] Rs,Rd

・上位ビットからの連続した"0"ビットを数える(count leading zero bits) ほかはctzeroと同様。

cttzero [v] [b|hw|w|dw] Rs,Rd

・下位ビットからの連続した"0"ビットを数える(count trailing zero bits)ほかはctzeroと同様。

| | コメント (0) | トラックバック (0)

命令セットアーキテクチャを考える8 (シフト/ローテート/バイトスワップ命令)

続いて、シフト/ローテート/バイトスワップ命令の定義です。


[シフト命令]:4命令

sll [v] [b|hw|w|dw] Rs,{Rt|=imm},Rd

・Rsの内容を、Rtまたはimmで示されるビット数分、論理左シフト(shift left logical)し、Rdに格納する。
・CCR0は変化しない。
・byteモード/half-wordモード/wordモードモードの場合、Rsの下位8ビット/16ビット/32ビットがシフトされ、残りの上位ビットは変更されない。
・byteモード/half-wordモード/wordモード/double-wordモードの場合、Rtの下位3ビット/4ビット/5ビット/6ビットのみが有効であり、符号無し二進数とみなされる。
・immモードの場合、同様に下位ビットが符号無し二進数とみなされる。

・SIMDモードの場合、Rsレジスタ内のデータを8bit*8、16bit*4、32bit*2のデータとしてシフト演算に使用される。
・SIMDモードの場合、Rtまたはimmの下位ビットが用いられ、すべてのパックドデータに対して同じビット数だけシフトされる。

srl [v] [b|hw|w|dw] Rs,{Rt|=imm},Rd

・論理右シフト(shift right logical)となることを除いて、sll命令と同様。

sla [v] [b|hw|w|dw] Rs,{Rt|=imm},Rd

・算術左シフト(shift left arithmetic)となることを除いて、sll命令と同様。

sra [v] [b|hw|w|dw] Rs,{Rt|=imm},Rd

・算術右シフト(shift right arithmetic)となることを除いて、sll命令と同様。


[ローテート命令]:1命令

rot [v] [b|hw|w|dw] Rs,{Rt|=imm},Rd

・Rsの内容をRtまたはimmで示されるビット数分だけ左ローテートし、Rdに格納する。(右ローテート命令はないが、ローテート量を大きく指定することにより同じ結果が得られる)
・CCR0は変化しない。
・byteモード/half-wordモード/wordモードモードの場合、Rsの下位8ビット/16ビット/32ビットがシフトされ、残りの上位ビットは変更されない。
・byteモード/half-wordモード/wordモード/double-wordモードの場合、Rtまたはimmの下位3ビット/4ビット/5ビット/6ビットのみが有効であり、符号無し二進数とみなされる。

・SIMDモードの場合、Rsレジスタ内のデータを8bit*8、16bit*4、32bit*2のデータとしてそれぞれローテートされる。
・SIMDモードの場合、Rtまたはimmの下位ビットが用いられ、すべてのパックドデータに対して同じビット数だけローテートされる。


[バイトスワップ命令]:1命令

boswap [hw|w|dw] Rs,Rd

・Rsの内容を2byte/4byte/8byte単位でbyte order swappingしてRdに格納する。
・Rsの内容が16進表記で0123456789ABCDEFであった場合、Rdの内容は以下のようになる。
hwモード :23016745AB89EFCD
w モード :67452301EFCDAB89
dwモード :EFCDAB8967452301

| | コメント (0) | トラックバック (0)