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:
Martyn Capewell 2009-12-04 16:44:58 +00:00 committed by Dave Butcher
parent 67d5358e2a
commit 4dc1fa8e8d
7 changed files with 47 additions and 1 deletions

View File

@ -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

View File

@ -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);

View File

@ -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...
// -----------------------------------------------------------------------

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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;
}