EssenR2_jit00
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
* Essen Rev2 JIT00
-(by [[K]], 2017.07.31)
** JIT00で提供する機能
-「即値が使えない命令」のような例外をなくす
-ラベルを使えるようにする
-CPUに依存するレイヤをここに集約する(JIT01以降はCPUに依...
-実際のCPUのレジスタ数がいくつであるかなどの制約を受けず...
** 基本仕様
-c# : 即値
-l# : ローカル変数(#=0~)
-g# : グローバル変数
-L# : 分岐先指定などに使うラベル
-p# : ポインタレジスタ(p0~p63)
-i# : s32以上レジスタ(i0~i63)
-f# : f64以上レジスタ(f0~f63)
-ローカル変数、グローバル変数には、どんな型の値でも代入で...
-ポインタレジスタはポインタしか代入できない。
-s32以上レジスタは整数しか代入できない。
-f64以上レジスタは浮動小数点しか代入できない。
-p#, i#, f#はグローバル変数で、これをうまく使いこなせるか...
-基本構文
命令 パラメータ1 パラメータ2 ...
-人間にとって書きやすい構文にしようとしていない。どうせこ...
--だからコメントやマクロなどはない。
-パラメータはスペース区切り(コンマはいらない)
-命令の命名規則
--最初の一文字はnかs。nはノーマル。sはスピード優先。
--二文字目はパラメータの数。
--末尾には型を表す接尾子が入る場合がある。
-例1:
n0sysEnt // JITコードの先頭に入れるべきコード...
s2cp_s32 g0 c0 // g0に定数0を代入
n1label L0 // ここをL0とする
s2add_s32 g0 g0 c1 // g0 += 1
s4cjmp_s32 g0 c1000000000 1 L0 // 条件ジャンプ命令 if ...
n0sysRet // JITコードから帰る場合に入れるべき...
-[Q]人間が書くわけじゃない中間言語なのに、どうしてバイナ...
--[A]その意見には全面的に賛成します。まあひとまずはデバッ...
** 命令一覧
-システム命令
--n0sysEnt
--n0sysRet
--n0reg
---n0reg "ppif" みたいに使う。「可能であればp00,p01,i00,f...
-2項演算命令
--s2cp_s32
--s2cp_f64
--s2cnv_f64_s32
--s2cnv_s32_f64
--s2not_s32 // xor -1 で代用できるので、消すかもしれない.
--s2neg_s32 // mul -1 で代用できるので、消すかもしれない.
-3項演算命令
--s3or_s32
--s3xor_s32
--s3and_s32
--s3add_s32
--s3sub_s32
--s3mul_s32
--s3shl_s32
--s3shr_s32 (符号付き右シフト)
--s3div_s32
--s3mod_s32
--s3add_f64
--s3sub_f64
--s3mul_f64
--s3div_f64
-条件分岐命令など
--n1align
--n1label
--n1jmp
--n1call_ext
--s4cjmp_s32 (ポインタを使ったjmpは想定しない)
--s4cset_s32_s32
--s4cjmp_f64 (ポインタを使ったjmpは想定しない)
--s4cset_s32_f64
-ポインタ演算
--未設計
** x86(32bit)版の仕様
-こうでなければいけないということではないが、とりあえず最...
-変数は16バイト
--型(32bit)、補助属性(32bit)、値(最大64bit)
--値が64bitに収まらない場合や可変長の場合は、ポインタを入...
-EAX: テンポラリデータレジスタ
-EBP: ローカル変数のベース
-EBX, ESI, EDI, ECX, EDX: pかiを割り当てる
//-EAX: テンポラリデータレジスタ
//-EDI: グローバル変数のベース
//-EBP: ローカル変数のベース
//-ESI: ワークエリアのベース
//-EBX: p0
//-ECX: テンポラリポインタ(p1)
//-EDX: テンポラリ
//--p2~p31はワークエリア内にある
//--i0~i31はワークエリア内にある
//--f0~f5はFPUの中にあり、f6~f31はワークエリア内にある
-例1は以下のような機械語になる(2017.07.28時点)
60 PUSHAD n0sysEnt
BF E8 24 48 00 EDI=....
B8 00 00 00 00 EAX=0 s2cp_s32 g0 i0
89 87 08 00 00 00 [EDI+8]=EAX
n1label L0
8B 87 08 00 00 00 EAX=[EDI+8] s2add_s32 g0 ...
40 EAX++
89 87 08 00 00 00 [EDI+8]=EAX
3D 00 CA 9A 3B CMP(EAX,0x3b9aca00) s4cjmp_s32 g0 ...
0F 85 E8 FF FF FF JNE L0
61 POPAD n0sysRet
C3 RET
-[Q]もっと短い機械語を生成しなくていいのか?
--[A]もちろんやりたいが、今は他を先に作るべきだと思ってい...
-[Q]・・・で、肝心の性能は?
--[A]Core-i7で実験した範囲では、gccで-O3したのと同じくら...
** もうちょっと細かい解説(1)
-基本的には以下のルールでコンパイルされている。
s2cp_s32 a b → MOV(EAX, b); MOV(a, EAX);
s2add_s32 a b c → MOV(EAX, b); ADD(EAX, c); MOV(a, E...
s4cjmp_s32 a b c d → MOV(EAX, a); CMP(EAX, b); jcc(d);
-見ての通りEAXしか使ってない。きわめてシンプルだ。
-ただしこれだけだと速度が出ない、なぜなら、
1: MOV(EAX, [EDI+8]);
2: INC(EAX);
3: MOV([EDI+8], EAX);
4: MOV(EAX, [EDI+8]);
5: CMP(EAX, 0x3b9aca00);
6: JNE(L0);
-のときに、3行目の書き込みが終わらないと4行目の読み込みが...
-ということで、JITコンパイラは不要な4行目を削除している(...
-EAXばかり使っていてもCPUはおそらくちゃんと依存関係を理解...
** もうちょっと細かい解説(2)
-レジスタ変数: zx:f0, zy:f1, xx:f2, yy:f3, tmp:f4, tx:f4...
1: s3mul_f64 f2 f0 f0 xx = zx * zx
2: s3mul_f64 f3 f1 f1 yy = zy * zy
3: s3add_f64 f4 f3 f2 tmp = yy + xx
4: s4cjmp_f64 f4 c4.0 5 L5 if (tmp > 4) goto L5
5: s3sub_f64 f4 f2 f3 tx = xx - yy
6: s3mul_f64 f5 f0 f1 ty = zx * zy * 2.0
7: s3add_f64 f5 f5 f5
8: s3add_f64 f0 f4 g8 zx = tx + cx
9: s3add_f64 f1 f5 g9 zy = ty + cy
-このコードから以下のバイナリを生成する(でもここでは機械...
01: FLD ST(0) // f0
02: FMUL ST(1) // f0
03: FSTP ST(3) // f2
04: FLD ST(1) // f1
05: FMUL ST(2) // f1
06: FSTP ST(4) // f3
07: FLD ST(3) // f3
08: FADD ST(3) // f2
09: FSTP ST(5) // f4
10: FLD ST(4) // f4
11: FCOMP [...] // 4.0
12: FNSTSW AX
13: SAHF
14: JA L5
(以下略)
-ここでEssenRev2のJIT00程度でも、以下の最適化が可能だと思...
--06行目をFSTに変更し、07行目を省略する
--09行目をFSTに変更し、10行目を省略する
-このようにレジスタ内で演算するようにすると、CPUは依存関...
終了行:
* Essen Rev2 JIT00
-(by [[K]], 2017.07.31)
** JIT00で提供する機能
-「即値が使えない命令」のような例外をなくす
-ラベルを使えるようにする
-CPUに依存するレイヤをここに集約する(JIT01以降はCPUに依...
-実際のCPUのレジスタ数がいくつであるかなどの制約を受けず...
** 基本仕様
-c# : 即値
-l# : ローカル変数(#=0~)
-g# : グローバル変数
-L# : 分岐先指定などに使うラベル
-p# : ポインタレジスタ(p0~p63)
-i# : s32以上レジスタ(i0~i63)
-f# : f64以上レジスタ(f0~f63)
-ローカル変数、グローバル変数には、どんな型の値でも代入で...
-ポインタレジスタはポインタしか代入できない。
-s32以上レジスタは整数しか代入できない。
-f64以上レジスタは浮動小数点しか代入できない。
-p#, i#, f#はグローバル変数で、これをうまく使いこなせるか...
-基本構文
命令 パラメータ1 パラメータ2 ...
-人間にとって書きやすい構文にしようとしていない。どうせこ...
--だからコメントやマクロなどはない。
-パラメータはスペース区切り(コンマはいらない)
-命令の命名規則
--最初の一文字はnかs。nはノーマル。sはスピード優先。
--二文字目はパラメータの数。
--末尾には型を表す接尾子が入る場合がある。
-例1:
n0sysEnt // JITコードの先頭に入れるべきコード...
s2cp_s32 g0 c0 // g0に定数0を代入
n1label L0 // ここをL0とする
s2add_s32 g0 g0 c1 // g0 += 1
s4cjmp_s32 g0 c1000000000 1 L0 // 条件ジャンプ命令 if ...
n0sysRet // JITコードから帰る場合に入れるべき...
-[Q]人間が書くわけじゃない中間言語なのに、どうしてバイナ...
--[A]その意見には全面的に賛成します。まあひとまずはデバッ...
** 命令一覧
-システム命令
--n0sysEnt
--n0sysRet
--n0reg
---n0reg "ppif" みたいに使う。「可能であればp00,p01,i00,f...
-2項演算命令
--s2cp_s32
--s2cp_f64
--s2cnv_f64_s32
--s2cnv_s32_f64
--s2not_s32 // xor -1 で代用できるので、消すかもしれない.
--s2neg_s32 // mul -1 で代用できるので、消すかもしれない.
-3項演算命令
--s3or_s32
--s3xor_s32
--s3and_s32
--s3add_s32
--s3sub_s32
--s3mul_s32
--s3shl_s32
--s3shr_s32 (符号付き右シフト)
--s3div_s32
--s3mod_s32
--s3add_f64
--s3sub_f64
--s3mul_f64
--s3div_f64
-条件分岐命令など
--n1align
--n1label
--n1jmp
--n1call_ext
--s4cjmp_s32 (ポインタを使ったjmpは想定しない)
--s4cset_s32_s32
--s4cjmp_f64 (ポインタを使ったjmpは想定しない)
--s4cset_s32_f64
-ポインタ演算
--未設計
** x86(32bit)版の仕様
-こうでなければいけないということではないが、とりあえず最...
-変数は16バイト
--型(32bit)、補助属性(32bit)、値(最大64bit)
--値が64bitに収まらない場合や可変長の場合は、ポインタを入...
-EAX: テンポラリデータレジスタ
-EBP: ローカル変数のベース
-EBX, ESI, EDI, ECX, EDX: pかiを割り当てる
//-EAX: テンポラリデータレジスタ
//-EDI: グローバル変数のベース
//-EBP: ローカル変数のベース
//-ESI: ワークエリアのベース
//-EBX: p0
//-ECX: テンポラリポインタ(p1)
//-EDX: テンポラリ
//--p2~p31はワークエリア内にある
//--i0~i31はワークエリア内にある
//--f0~f5はFPUの中にあり、f6~f31はワークエリア内にある
-例1は以下のような機械語になる(2017.07.28時点)
60 PUSHAD n0sysEnt
BF E8 24 48 00 EDI=....
B8 00 00 00 00 EAX=0 s2cp_s32 g0 i0
89 87 08 00 00 00 [EDI+8]=EAX
n1label L0
8B 87 08 00 00 00 EAX=[EDI+8] s2add_s32 g0 ...
40 EAX++
89 87 08 00 00 00 [EDI+8]=EAX
3D 00 CA 9A 3B CMP(EAX,0x3b9aca00) s4cjmp_s32 g0 ...
0F 85 E8 FF FF FF JNE L0
61 POPAD n0sysRet
C3 RET
-[Q]もっと短い機械語を生成しなくていいのか?
--[A]もちろんやりたいが、今は他を先に作るべきだと思ってい...
-[Q]・・・で、肝心の性能は?
--[A]Core-i7で実験した範囲では、gccで-O3したのと同じくら...
** もうちょっと細かい解説(1)
-基本的には以下のルールでコンパイルされている。
s2cp_s32 a b → MOV(EAX, b); MOV(a, EAX);
s2add_s32 a b c → MOV(EAX, b); ADD(EAX, c); MOV(a, E...
s4cjmp_s32 a b c d → MOV(EAX, a); CMP(EAX, b); jcc(d);
-見ての通りEAXしか使ってない。きわめてシンプルだ。
-ただしこれだけだと速度が出ない、なぜなら、
1: MOV(EAX, [EDI+8]);
2: INC(EAX);
3: MOV([EDI+8], EAX);
4: MOV(EAX, [EDI+8]);
5: CMP(EAX, 0x3b9aca00);
6: JNE(L0);
-のときに、3行目の書き込みが終わらないと4行目の読み込みが...
-ということで、JITコンパイラは不要な4行目を削除している(...
-EAXばかり使っていてもCPUはおそらくちゃんと依存関係を理解...
** もうちょっと細かい解説(2)
-レジスタ変数: zx:f0, zy:f1, xx:f2, yy:f3, tmp:f4, tx:f4...
1: s3mul_f64 f2 f0 f0 xx = zx * zx
2: s3mul_f64 f3 f1 f1 yy = zy * zy
3: s3add_f64 f4 f3 f2 tmp = yy + xx
4: s4cjmp_f64 f4 c4.0 5 L5 if (tmp > 4) goto L5
5: s3sub_f64 f4 f2 f3 tx = xx - yy
6: s3mul_f64 f5 f0 f1 ty = zx * zy * 2.0
7: s3add_f64 f5 f5 f5
8: s3add_f64 f0 f4 g8 zx = tx + cx
9: s3add_f64 f1 f5 g9 zy = ty + cy
-このコードから以下のバイナリを生成する(でもここでは機械...
01: FLD ST(0) // f0
02: FMUL ST(1) // f0
03: FSTP ST(3) // f2
04: FLD ST(1) // f1
05: FMUL ST(2) // f1
06: FSTP ST(4) // f3
07: FLD ST(3) // f3
08: FADD ST(3) // f2
09: FSTP ST(5) // f4
10: FLD ST(4) // f4
11: FCOMP [...] // 4.0
12: FNSTSW AX
13: SAHF
14: JA L5
(以下略)
-ここでEssenRev2のJIT00程度でも、以下の最適化が可能だと思...
--06行目をFSTに変更し、07行目を省略する
--09行目をFSTに変更し、10行目を省略する
-このようにレジスタ内で演算するようにすると、CPUは依存関...
ページ名: