2009年09月04日
AndroidのユーザーランドをFPUを有効にしてリビルドする
これまで2回に渡ってDalvikVMのインタープリタの部分でFPU命令を使って高速化する変更方法を紹介しました。
残りのCの部分で書いてある部分もコンパイルオプションを変えればFPU命令を使うようになるはずです。ソースをながめてみるとsetjmpの部分でFPUレジスタが退避されていなかったので、そのソース修正も合わせて紹介します。
2009年11月のEclairのソースリリースでだいぶ状況が変わっています。こちらも参照してください。
setjmpの修正
setjmp関連でのFPUのレジスタの退避、復帰の部分がeabiのコーリングコンベンションとは違うかたちになっていたので以下のように修正します。
diff --git a/libc/arch-arm/bionic/_setjmp.S b/libc/arch-arm/bionic/_setjmp.S index 6a27af2..4103e1a 100644 --- a/libc/arch-arm/bionic/_setjmp.S +++ b/libc/arch-arm/bionic/_setjmp.S @@ -53,13 +53,13 @@ ENTRY(_setjmp) ldr r1, .L_setjmp_magic str r1, [r0], #4 #ifdef SOFTFLOAT - add r0, r0, #52 + add r0, r0, #68 #else - /* Store fp registers */ - sfm f4, 4, [r0], #48 /* Store fpsr */ - rfs r1 - str r1, [r0], #0x0004 + fmrx r1, fpscr + str r1, [r0], #4 + /* Store fp registers */ + fstmiad r0!, {d8-d15} #endif /* SOFTFLOAT */ /* Store integer registers */ stmia r0, {r4-r14} @@ -77,13 +77,13 @@ ENTRY(_longjmp) bne botch #ifdef SOFTFLOAT - add r0, r0, #52 + add r0, r0, #68 #else + /* Restore FPSR */ + ldr r1, [r0], #4 + fmxr fpscr, r1 /* Restore fp registers */ - lfm f4, 4, [r0], #48 - /* Restore fpsr */ - ldr r4, [r0], #0x0004 - wfs r4 + fldmiad r0!, {d8-d15} #endif /* SOFTFLOAT */ /* Restore integer registers */ ldmia r0, {r4-r14} diff --git a/libc/arch-arm/bionic/setjmp.S b/libc/arch-arm/bionic/setjmp.S index a9f6ea4..8903cdd 100644 --- a/libc/arch-arm/bionic/setjmp.S +++ b/libc/arch-arm/bionic/setjmp.S @@ -57,19 +57,19 @@ ENTRY(setjmp) ldmfd sp!, {r0, r14} /* Store signal mask */ - str r1, [r0, #(25 * 4)] + str r1, [r0, #(29 * 4)] ldr r1, .Lsetjmp_magic str r1, [r0], #4 #ifdef SOFTFLOAT - add r0, r0, #52 + add r0, r0, #68 #else - /* Store fp registers */ - sfm f4, 4, [r0], #48 /* Store fpsr */ - rfs r1 - str r1, [r0], #0x0004 + fmrx r1, fpscr + str r1, [r0], #4 + /* Store fp registers */ + fstmiad r0!, {d8-d15} #endif /*SOFTFLOAT*/ /* Store integer registers */ stmia r0, {r4-r14} @@ -87,7 +87,7 @@ ENTRY(longjmp) bne botch /* Fetch signal mask */ - ldr r2, [r0, #(25 * 4)] + ldr r2, [r0, #(29 * 4)] /* Set signal mask */ stmfd sp!, {r0, r1, r14} @@ -101,13 +101,13 @@ ENTRY(longjmp) add r0, r0, #4 #ifdef SOFTFLOAT - add r0, r0, #52 + add r0, r0, #68 #else - /* Restore fp registers */ - lfm f4, 4, [r0], #48 /* Restore FPSR */ - ldr r4, [r0], #0x0004 - wfs r4 + ldr r1, [r0], #4 + fmxr fpscr, r1 + /* Restore fp registers */ + fldmiad r0!, {d8-d15} #endif /* SOFTFLOAT */ /* Restore integer registers */ ldmia r0, {r4-r14} diff --git a/libc/arch-arm/include/machine/setjmp.h b/libc/arch-arm/include/machine/setjmp.h index f20cab2..ce79d03 100644 --- a/libc/arch-arm/include/machine/setjmp.h +++ b/libc/arch-arm/include/machine/setjmp.h @@ -5,11 +5,8 @@ * machine/setjmp.h: machine dependent setjmp-related information. */ -#ifdef __ELF__ #define _JBLEN 64 /* size, in longs, of a jmp_buf */ -#else -#define _JBLEN 29 /* size, in longs, of a jmp_buf */ -#endif + /* * NOTE: The internal structure of a jmp_buf is *PRIVATE* @@ -65,23 +62,28 @@ /* Valid for all jmp_buf's */ #define _JB_MAGIC 0 -#define _JB_REG_F4 1 -#define _JB_REG_F5 4 -#define _JB_REG_F6 7 -#define _JB_REG_F7 10 -#define _JB_REG_FPSR 13 -#define _JB_REG_R4 14 -#define _JB_REG_R5 15 -#define _JB_REG_R6 16 -#define _JB_REG_R7 17 -#define _JB_REG_R8 18 -#define _JB_REG_R9 19 -#define _JB_REG_R10 20 -#define _JB_REG_R11 21 -#define _JB_REG_R12 22 -#define _JB_REG_R13 23 -#define _JB_REG_R14 24 +#define _JB_REG_FPSR 1 +#define _JB_REG_D8 2 +#define _JB_REG_D9 4 +#define _JB_REG_D10 6 +#define _JB_REG_D11 8 +#define _JB_REG_D12 10 +#define _JB_REG_D13 12 +#define _JB_REG_D14 14 +#define _JB_REG_D15 16 + +#define _JB_REG_R4 18 +#define _JB_REG_R5 19 +#define _JB_REG_R6 20 +#define _JB_REG_R7 21 +#define _JB_REG_R8 22 +#define _JB_REG_R9 23 +#define _JB_REG_R10 24 +#define _JB_REG_R11 25 +#define _JB_REG_R12 26 +#define _JB_REG_R13 27 +#define _JB_REG_R14 28 /* Only valid with the _JB_MAGIC_SETJMP magic */ -#define _JB_SIGMASK 25 +#define _JB_SIGMASK 29
それから、条件コンパイルで常にSOFTFLOATが有効になっていたので、FPUレジスタの退避、復帰の部分がはずれていました。
本来ならばコンパイルオプションに連動するように変更するべきですが、今回はとりあえず無条件にはずします。
diff --git a/libc/Android.mk b/libc/Android.mk index 59a4c6b..ca6fa36 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -352,7 +352,6 @@ libc_common_cflags := \ -DUSE_LOCKS \ -DREALLOC_ZERO_BYTES_FREES \ -D_LIBC=1 \ - -DSOFTFLOAT \ -DFLOATING_POINT \ -DNEED_PSELECT=1 \ -DINET6 \
コンパイルオプションの変更
コンパイルオプションでsoft-floatを指定しているところをvfpを使うように変更します。
diff --git a/core/combo/linux-arm.mk b/core/combo/linux-arm.mk index 11a8ac7..46d0ccd 100644 --- a/core/combo/linux-arm.mk +++ b/core/combo/linux-arm.mk @@ -110,8 +110,18 @@ endif android_config_h := $(call select-android-config-h,linux-arm) arch_include_dir := $(dir $(android_config_h)) $(combo_target)GLOBAL_CFLAGS += \ - -msoft-float -fpic \ + -mhard-float -mfloat-abi=softfp -mfpu=vfp -fpic \ -ffunction-sections \ -funwind-tables \ -fstack-protector \
これでトップディレクトリからクリーンビルドすればFPU命令を使用するユーザーランドがビルドできます。
qemuの変更
これをエミュレータで動かすには前回紹介したqemuへのパッチが必要になりますから、忘れずに変更してください。これをいれないとバスエラーが発生します。
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index 36de55b..41219f6 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -70,7 +70,7 @@ uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, static void do_unaligned_access (target_ulong addr, int is_write, int is_user, void *retaddr); #define MMUSUFFIX _mmu -#define ALIGNED_ONLY 1 +/*#define ALIGNED_ONLY 1*/ #define SHIFT 0 #include "softmmu_template.h"
まとめ
3回に渡ってAndroidでFPUを使って高速化する方法を紹介しました。
FPU付きの実機にAndroidを移植して動かしている方はぜひ試してみてください。速度性能評価などをトラックバックしてくれたら嬉しいです。
また、インタープリタにはまだ高速化の余地が残されています。どなたか続きに挑戦してみてください。