a21_txt02_5a
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
* 「10日くらいでできる!プログラミング言語自作入門」の続...
-(by [[K]], 2021.04.27)
** (1) HL-15a
-HL-15まででは、整数の定数があってもそれはすべて変数扱い...
-[1]optimizerX86()関数を以下のものと差し替え
unsigned char *icq0, *icq1, *icqSet;
int isConst(int i)
{
if ('0' <= ts[i][0] && ts[i][0] <= '9') return 1;
return 0;
}
int isConstM(unsigned char *p)
{
if ((*p & 0xc7) != 0x05) return 0;
return isConst(((AInt *) get32(p + 1)) - var);
}
int getConstM(unsigned char *p)
{
return *((AInt *) get32(p + 1));
}
void putIcX86(String s, IntP p0, IntP p1, IntP p2, IntP ...
void optimizerX86()
{
int i;
if (icq0 != icq) {
if (icq0[0] == 0x0f && 0x90 <= icq0[1] && icq0[1...
icqSet = icq0;
}
+ if (icq0[0] == 0x8b && isConstM(&icq0[1])) { // ...
+ int reg = (icq0[1] >> 3) & 7, i = getConstM(...
+ icq = icq0;
+ if (i == 0) { putIcX86("31_%0c", (IntP) (reg...
+ else { putIcX86("%0c_%1i", (IntP) (re...
+ }
+ if (icq0[0] <= 0x3f && (icq0[0] & 7) == 3 && isC...
+ int reg = (icq0[1] >> 3) & 7, i = getConstM(...
+ icq = icq0;
+ if (-0x80 <= i && i <= 0x7f) { putIcX86("83_...
+ else { putIcX86("81_...
+ }
+ if (icq0[0] == 0x0f && icq0[1] == 0xaf && isCons...
+ int reg = (icq0[2] >> 3) & 7, i = getConstM(...
+ icq = icq0;
+ if (-0x80 <= i && i <= 0x7f) { putIcX86("6b_...
+ else { putIcX86("69_...
+ }
+ if (icq0[0] == 0x83 && (icq0[1] & 0xf8) == 0xc0 ...
+ icq = icq0;
+ putIcX86("%0c", (IntP) ((icq0[1] & 7) + 0x40...
+ }
+ if (icq0[0] == 0x83 && (icq0[1] & 0xf8) == 0xe8 ...
+ icq = icq0;
+ putIcX86("%0c", (IntP) ((icq0[1] & 7) + 0x48...
+ }
+ if (icq0[0] == 0x83 && (icq0[1] & 0xf8) == 0xf8 ...
+ icq = icq0;
+ putIcX86("85_%0c", (IntP) ((icq0[1] & 7) * 9...
+ }
if (icq0[0] == 0x8b && icq1 != 0 && icq1[0] == 0...
icq = icq0; // 8b命令は削除.
i = (IntP) get32(icq1 + 2) - var;
if (TcTmp0 <= i && i <= TcTmp9) {
icq = icq1; // 89命令も削除.
}
}
icq1 = icq0;
icq0 = icq;
}
if (icqSet + 14 == icq && memcmp(&icqSet[2], "\xc0\x...
memcpy(&icqSet[2], &icqSet[10], 4);
icqSet[1] -= 0x10; // SETcc → Jcc.
if (icqSet[9] == 0x84) {
icqSet[1] ^= 1; // 条件反転.
}
icq0 = icq = icqSet + 6;
icq1 = icqSet = 0;
jmps[jp - 1] = icq - 4 - ic;
}
}
-[2]defLabel()関数を以下のものと差し替え
int align;
void defLabel(int i)
{
+ if (align > 0) {
+ int j = (icq - ic) & 15; // 0-15.
+ if (j > 0 && j <= 7) {
+ putIcX86("66_0f_1f_84_00_00_00_00_00", 0, 0,...
+ j = (j + 9) & 15;
+ }
+ if (j > 0) { // 8-15.
+ static char *table[8] = {
+ "0f_1f_84_00_00_00_00_00", "0f_1f_80_00_...
+ "66_0f_1f_44_00_00", "0f_1f_44_00_00", "...
+ };
+ putIcX86(table[j - 8], 0, 0, 0, 0);
+ }
+ align--;
+ }
var[i] = icq - ic;
icq1 = icqSet = 0;
}
-[3]compile()関数に以下を追加
+ } else if (phrCmp(39, "align();", pc)) {
+ align = 1;
+ } else if (phrCmp(40, "align(!!*0);", pc)) {
+ align = var[tc[wpc[0]]];
----
-以上すべての改造を終えると、プログラムは1012行になります。
** (2) プログラムの説明#1
-isConst()関数
int isConst(int i)
{
if ('0' <= ts[i][0] && ts[i][0] <= '9') return 1;
return 0;
}
--これは、トークンコード(トークン番号)を渡すと、それが...
-isConstM()関数
int isConstM(unsigned char *p)
{
if ((*p & 0xc7) != 0x05) return 0;
return isConst(((AInt *) get32(p + 1)) - var);
}
--これは%mの部分のポインタを渡すと、その引数が定数を指し...
-getConstM()関数
int getConstM(unsigned char *p)
{
return *((AInt *) get32(p + 1));
}
--定数だった場合に、その定数値を受け取ります。
----
-optimizerX86()関数の中(8b用)
+ if (icq0[0] == 0x8b && isConstM(&icq0[1])) { // ...
+ int reg = (icq0[1] >> 3) & 7, i = getConstM(...
+ icq = icq0;
+ if (i == 0) { putIcX86("31_%0c", (IntP) (reg...
+ else { putIcX86("%0c_%1i", (IntP) (re...
+ }
--これは例えば「a = 0;」をHL-15でコンパイルすると「8b_05_...
--[最適化対象例] 8b_05_1c_0a_42_00
--[最適化結果例#1] 31_c0 (定数=0の場合)
--[最適化結果例#2] b8_??_??_??_?? (それ以外の場合)
-optimizerX86()関数の中(03~3b用)
+ if (icq0[0] <= 0x3f && (icq0[0] & 7) == 3 && isC...
+ int reg = (icq0[1] >> 3) & 7, i = getConstM(...
+ icq = icq0;
+ if (-0x80 <= i && i <= 0x7f) { putIcX86("83_...
+ else { putIcX86("81_...
+ }
--これは例えば「a = b + 2;」をHL-15でコンパイルすると「8b...
--[最適化対象例] 03_05_24_0a_42_00
--[最適化結果例#1] 83_c0_?? (定数=-128~+127の場合)
--[最適化結果例#2] 81_c0_??_??_??_?? (それ以外の場合)
-optimizerX86()関数の中(0f_af用)
+ if (icq0[0] == 0x0f && icq0[1] == 0xaf && isCons...
+ int reg = (icq0[2] >> 3) & 7, i = getConstM(...
+ icq = icq0;
+ if (-0x80 <= i && i <= 0x7f) { putIcX86("6b_...
+ else { putIcX86("69_...
+ }
--これは例えば「a = b * 12;」をHL-15でコンパイルすると「8...
--[最適化対象例] 0f_af_05_34_0b_42_00
--[最適化結果例#1] 6b_c0_?? (定数=-128~+127の場合)
--[最適化結果例#2] 69_c0_??_??_??_?? (それ以外の場合)
-optimizerX86()関数の中(さらに最適化)
+ if (icq0[0] == 0x83 && (icq0[1] & 0xf8) == 0xc0 ...
+ icq = icq0;
+ putIcX86("%0c", (IntP) ((icq0[1] & 7) + 0x40...
+ }
+ if (icq0[0] == 0x83 && (icq0[1] & 0xf8) == 0xe8 ...
+ icq = icq0;
+ putIcX86("%0c", (IntP) ((icq0[1] & 7) + 0x48...
+ }
+ if (icq0[0] == 0x83 && (icq0[1] & 0xf8) == 0xf8 ...
+ icq = icq0;
+ putIcX86("85_%0c", (IntP) ((icq0[1] & 7) * 9...
+ }
--これらは、以下のような最適化をします。
--「83_c0_01;」→「40;」(ADD 1 → INC)
--「83_e8_01;」→「48;」(SUB 1 → DEC)
--「83_f8_00;」→「85_c0;」(CMP 0 → TEST)
** (3) プログラムの説明#2
-基本的にはこれだけで十分に良いのですが、なんとそれだけだ...
-これは実は命令長が短くなってしまったせいで、分岐先のアド...
-それはあまりにも悲しいので、命令が短くなりすぎて速度が出...
-align命令でアライン機能が有効な時は、defLabel()するとき...
-x86のアライン用のNOP命令
|1バイトのNOP|90;|
|2バイトのNOP|66_90;|
|3バイトのNOP|0f_1f_00;|
|4バイトのNOP|0f_1f_40_00;|
|5バイトのNOP|0f_1f_44_00_00;|
|6バイトのNOP|66_0f_1f_44_00_00;|
|7バイトのNOP|0f_1f_80_00_00_00_00;|
|8バイトのNOP|0f_1f_84_00_00_00_00_00;|
|9バイトのNOP|66_0f_1f_84_00_00_00_00_00;|
-align()命令では、カッコ内に数値を書かなければ、次の1つの...
-10億回ループのプログラムをrunする前に、align(100);とかを...
** (4) 成果の比較
-上記みたいなのはすごく特別でレアケースなのか、それともよ...
-サイズが小さくなったからいいとか悪いとかではなく、「サイ...
||HL-13a|HL-14|HL-14a|HL-15|HL-15a|
|mandel.c|RIGHT:1087|RIGHT:1007|RIGHT:942|RIGHT:768|RIGHT...
|maze.c|RIGHT:2192|RIGHT:2192|RIGHT:2192|RIGHT:1770|RIGHT...
|kcube.c|RIGHT:4623|RIGHT:4623|RIGHT:4623|RIGHT:3695|RIGH...
|invader.c|RIGHT:3260|RIGHT:3260|RIGHT:3260|RIGHT:2750|RI...
** 次回に続く
-次回: [[a21_txt02_6]]
*こめんと欄
#comment
終了行:
* 「10日くらいでできる!プログラミング言語自作入門」の続...
-(by [[K]], 2021.04.27)
** (1) HL-15a
-HL-15まででは、整数の定数があってもそれはすべて変数扱い...
-[1]optimizerX86()関数を以下のものと差し替え
unsigned char *icq0, *icq1, *icqSet;
int isConst(int i)
{
if ('0' <= ts[i][0] && ts[i][0] <= '9') return 1;
return 0;
}
int isConstM(unsigned char *p)
{
if ((*p & 0xc7) != 0x05) return 0;
return isConst(((AInt *) get32(p + 1)) - var);
}
int getConstM(unsigned char *p)
{
return *((AInt *) get32(p + 1));
}
void putIcX86(String s, IntP p0, IntP p1, IntP p2, IntP ...
void optimizerX86()
{
int i;
if (icq0 != icq) {
if (icq0[0] == 0x0f && 0x90 <= icq0[1] && icq0[1...
icqSet = icq0;
}
+ if (icq0[0] == 0x8b && isConstM(&icq0[1])) { // ...
+ int reg = (icq0[1] >> 3) & 7, i = getConstM(...
+ icq = icq0;
+ if (i == 0) { putIcX86("31_%0c", (IntP) (reg...
+ else { putIcX86("%0c_%1i", (IntP) (re...
+ }
+ if (icq0[0] <= 0x3f && (icq0[0] & 7) == 3 && isC...
+ int reg = (icq0[1] >> 3) & 7, i = getConstM(...
+ icq = icq0;
+ if (-0x80 <= i && i <= 0x7f) { putIcX86("83_...
+ else { putIcX86("81_...
+ }
+ if (icq0[0] == 0x0f && icq0[1] == 0xaf && isCons...
+ int reg = (icq0[2] >> 3) & 7, i = getConstM(...
+ icq = icq0;
+ if (-0x80 <= i && i <= 0x7f) { putIcX86("6b_...
+ else { putIcX86("69_...
+ }
+ if (icq0[0] == 0x83 && (icq0[1] & 0xf8) == 0xc0 ...
+ icq = icq0;
+ putIcX86("%0c", (IntP) ((icq0[1] & 7) + 0x40...
+ }
+ if (icq0[0] == 0x83 && (icq0[1] & 0xf8) == 0xe8 ...
+ icq = icq0;
+ putIcX86("%0c", (IntP) ((icq0[1] & 7) + 0x48...
+ }
+ if (icq0[0] == 0x83 && (icq0[1] & 0xf8) == 0xf8 ...
+ icq = icq0;
+ putIcX86("85_%0c", (IntP) ((icq0[1] & 7) * 9...
+ }
if (icq0[0] == 0x8b && icq1 != 0 && icq1[0] == 0...
icq = icq0; // 8b命令は削除.
i = (IntP) get32(icq1 + 2) - var;
if (TcTmp0 <= i && i <= TcTmp9) {
icq = icq1; // 89命令も削除.
}
}
icq1 = icq0;
icq0 = icq;
}
if (icqSet + 14 == icq && memcmp(&icqSet[2], "\xc0\x...
memcpy(&icqSet[2], &icqSet[10], 4);
icqSet[1] -= 0x10; // SETcc → Jcc.
if (icqSet[9] == 0x84) {
icqSet[1] ^= 1; // 条件反転.
}
icq0 = icq = icqSet + 6;
icq1 = icqSet = 0;
jmps[jp - 1] = icq - 4 - ic;
}
}
-[2]defLabel()関数を以下のものと差し替え
int align;
void defLabel(int i)
{
+ if (align > 0) {
+ int j = (icq - ic) & 15; // 0-15.
+ if (j > 0 && j <= 7) {
+ putIcX86("66_0f_1f_84_00_00_00_00_00", 0, 0,...
+ j = (j + 9) & 15;
+ }
+ if (j > 0) { // 8-15.
+ static char *table[8] = {
+ "0f_1f_84_00_00_00_00_00", "0f_1f_80_00_...
+ "66_0f_1f_44_00_00", "0f_1f_44_00_00", "...
+ };
+ putIcX86(table[j - 8], 0, 0, 0, 0);
+ }
+ align--;
+ }
var[i] = icq - ic;
icq1 = icqSet = 0;
}
-[3]compile()関数に以下を追加
+ } else if (phrCmp(39, "align();", pc)) {
+ align = 1;
+ } else if (phrCmp(40, "align(!!*0);", pc)) {
+ align = var[tc[wpc[0]]];
----
-以上すべての改造を終えると、プログラムは1012行になります。
** (2) プログラムの説明#1
-isConst()関数
int isConst(int i)
{
if ('0' <= ts[i][0] && ts[i][0] <= '9') return 1;
return 0;
}
--これは、トークンコード(トークン番号)を渡すと、それが...
-isConstM()関数
int isConstM(unsigned char *p)
{
if ((*p & 0xc7) != 0x05) return 0;
return isConst(((AInt *) get32(p + 1)) - var);
}
--これは%mの部分のポインタを渡すと、その引数が定数を指し...
-getConstM()関数
int getConstM(unsigned char *p)
{
return *((AInt *) get32(p + 1));
}
--定数だった場合に、その定数値を受け取ります。
----
-optimizerX86()関数の中(8b用)
+ if (icq0[0] == 0x8b && isConstM(&icq0[1])) { // ...
+ int reg = (icq0[1] >> 3) & 7, i = getConstM(...
+ icq = icq0;
+ if (i == 0) { putIcX86("31_%0c", (IntP) (reg...
+ else { putIcX86("%0c_%1i", (IntP) (re...
+ }
--これは例えば「a = 0;」をHL-15でコンパイルすると「8b_05_...
--[最適化対象例] 8b_05_1c_0a_42_00
--[最適化結果例#1] 31_c0 (定数=0の場合)
--[最適化結果例#2] b8_??_??_??_?? (それ以外の場合)
-optimizerX86()関数の中(03~3b用)
+ if (icq0[0] <= 0x3f && (icq0[0] & 7) == 3 && isC...
+ int reg = (icq0[1] >> 3) & 7, i = getConstM(...
+ icq = icq0;
+ if (-0x80 <= i && i <= 0x7f) { putIcX86("83_...
+ else { putIcX86("81_...
+ }
--これは例えば「a = b + 2;」をHL-15でコンパイルすると「8b...
--[最適化対象例] 03_05_24_0a_42_00
--[最適化結果例#1] 83_c0_?? (定数=-128~+127の場合)
--[最適化結果例#2] 81_c0_??_??_??_?? (それ以外の場合)
-optimizerX86()関数の中(0f_af用)
+ if (icq0[0] == 0x0f && icq0[1] == 0xaf && isCons...
+ int reg = (icq0[2] >> 3) & 7, i = getConstM(...
+ icq = icq0;
+ if (-0x80 <= i && i <= 0x7f) { putIcX86("6b_...
+ else { putIcX86("69_...
+ }
--これは例えば「a = b * 12;」をHL-15でコンパイルすると「8...
--[最適化対象例] 0f_af_05_34_0b_42_00
--[最適化結果例#1] 6b_c0_?? (定数=-128~+127の場合)
--[最適化結果例#2] 69_c0_??_??_??_?? (それ以外の場合)
-optimizerX86()関数の中(さらに最適化)
+ if (icq0[0] == 0x83 && (icq0[1] & 0xf8) == 0xc0 ...
+ icq = icq0;
+ putIcX86("%0c", (IntP) ((icq0[1] & 7) + 0x40...
+ }
+ if (icq0[0] == 0x83 && (icq0[1] & 0xf8) == 0xe8 ...
+ icq = icq0;
+ putIcX86("%0c", (IntP) ((icq0[1] & 7) + 0x48...
+ }
+ if (icq0[0] == 0x83 && (icq0[1] & 0xf8) == 0xf8 ...
+ icq = icq0;
+ putIcX86("85_%0c", (IntP) ((icq0[1] & 7) * 9...
+ }
--これらは、以下のような最適化をします。
--「83_c0_01;」→「40;」(ADD 1 → INC)
--「83_e8_01;」→「48;」(SUB 1 → DEC)
--「83_f8_00;」→「85_c0;」(CMP 0 → TEST)
** (3) プログラムの説明#2
-基本的にはこれだけで十分に良いのですが、なんとそれだけだ...
-これは実は命令長が短くなってしまったせいで、分岐先のアド...
-それはあまりにも悲しいので、命令が短くなりすぎて速度が出...
-align命令でアライン機能が有効な時は、defLabel()するとき...
-x86のアライン用のNOP命令
|1バイトのNOP|90;|
|2バイトのNOP|66_90;|
|3バイトのNOP|0f_1f_00;|
|4バイトのNOP|0f_1f_40_00;|
|5バイトのNOP|0f_1f_44_00_00;|
|6バイトのNOP|66_0f_1f_44_00_00;|
|7バイトのNOP|0f_1f_80_00_00_00_00;|
|8バイトのNOP|0f_1f_84_00_00_00_00_00;|
|9バイトのNOP|66_0f_1f_84_00_00_00_00_00;|
-align()命令では、カッコ内に数値を書かなければ、次の1つの...
-10億回ループのプログラムをrunする前に、align(100);とかを...
** (4) 成果の比較
-上記みたいなのはすごく特別でレアケースなのか、それともよ...
-サイズが小さくなったからいいとか悪いとかではなく、「サイ...
||HL-13a|HL-14|HL-14a|HL-15|HL-15a|
|mandel.c|RIGHT:1087|RIGHT:1007|RIGHT:942|RIGHT:768|RIGHT...
|maze.c|RIGHT:2192|RIGHT:2192|RIGHT:2192|RIGHT:1770|RIGHT...
|kcube.c|RIGHT:4623|RIGHT:4623|RIGHT:4623|RIGHT:3695|RIGH...
|invader.c|RIGHT:3260|RIGHT:3260|RIGHT:3260|RIGHT:2750|RI...
** 次回に続く
-次回: [[a21_txt02_6]]
*こめんと欄
#comment
ページ名: