From 4dc1fa8e8d1f14868ab8bba93a8cbb87f847c4e3 Mon Sep 17 00:00:00 2001 From: Martyn Capewell Date: Fri, 4 Dec 2009 16:44:58 +0000 Subject: [PATCH] Adds support for UBFX to JIT and Disassembler This introduces UBFX instruction generation abilities to the Pixelflinger JIT, and also modifies the component extraction function to generate the instruction. The extract function contains defines to prevent generation of UBFX on pre-v7 cores. The JIT itself retains the ability to produce the instruction even on v5/6. This patch only generates UBFX when MOV, AND or BIC can't be used. Based on the TRM, this appears to be faster on A9 than using UBFX in all cases. On startup, Pixelflinger JITs three chunks of code. UBFX improves these as follows: 00000077:03515104_00000000_00000000 (Blends a single colour into an RGB565 buffer.) Before: 27 inst/pixel, After: 24 inst/pixel, Improvement: 12.5% 00000077:03545404_00000A01_00000000 (Blends RGBA8888 texture into an RGB565 buffer using alpha.) Before: 30 inst/pixel, After: 27 inst/pixel, Improvement: 11.1% 00000077:03545404_00000A04_00000000 (Blends RGB565 texture into an RGB565 buffer using alpha.) Before: 29 inst/pixel, After: 27 inst/pixel, Improvement: 7.4% --- libpixelflinger/codeflinger/ARMAssembler.cpp | 10 ++++++++++ libpixelflinger/codeflinger/ARMAssembler.h | 1 + .../codeflinger/ARMAssemblerInterface.h | 3 +++ .../codeflinger/ARMAssemblerProxy.cpp | 4 ++++ .../codeflinger/ARMAssemblerProxy.h | 1 + libpixelflinger/codeflinger/disassem.c | 11 +++++++++++ libpixelflinger/codeflinger/load_store.cpp | 18 +++++++++++++++++- 7 files changed, 47 insertions(+), 1 deletion(-) diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp index d3720c3ee..fa9f1ade8 100644 --- a/libpixelflinger/codeflinger/ARMAssembler.cpp +++ b/libpixelflinger/codeflinger/ARMAssembler.cpp @@ -433,6 +433,16 @@ void ARMAssembler::UXTB16(int cc, int Rd, int Rm, int rotate) { *mPC++ = (cc<<28) | 0x6CF0070 | (Rd<<12) | ((rotate >> 3) << 10) | Rm; } +#if 0 +#pragma mark - +#pragma mark Bit manipulation (ARMv7+ only)... +#endif + +// Bit manipulation (ARMv7+ only)... +void ARMAssembler::UBFX(int cc, int Rd, int Rn, int lsb, int width) +{ + *mPC++ = (cc<<28) | 0x7E00000 | ((width-1)<<16) | (Rd<<12) | (lsb<<7) | 0x50 | Rn; +} }; // namespace android diff --git a/libpixelflinger/codeflinger/ARMAssembler.h b/libpixelflinger/codeflinger/ARMAssembler.h index a667cb511..e7f038ae4 100644 --- a/libpixelflinger/codeflinger/ARMAssembler.h +++ b/libpixelflinger/codeflinger/ARMAssembler.h @@ -124,6 +124,7 @@ public: virtual void SMLAW(int cc, int y, int Rd, int Rm, int Rs, int Rn); virtual void UXTB16(int cc, int Rd, int Rm, int rotate); + virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width); private: ARMAssembler(const ARMAssembler& rhs); diff --git a/libpixelflinger/codeflinger/ARMAssemblerInterface.h b/libpixelflinger/codeflinger/ARMAssemblerInterface.h index ff6af2a22..796342a06 100644 --- a/libpixelflinger/codeflinger/ARMAssemblerInterface.h +++ b/libpixelflinger/codeflinger/ARMAssemblerInterface.h @@ -206,6 +206,9 @@ public: // byte/half word extract... virtual void UXTB16(int cc, int Rd, int Rm, int rotate) = 0; + // bit manipulation... + virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width) = 0; + // ----------------------------------------------------------------------- // convenience... // ----------------------------------------------------------------------- diff --git a/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp b/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp index 7c422dbad..c57d7daa9 100644 --- a/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp +++ b/libpixelflinger/codeflinger/ARMAssemblerProxy.cpp @@ -199,5 +199,9 @@ void ARMAssemblerProxy::UXTB16(int cc, int Rd, int Rm, int rotate) { mTarget->UXTB16(cc, Rd, Rm, rotate); } +void ARMAssemblerProxy::UBFX(int cc, int Rd, int Rn, int lsb, int width) { + mTarget->UBFX(cc, Rd, Rn, lsb, width); +} + }; // namespace android diff --git a/libpixelflinger/codeflinger/ARMAssemblerProxy.h b/libpixelflinger/codeflinger/ARMAssemblerProxy.h index 9134cce6f..8c7f2707f 100644 --- a/libpixelflinger/codeflinger/ARMAssemblerProxy.h +++ b/libpixelflinger/codeflinger/ARMAssemblerProxy.h @@ -115,6 +115,7 @@ public: int Rd, int Rm, int Rs, int Rn); virtual void UXTB16(int cc, int Rd, int Rm, int rotate); + virtual void UBFX(int cc, int Rd, int Rn, int lsb, int width); private: ARMAssemblerInterface* mTarget; diff --git a/libpixelflinger/codeflinger/disassem.c b/libpixelflinger/codeflinger/disassem.c index c17f3ecc1..aeb80340a 100644 --- a/libpixelflinger/codeflinger/disassem.c +++ b/libpixelflinger/codeflinger/disassem.c @@ -81,6 +81,8 @@ * g - 2nd fp operand (register) (bits 16-18) * h - 3rd fp operand (register/immediate) (bits 0-4) * j - xtb rotate literal (bits 10-11) + * i - bfx lsb literal (bits 7-11) + * w - bfx width literal (bits 16-20) * b - branch address * t - thumb branch address (bits 24, 0-23) * k - breakpoint comment (bits 0-3, 8-19) @@ -124,6 +126,7 @@ static const struct arm32_insn arm32_i[] = { { 0x0fe000f0, 0x00a00090, "umlal", "Sdnms" }, { 0x0fe000f0, 0x00e00090, "smlal", "Sdnms" }, { 0x0fff03f0, 0x06cf0070, "uxtb16", "dmj" }, + { 0x0fe00070, 0x07e00050, "ubfx", "dmiw" }, { 0x0d700000, 0x04200000, "strt", "daW" }, { 0x0d700000, 0x04300000, "ldrt", "daW" }, { 0x0d700000, 0x04600000, "strbt", "daW" }, @@ -412,6 +415,14 @@ disasm(const disasm_interface_t *di, u_int loc, int altfmt) case 'j': di->di_printf("ror #%d", ((insn >> 10) & 3) << 3); break; + /* i - bfx lsb literal (bits 7-11) */ + case 'i': + di->di_printf("#%d", (insn >> 7) & 31); + break; + /* w - bfx width literal (bits 16-20) */ + case 'w': + di->di_printf("#%d", 1 + ((insn >> 16) & 31)); + break; /* b - branch address */ case 'b': branch = ((insn << 2) & 0x03ffffff); diff --git a/libpixelflinger/codeflinger/load_store.cpp b/libpixelflinger/codeflinger/load_store.cpp index 93c582579..023381c72 100644 --- a/libpixelflinger/codeflinger/load_store.cpp +++ b/libpixelflinger/codeflinger/load_store.cpp @@ -18,9 +18,10 @@ #include #include #include - #include "codeflinger/GGLAssembler.h" +#include + namespace android { // ---------------------------------------------------------------------------- @@ -110,6 +111,20 @@ void GGLAssembler::extract(integer_t& d, int s, int h, int l, int bits) assert(maskLen<=8); assert(h); +#if __ARM_ARCH__ >= 7 + const int mask = (1<> l; + } else if (!l && isValidImmediate(mask)) { + AND(AL, 0, d.reg, s, imm(mask)); // component = packed & mask; + } else if (!l && isValidImmediate(~mask)) { + BIC(AL, 0, d.reg, s, imm(~mask)); // component = packed & mask; + } else { + UBFX(AL, d.reg, s, l, maskLen); // component = (packed & mask) >> l; + } +#else if (h != bits) { const int mask = ((1<