diff --git a/libpixelflinger/codeflinger/ARMAssembler.cpp b/libpixelflinger/codeflinger/ARMAssembler.cpp
index d3720c3ee168eb9acf1443a2b237ace49c6371ae..fa9f1ade8727e687a70b872d4cc785fe76247c9c 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 a667cb511259bbe44568ab5ac59de8ab1cceed89..e7f038ae494b9d3c18bb4558eb2dc8c369b758d0 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 ff6af2a22b20e9955dd91843406f19ed4ca598c2..796342a06aebfae2f4503224b0b47086a9a9cac6 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 7c422dbadb2d9c3d4dd2685b0dfa74fc27f99d04..c57d7daa962079fac66fc0610223225194e8b492 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 9134cce6f1708b882b5c67ca1e791ecb74cfe9e9..8c7f2707f06e9bc53f98ab8e904dd2e862785358 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 c17f3ecc1d2e5526e15b1ccffd1a9ba65d452af0..aeb80340a7ab5269166dca07543b634c8455f741 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 93c5825797275eafb5cff63eadc0b1bd5f35dac5..023381c7288e2648ff180a68c6778526ef862e32 100644
--- a/libpixelflinger/codeflinger/load_store.cpp
+++ b/libpixelflinger/codeflinger/load_store.cpp
@@ -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;
 }