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%
This commit is contained in:
parent
67d5358e2a
commit
4dc1fa8e8d
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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...
|
||||
// -----------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -18,9 +18,10 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <cutils/log.h>
|
||||
|
||||
#include "codeflinger/GGLAssembler.h"
|
||||
|
||||
#include <machine/cpu-features.h>
|
||||
|
||||
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<<maskLen)-1;
|
||||
if ((h == bits) && !l && (s != d.reg)) {
|
||||
MOV(AL, 0, d.reg, s); // component = packed;
|
||||
} else if ((h == bits) && l) {
|
||||
MOV(AL, 0, d.reg, reg_imm(s, LSR, l)); // component = packed >> 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<<maskLen)-1) << l;
|
||||
if (isValidImmediate(mask)) {
|
||||
|
@ -132,6 +147,7 @@ void GGLAssembler::extract(integer_t& d, int s, int h, int l, int bits)
|
|||
if (s != d.reg) {
|
||||
MOV(AL, 0, d.reg, s);
|
||||
}
|
||||
#endif
|
||||
|
||||
d.s = maskLen;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue