Merge change 24493 into eclair

* changes:
  Fix several issues in framebuffer_service
diff --git a/adb/commandline.c b/adb/commandline.c
index 6603452..411bb82 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -929,7 +929,7 @@
 
     if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
             || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
-            || !strcmp(argv[0], "root") || !strcmp(argv[0], "bugreport")) {
+            || !strcmp(argv[0], "root")) {
         char command[100];
         if (argc > 1)
             snprintf(command, sizeof(command), "%s:%s", argv[0], argv[1]);
@@ -945,6 +945,14 @@
         return 1;
     }
 
+    if(!strcmp(argv[0], "bugreport")) {
+        if (argc != 1) {
+            return 1;
+        }
+        do_cmd(ttype, serial, "shell", "dumpstate", "-", 0);
+        return 0;
+    }
+
     /* adb_command() wrapper commands */
 
     if(!strncmp(argv[0], "wait-for-", strlen("wait-for-"))) {
diff --git a/adb/services.c b/adb/services.c
index 447c11b..cd02b36 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -32,8 +32,7 @@
 #    include <netdb.h>
 #  endif
 #else
-#include <sys/poll.h>
-#include <sys/reboot.h>
+#  include <sys/reboot.h>
 #endif
 
 typedef struct stinfo stinfo;
@@ -188,43 +187,6 @@
     adb_close(fd);
 }
 
-void bugreport_service(int fd, void *cookie)
-{
-    char    buffer[MAX_PAYLOAD];
-    int i, s;
-
-    /* start the dumpstate service */
-    property_set("ctl.start", "dumpstate");
-
-    /* socket will not be available until service starts */
-    for (i = 0; i < 10; i++) {
-        s = socket_local_client("dumpstate",
-                             ANDROID_SOCKET_NAMESPACE_RESERVED,
-                             SOCK_STREAM);
-        if (s >= 0)
-            break;
-        /* try again in 1 second */
-        sleep(1);
-    }
-
-    if (s < 0) {
-        const char* failed = "Failed to connect to dumpstate service\n";
-        writex(fd, failed, strlen(failed));
-        adb_close(fd);
-        return;
-    }
-
-    while (1) {
-        int length = adb_read(s, buffer, sizeof(buffer));
-        if (length <= 0)
-            break;
-        if (adb_write(fd, buffer, length) <= 0)
-            break;
-    }
-    adb_close(s);
-    adb_close(fd);
-}
-
 #endif
 
 #if 0
@@ -290,9 +252,12 @@
     return s[0];
 }
 
-#if !ADB_HOST
 static int create_subprocess(const char *cmd, const char *arg0, const char *arg1)
 {
+#ifdef HAVE_WIN32_PROC
+	fprintf(stderr, "error: create_subprocess not implemented on Win32 (%s %s %s)\n", cmd, arg0, arg1);
+	return -1;
+#else /* !HAVE_WIN32_PROC */
     char *devname;
     int ptm;
     pid_t pid;
@@ -335,6 +300,7 @@
                 cmd, strerror(errno), errno);
         exit(-1);
     } else {
+#if !ADB_HOST
         // set child's OOM adjustment to zero
         char text[64];
         snprintf(text, sizeof text, "/proc/%d/oom_adj", pid);
@@ -345,11 +311,11 @@
         } else {
            D("adb: unable to open %s\n", text);
         }
-
+#endif
         return ptm;
     }
+#endif /* !HAVE_WIN32_PROC */
 }
-#endif /* !ADB_HOST */
 
 #if ADB_HOST
 #define SHELL_COMMAND "/bin/sh"
@@ -357,76 +323,6 @@
 #define SHELL_COMMAND "/system/bin/sh"
 #endif
 
-#if !ADB_HOST
-static void shell_service(int s, void *command)
-{
-    char    buffer[MAX_PAYLOAD];
-    char    buffer2[MAX_PAYLOAD];
-    struct pollfd ufds[2];
-    int     fd, ret = 0;
-    unsigned count = 0;
-    char** args = (char **)command;
-    fd = create_subprocess(SHELL_COMMAND, args[0], args[1]);
-
-    while (1) {
-        while (count < sizeof(buffer)) {
-            ufds[0].fd = fd;
-            ufds[0].events = POLLIN | POLLHUP;
-            ufds[0].revents = 0;
-            ufds[1].fd = s;
-            ufds[1].events = POLLIN | POLLHUP;
-            ufds[1].revents = 0;
-            // use a 100ms timeout so we don't block indefinitely with our
-            // buffer partially filled.
-            ret = poll(ufds, 2, 100);
-            if (ret <= 0) {
-                D("poll returned %d\n", ret);
-                // file has closed or we timed out
-                // set ret to 1 so we don't exit the outer loop
-                ret = 1;
-                break;
-            }
-
-            if (ufds[0].revents & POLLIN) {
-                ret = adb_read(fd, buffer + count, sizeof(buffer) - count);
-                D("read fd ret: %d, count: %d\n", ret, count);
-                if (ret > 0)
-                    count += ret;
-                else
-                    break;
-            }
-            if (ufds[1].revents & POLLIN) {
-                ret = adb_read(s, buffer2, sizeof(buffer2));
-                D("read s ret: %d\n", ret);
-                if (ret > 0)
-                    adb_write(fd, buffer2, ret);
-                else
-                    break;
-            }
-
-            if ((ufds[0].revents & POLLHUP) || (ufds[1].revents & POLLHUP)) {
-                // set flag to exit after flushing the buffer
-                ret = -1;
-                break;
-            }
-        }
-
-        D("writing: %d\n", count);
-        if (count > 0) {
-            adb_write(s, buffer, count);
-            count = 0;
-        }
-        if (ret <= 0)
-            break;
-    }
-
-    D("shell_service done\n");
-
-    adb_close(fd);
-    adb_close(s);
-}
-#endif // !ADB_HOST
-
 int service_to_fd(const char *name)
 {
     int ret = -1;
@@ -477,16 +373,14 @@
         ret = create_jdwp_connection_fd(atoi(name+5));
     } else if (!strncmp(name, "log:", 4)) {
         ret = create_service_thread(log_service, get_log_file_path(name + 4));
+#endif
     } else if(!HOST && !strncmp(name, "shell:", 6)) {
-        const char* args[2];
         if(name[6]) {
-            args[0] = "-c";
-            args[1] = name + 6;
+            ret = create_subprocess(SHELL_COMMAND, "-c", name + 6);
         } else {
-            args[0] = "-";
-            args[1] = 0;
+            ret = create_subprocess(SHELL_COMMAND, "-", 0);
         }
-        ret = create_service_thread(shell_service, (void *)args);
+#if !ADB_HOST
     } else if(!strncmp(name, "sync:", 5)) {
         ret = create_service_thread(file_sync_service, NULL);
     } else if(!strncmp(name, "remount:", 8)) {
@@ -506,8 +400,6 @@
         ret = create_service_thread(restart_tcp_service, (void *)port);
     } else if(!strncmp(name, "usb:", 4)) {
         ret = create_service_thread(restart_usb_service, NULL);
-    } else if(!strncmp(name, "bugreport:", 10)) {
-        ret = create_service_thread(bugreport_service, NULL);
 #endif
 #if 0
     } else if(!strncmp(name, "echo:", 5)){
diff --git a/include/acc/acc.h b/include/acc/acc.h
index af21a46..1182355 100644
--- a/include/acc/acc.h
+++ b/include/acc/acc.h
@@ -77,6 +77,12 @@
 void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount,
                    ACCsizei maxStringCount, ACCchar** strings);
 
+/* Used to implement disassembly */
+
+void accGetProgramBinary(ACCscript* script,
+    ACCvoid** base,
+    ACCsizei* length);
+
 #ifdef __cplusplus
 };
 #endif
diff --git a/init/devices.c b/init/devices.c
index ea77cf3..c2c9353 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -101,6 +101,10 @@
     /* gpu driver for adreno200 is globally accessible */
     { "/dev/kgsl",          0666,   AID_ROOT,       AID_ROOT,       0 },
 
+    /* STOPSHIP: temporarily make this be writable by all. We need to
+     * remove this entirely before we ship. */
+    { "/dev/pmem_gpu",      0666,   AID_ROOT,       AID_ROOT,       1 },
+
         /* these should not be world writable */
     { "/dev/diag",          0660,   AID_RADIO,      AID_RADIO,        0 },
     { "/dev/diag_arm9",     0660,   AID_RADIO,      AID_RADIO,        0 },
@@ -117,7 +121,6 @@
     { "/dev/eac",           0660,   AID_ROOT,       AID_AUDIO,      0 },
     { "/dev/cam",           0660,   AID_ROOT,       AID_CAMERA,     0 },
     { "/dev/pmem",          0660,   AID_SYSTEM,     AID_GRAPHICS,   0 },
-    { "/dev/pmem_gpu",      0660,   AID_SYSTEM,     AID_GRAPHICS,   1 },
     { "/dev/pmem_adsp",     0660,   AID_SYSTEM,     AID_AUDIO,      1 },
     { "/dev/pmem_camera",   0660,   AID_SYSTEM,     AID_CAMERA,     1 },
     { "/dev/oncrpc/",       0660,   AID_ROOT,       AID_SYSTEM,     1 },
diff --git a/libacc/Android.mk b/libacc/Android.mk
index f77e2b3..2b4998e 100644
--- a/libacc/Android.mk
+++ b/libacc/Android.mk
@@ -7,10 +7,6 @@
 LOCAL_MODULE:= libacc
 LOCAL_SRC_FILES := acc.cpp
 
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_SRC_FILES += disassem.cpp
-endif
-
 LOCAL_SHARED_LIBRARIES := libdl libcutils
 
 include $(BUILD_SHARED_LIBRARY)
@@ -24,10 +20,6 @@
 
 LOCAL_CFLAGS := -O0 -g
 
-ifeq ($(TARGET_ARCH),arm)
-LOCAL_SRC_FILES += disassem.cpp
-endif
-
 LOCAL_STATIC_LIBRARIES := libcutils
 LOCAL_LDLIBS := -ldl
 
diff --git a/libacc/acc.cpp b/libacc/acc.cpp
index 535361c..6dccc5b 100644
--- a/libacc/acc.cpp
+++ b/libacc/acc.cpp
@@ -13,20 +13,20 @@
 
 #include <ctype.h>
 #include <errno.h>
+#include <limits.h>
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+
 #include <cutils/hashmap.h>
 
 #if defined(__i386__)
 #include <sys/mman.h>
 #endif
 
-#if defined(__arm__)
-#include <unistd.h>
-#endif
 
 #if defined(__arm__)
 #define DEFAULT_ARM_CODEGEN
@@ -39,10 +39,6 @@
 #define PROVIDE_X64_CODEGEN
 #endif
 
-#ifdef PROVIDE_ARM_CODEGEN
-#include "disassem.h"
-#endif
-
 #if (defined(__VFP_FP__) && !defined(__SOFTFP__))
 #define ARM_USE_VFP
 #endif
@@ -55,9 +51,22 @@
 #define LOG_STACK(...) do {} while(0)
 // #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__)
 
-#define ENABLE_ARM_DISASSEMBLY
 // #define PROVIDE_TRACE_CODEGEN
 
+// Uncomment to disable ARM peephole optimizations
+// #define DISABLE_ARM_PEEPHOLE
+
+// Uncomment to save input to a text file in DEBUG_DUMP_PATTERN
+// #define DEBUG_SAVE_INPUT_TO_FILE
+
+#ifdef DEBUG_SAVE_INPUT_TO_FILE
+#ifdef ARM_USE_VFP
+#define DEBUG_DUMP_PATTERN "/data/misc/acc_dump/%d.c"
+#else
+#define DEBUG_DUMP_PATTERN "/tmp/acc_dump/%d.c"
+#endif
+#endif
+
 #define assert(b) assertImpl(b, __LINE__)
 
 namespace acc {
@@ -179,7 +188,21 @@
         Type* pType;
     };
 
-    class CodeBuf {
+    class ICodeBuf {
+    public:
+        virtual ~ICodeBuf() {}
+        virtual void init(int size) = 0;
+        virtual void setErrorSink(ErrorSink* pErrorSink) = 0;
+        virtual void o4(int n) = 0;
+        virtual void ob(int n) = 0;
+        virtual void* getBase() = 0;
+        virtual intptr_t getSize() = 0;
+        virtual intptr_t getPC() = 0;
+        // Call this before trying to modify code in the buffer.
+        virtual void flush() = 0;
+    };
+
+    class CodeBuf : public ICodeBuf {
         char* ind; // Output code pointer
         char* pProgramBase;
         ErrorSink* mErrorSink;
@@ -214,52 +237,52 @@
             mOverflowed = false;
         }
 
-        ~CodeBuf() {
+        virtual ~CodeBuf() {
             release();
         }
 
-        void init(int size) {
+        virtual void init(int size) {
             release();
             mSize = size;
             pProgramBase = (char*) calloc(1, size);
             ind = pProgramBase;
         }
 
-        void setErrorSink(ErrorSink* pErrorSink) {
+        virtual void setErrorSink(ErrorSink* pErrorSink) {
             mErrorSink = pErrorSink;
         }
 
-        int o4(int n) {
+        virtual void o4(int n) {
             if(check(4)) {
-                return 0;
+                return;
             }
-            intptr_t result = (intptr_t) ind;
             * (int*) ind = n;
             ind += 4;
-            return result;
         }
 
         /*
          * Output a byte. Handles all values, 0..ff.
          */
-        void ob(int n) {
+        virtual void ob(int n) {
             if(check(1)) {
                 return;
             }
             *ind++ = n;
         }
 
-        inline void* getBase() {
+        virtual void* getBase() {
             return (void*) pProgramBase;
         }
 
-        intptr_t getSize() {
+        virtual intptr_t getSize() {
             return ind - pProgramBase;
         }
 
-        intptr_t getPC() {
+        virtual intptr_t getPC() {
             return (intptr_t) ind;
         }
+
+        virtual void flush() {}
     };
 
     /**
@@ -291,7 +314,7 @@
         }
         virtual ~CodeGenerator() {}
 
-        virtual void init(CodeBuf* pCodeBuf) {
+        virtual void init(ICodeBuf* pCodeBuf) {
             this->pCodeBuf = pCodeBuf;
             pCodeBuf->setErrorSink(mErrorSink);
         }
@@ -473,11 +496,6 @@
          */
         virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) = 0;
 
-        /* Print a disassembly of the assembled code to out. Return
-         * non-zero if there is an error.
-         */
-        virtual int disassemble(FILE* out) = 0;
-
         /* Generate a symbol at the current PC. t is the head of a
          * linked list of addresses to patch.
          */
@@ -543,8 +561,8 @@
             pCodeBuf->ob(n);
         }
 
-        intptr_t o4(int data) {
-            return pCodeBuf->o4(data);
+        void o4(int data) {
+            pCodeBuf->o4(data);
         }
 
         intptr_t getBase() {
@@ -559,6 +577,10 @@
             return pCodeBuf->getSize();
         }
 
+        void flush() {
+            pCodeBuf->flush();
+        }
+
         void error(const char* fmt,...) {
             va_list ap;
             va_start(ap, fmt);
@@ -674,19 +696,269 @@
 
     private:
         Vector<ExpressionValue> mExpressionStack;
-        CodeBuf* pCodeBuf;
+        ICodeBuf* pCodeBuf;
         ErrorSink* mErrorSink;
     };
 
 #ifdef PROVIDE_ARM_CODEGEN
 
+    static size_t rotateRight(size_t n, size_t rotate) {
+        return (n >> rotate) | (n << (32 - rotate));
+    }
+
+    static size_t rotateLeft(size_t n, size_t rotate) {
+        return (n << rotate) | (n >> (32 - rotate));
+    }
+
+    static bool encode12BitImmediate(size_t immediate, size_t* pResult) {
+        for(size_t i = 0; i < 16; i++) {
+            size_t rotate = i * 2;
+            size_t mask = rotateRight(0xff, rotate);
+            if ((immediate | mask) == mask) {
+                size_t bits8 = rotateLeft(immediate, rotate);
+                // assert(bits8 <= 0xff);
+                *pResult = (i << 8) | bits8;
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static size_t decode12BitImmediate(size_t immediate) {
+        size_t data = immediate & 0xff;
+        size_t rotate = 2 * ((immediate >> 8) & 0xf);
+        return rotateRight(data, rotate);
+    }
+
+    static bool isPowerOfTwo(size_t n) {
+        return (n != 0) & ((n & (n-1)) == 0);
+    }
+
+    static size_t log2(size_t n) {
+        int result = 0;
+        while (n >>= 1) {
+            result++;
+        }
+        return result;
+    }
+
+    class ARMCodeBuf : public ICodeBuf {
+        ICodeBuf* mpBase;
+        ErrorSink* mErrorSink;
+
+        class CircularQueue {
+            static const int SIZE = 16; // Must be power of 2
+            static const int MASK = SIZE-1;
+            unsigned int mBuf[SIZE];
+            int mHead;
+            int mCount;
+
+        public:
+            CircularQueue() {
+                mHead = 0;
+                mCount = 0;
+            }
+
+            void pushBack(unsigned int data) {
+                mBuf[(mHead + mCount) & MASK] = data;
+                mCount += 1;
+            }
+
+            unsigned int popFront() {
+                unsigned int result = mBuf[mHead];
+                mHead = (mHead + 1) & MASK;
+                mCount -= 1;
+                return result;
+            }
+
+            void popBack(int n) {
+                mCount -= n;
+            }
+
+            inline int count() {
+                return mCount;
+            }
+
+            bool empty() {
+                return mCount == 0;
+            }
+
+            bool full() {
+                return mCount == SIZE;
+            }
+
+            // The valid indexes are 1 - count() to 0
+            unsigned int operator[](int i) {
+                return mBuf[(mHead + mCount + i) & MASK];
+            }
+        };
+
+        CircularQueue mQ;
+
+        void error(const char* fmt,...) {
+            va_list ap;
+            va_start(ap, fmt);
+            mErrorSink->verror(fmt, ap);
+            va_end(ap);
+        }
+
+        void flush() {
+            while (!mQ.empty()) {
+                mpBase->o4(mQ.popFront());
+            }
+            mpBase->flush();
+        }
+
+    public:
+        ARMCodeBuf(ICodeBuf* pBase) {
+            mpBase = pBase;
+        }
+
+        virtual ~ARMCodeBuf() {
+            delete mpBase;
+        }
+
+        void init(int size) {
+            mpBase->init(size);
+        }
+
+        void setErrorSink(ErrorSink* pErrorSink) {
+            mErrorSink = pErrorSink;
+            mpBase->setErrorSink(pErrorSink);
+        }
+
+        void o4(int n) {
+            if (mQ.full()) {
+                mpBase->o4(mQ.popFront());
+            }
+            mQ.pushBack(n);
+
+#ifndef DISABLE_ARM_PEEPHOLE
+            // Peephole check
+            bool didPeep;
+            do {
+                static const unsigned int opMask = 0x01e00000;
+                static const unsigned int immediateMask = 0x00000fff;
+                static const unsigned int BMask = 0x00400000;
+                didPeep = false;
+                if (mQ.count() >= 4) {
+
+                    // Operand by a small constant
+                    // push;mov #imm;pop;op ==> op #imm
+
+                    if (mQ[-4] == 0xe92d0001  && // stmfd	r13!, {r0}
+                        (mQ[-3] & ~immediateMask) == 0xe3a00000  && // mov	r0, #X
+                        mQ[-2] == 0xe8bd0002  && // ldmea	r13!, {r1}
+                        (mQ[-1] & ~opMask) == (0xe0810000 & ~opMask)) {  // OP	r0, r1, r0
+                        unsigned int movConst = mQ[-3];
+                        unsigned int op = mQ[-1];
+                        unsigned int combined = 0xe2000000 | (op & opMask) | (movConst & immediateMask);
+                        // fprintf(stderr, "op %x movConst %x combined %x\n", op, movConst, combined);
+                        if (! (combined == 0xe2800000 || combined == 0xe2400000)) { // add/sub #0
+                            mQ.popBack(4);
+                            mQ.pushBack(combined);
+                            didPeep = true;
+                        } else {
+                            mQ.popBack(4);
+                            didPeep = true;
+                        }
+                    }
+                }
+
+                // Load local variable
+                // sub r0,r11,#imm;ldr/ldrb r0,[r0]  ==> ldr/ldrb r0, [r11,#-imm]
+                if (mQ.count() >= 2) {
+                    if ((mQ[-2] & ~immediateMask) == 0xe24b0000) { // sub r0,r11,#imm
+                        const unsigned int encodedImmediate = mQ[-2] & immediateMask;
+                        const unsigned int ld = mQ[-1];
+                        if ((ld & ~BMask) == 0xe5900000) { // ldr{b} r0, [r0]
+                            unsigned int combined = encodedImmediate | (0xE51B0000 | (ld & BMask)); // ldr r0, [r11, #-0]
+                            mQ.popBack(2);
+                            mQ.pushBack(combined);
+                            didPeep = true;
+                        } else if (ld == 0xedd07a00) {  // ldcl	p10, c7, [r0, #0x000]
+                            unsigned int decodedImmediate = decode12BitImmediate(encodedImmediate);
+                            if (decodedImmediate <= 1020 && ((decodedImmediate & 3) == 0)) {
+                                unsigned int combined = (decodedImmediate >> 2) | 0xed5b7a00; // ldcl	p10, c7, [r11, #-0]
+                                mQ.popBack(2);
+                                mQ.pushBack(combined);
+                                didPeep = true;
+                            }
+                        }
+                    }
+                }
+
+                // Constant array lookup
+
+                if (mQ.count() >= 6 &&
+                    mQ[-6] == 0xe92d0001 && // stmfd r13!, {r0}
+                    (mQ[-5] & ~immediateMask)== 0xe3a00000 && // mov r0, #0x00000001
+                    mQ[-4] == 0xe8bd0002 && // ldmea r13!, {r1}
+                    (mQ[-3] & ~immediateMask)== 0xe3a02000 && // mov r2, #0x00000004
+                    mQ[-2] == 0xe0000092 && // mul r0, r2, r0
+                    mQ[-1] == 0xe0810000) { // add r0, r1, r0
+                    unsigned int mov1 = mQ[-5];
+                    unsigned int mov2 = mQ[-3];
+                    unsigned int const1 = decode12BitImmediate(mov1);
+                    unsigned int const2 = decode12BitImmediate(mov2);
+                    unsigned int comboConst = const1 * const2;
+                    size_t immediate = 0;
+                    if (encode12BitImmediate(comboConst, &immediate)) {
+                        mQ.popBack(6);
+                        unsigned int add = immediate | 0xE2800000; // add r0, r0, #n
+                        if (comboConst) {
+                            mQ.pushBack(add);
+                        }
+                        didPeep = true;
+                    }
+                }
+
+                // Pointer arithmetic with a stride that is a power of two
+
+                if (mQ.count() >= 3 &&
+                    (mQ[-3] & ~ immediateMask) == 0xe3a02000 &&  // mov	r2, #stride
+                     mQ[-2] == 0xe0000092 && // mul	r0, r2, r0
+                     mQ[-1] == 0xe0810000) {  // add r0, r1, r0
+                    int stride = decode12BitImmediate(mQ[-3]);
+                    if (isPowerOfTwo(stride)) {
+                        mQ.popBack(3);
+                        unsigned int add = 0xe0810000 | (log2(stride) << 7); // add r0, r1, r0, LSL #log2(stride)
+                        mQ.pushBack(add);
+                        didPeep = true;
+                    }
+                }
+
+            } while (didPeep);
+#endif
+        }
+
+        void ob(int n) {
+            error("ob() not supported.");
+        }
+
+        void* getBase() {
+            flush();
+            return mpBase->getBase();
+        }
+
+        intptr_t getSize() {
+            flush();
+            return mpBase->getSize();
+        }
+
+        intptr_t getPC() {
+            flush();
+            return mpBase->getPC();
+        }
+    };
+
     class ARMCodeGenerator : public CodeGenerator {
     public:
         ARMCodeGenerator() {
 #ifdef ARM_USE_VFP
-            LOGD("Using ARM VFP hardware floating point.");
+            // LOGD("Using ARM VFP hardware floating point.");
 #else
-            LOGD("Using ARM soft floating point.");
+            // LOGD("Using ARM soft floating point.");
 #endif
         }
 
@@ -709,10 +981,12 @@
             // sp, fp -> oldfp, retadr, arg0 arg1 ....
             o4(0xE1A0B00D); // mov    fp, sp
             LOG_STACK("functionEntry: %d\n", mStackUse);
-            return o4(0xE24DD000); // sub    sp, sp, # <local variables>
+            int pc = getPC();
+            o4(0xE24DD000); // sub    sp, sp, # <local variables>
             // We don't know how many local variables we are going to use,
             // but we will round the allocation up to a multiple of
             // STACK_ALIGNMENT, so it won't affect the stack alignment.
+            return pc;
         }
 
         virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) {
@@ -809,7 +1083,9 @@
         }
 
         virtual int gjmp(int t) {
-            return o4(0xEA000000 | encodeAddress(t)); // b .L33
+            int pc = getPC();
+            o4(0xEA000000 | encodeAddress(t)); // b .L33
+            return pc;
         }
 
         /* l = 0: je, l == 1: jne */
@@ -840,7 +1116,9 @@
                     break;
             }
             int branch = l ? 0x1A000000 : 0x0A000000; // bne : beq
-            return o4(branch | encodeAddress(t));
+            int pc = getPC();
+            o4(branch | encodeAddress(t));
+            return pc;
         }
 
         virtual void gcmp(int op) {
@@ -1475,7 +1753,8 @@
 
             if (ea == 0) {
                 o4(0xEA000000); //        b .L99
-                result = o4(ea);         // .L1:   .word 0
+                result = getPC();
+                o4(ea);         // .L1:   .word 0
                             // .L99:
             }
             return result;
@@ -1537,21 +1816,27 @@
 #endif
                     }
                 } else {
-                    assert (r0Tag == TY_DOUBLE);
-                    if (destTag == TY_INT) {
+                    if (r0Tag == TY_DOUBLE) {
+                        if (destTag == TY_INT) {
 #ifdef ARM_USE_VFP
-                        o4(0xEEFD7BC7); // ftosizd s15, d7
-                        o4(0xEE170A90); // fmrs r0, s15
+                            o4(0xEEFD7BC7); // ftosizd s15, d7
+                            o4(0xEE170A90); // fmrs r0, s15
 #else
-                        callRuntime((void*) runtime_double_to_int);
+                            callRuntime((void*) runtime_double_to_int);
 #endif
+                        } else {
+                            if(destTag == TY_FLOAT) {
+#ifdef ARM_USE_VFP
+                                o4(0xEEF77BC7); // fcvtsd s15, d7
+#else
+                                callRuntime((void*) runtime_double_to_float);
+#endif
+                            } else {
+                                incompatibleTypes(pR0Type, pType);
+                            }
+                        }
                     } else {
-                        assert(destTag == TY_FLOAT);
-#ifdef ARM_USE_VFP
-                        o4(0xEEF77BC7); // fcvtsd s15, d7
-#else
-                        callRuntime((void*) runtime_double_to_float);
-#endif
+                        incompatibleTypes(pR0Type, pType);
                     }
                 }
             }
@@ -1559,7 +1844,9 @@
         }
 
         virtual int beginFunctionCallArguments() {
-            return o4(0xE24DDF00); // Placeholder
+            int pc = getPC();
+            o4(0xE24DDF00); // Placeholder sub  sp, sp, #0
+            return pc;
         }
 
         virtual size_t storeR0ToArg(int l, Type* pArgType) {
@@ -1645,6 +1932,7 @@
             if (l < 0 || l > 0x3FC) {
                 error("L out of range for stack adjustment: 0x%08x", l);
             }
+            flush();
             * (int*) a = 0xE24DDF00 | (l >> 2); // sub    sp, sp, #0 << 2
             mStackUse += mStackAlignmentAdjustment;
             LOG_STACK("endFunctionCallArguments mStackUse: %d, mStackAlignmentAdjustment %d\n",
@@ -1654,7 +1942,9 @@
         virtual int callForward(int symbol, Type* pFunc) {
             setR0Type(pFunc->pHead);
             // Forward calls are always short (local)
-            return o4(0xEB000000 | encodeAddress(symbol));
+            int pc = getPC();
+            o4(0xEB000000 | encodeAddress(symbol));
+            return pc;
         }
 
         virtual void callIndirect(int l, Type* pFunc) {
@@ -1747,24 +2037,6 @@
 #endif
         }
 
-        virtual int disassemble(FILE* out) {
-#ifdef ENABLE_ARM_DISASSEMBLY
-            disasmOut = out;
-            disasm_interface_t  di;
-            di.di_readword = disassemble_readword;
-            di.di_printaddr = disassemble_printaddr;
-            di.di_printf = disassemble_printf;
-
-            int base = getBase();
-            int pc = getPC();
-            for(int i = base; i < pc; i += 4) {
-                fprintf(out, "%08x: %08x  ", i, *(int*) i);
-                ::disasm(&di, i, 0);
-            }
-#endif
-            return 0;
-        }
-
         /**
          * alignment (in bytes) for this type of data
          */
@@ -1816,27 +2088,6 @@
         }
 
     private:
-        static FILE* disasmOut;
-
-        static u_int
-        disassemble_readword(u_int address)
-        {
-            return(*((u_int *)address));
-        }
-
-        static void
-        disassemble_printaddr(u_int address)
-        {
-            fprintf(disasmOut, "0x%08x", address);
-        }
-
-        static void
-        disassemble_printf(const char *fmt, ...) {
-            va_list ap;
-            va_start(ap, fmt);
-            vfprintf(disasmOut, fmt, ap);
-            va_end(ap);
-        }
 
         static const int BRANCH_REL_ADDRESS_MASK = 0x00ffffff;
 
@@ -2007,26 +2258,8 @@
             }
         }
 
-        bool encode12BitImmediate(size_t immediate, size_t* pResult) {
-            for(size_t i = 0; i < 16; i++) {
-                size_t rotate = i * 2;
-                size_t mask = rotateRight(0xff, rotate);
-                if ((immediate | mask) == mask) {
-                    size_t bits8 = rotateLeft(immediate, rotate);
-                    assert(bits8 <= 0xff);
-                    *pResult = (i << 8) | bits8;
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        size_t rotateRight(size_t n, size_t rotate) {
-            return (n >> rotate) | (n << (32 - rotate));
-        }
-
-        size_t rotateLeft(size_t n, size_t rotate) {
-            return (n << rotate) | (n >> (32 - rotate));
+        void incompatibleTypes(Type* pR0Type, Type* pType) {
+            error("Incompatible types old: %d new: %d", pR0Type->tag, pType->tag);
         }
 
         void callRuntime(void* fn) {
@@ -2762,10 +2995,6 @@
             return 5;
         }
 
-        virtual int disassemble(FILE* out) {
-            return 0;
-        }
-
         /* output a symbol and patch all calls to it */
         virtual void gsym(int t) {
             int n;
@@ -2942,7 +3171,7 @@
             delete mpBase;
         }
 
-        virtual void init(CodeBuf* pCodeBuf) {
+        virtual void init(ICodeBuf* pCodeBuf) {
             mpBase->init(pCodeBuf);
         }
 
@@ -3093,10 +3322,6 @@
             return mpBase->jumpOffset();
         }
 
-        virtual int disassemble(FILE* out) {
-            return mpBase->disassemble(out);
-        }
-
         /* output a symbol and patch all calls to it */
         virtual void gsym(int t) {
             fprintf(stderr, "gsym(%d)\n", t);
@@ -3719,7 +3944,7 @@
     int mLineNumber;
     bool mbBumpLine;
 
-    CodeBuf codeBuf;
+    ICodeBuf* pCodeBuf;
     CodeGenerator* pGen;
 
     String mErrorBuf;
@@ -4450,10 +4675,8 @@
                 unary();
                 doPointer();
             } else if (t == '&') {
-                VariableInfo* pVI = VI(tok);
-                pGen->leaR0((int) pVI->pAddress, createPtrType(pVI->pType),
-                        ET_RVALUE);
-                next();
+                unary();
+                doAddressOf();
             } else if (t == EOF ) {
                 error("Unexpected EOF.");
             } else if (t == ';') {
@@ -4529,7 +4752,7 @@
                 pGen->forceR0RVal();
                 Type* pStruct = pGen->getR0Type();
                 if (pStruct->tag == TY_STRUCT) {
-                    doStructMember(pStruct);
+                    doStructMember(pStruct, true);
                 } else {
                     error("expected a struct value to the left of '.'");
                 }
@@ -4538,7 +4761,7 @@
                 Type* pPtr = pGen->getR0Type();
                 if (pPtr->tag == TY_POINTER && pPtr->pHead->tag == TY_STRUCT) {
                     pGen->loadR0FromR0();
-                    doStructMember(pPtr->pHead);
+                    doStructMember(pPtr->pHead, false);
                 } else {
                     error("Expected a pointer to a struct to the left of '->'");
                 }
@@ -4604,7 +4827,7 @@
         }
     }
 
-    void doStructMember(Type* pStruct) {
+    void doStructMember(Type* pStruct, bool isDot) {
         Type* pStructElement = lookupStructMember(pStruct, tok);
         if (pStructElement) {
             next();
@@ -4612,7 +4835,8 @@
         } else {
             String buf;
             decodeToken(buf, tok, true);
-            error("Expected a struct member to the right of '.', got %s", buf.getUnwrapped());
+            error("Expected a struct member to the right of '%s', got %s",
+                    isDot ? "." : "->", buf.getUnwrapped());
         }
     }
 
@@ -4656,6 +4880,16 @@
         }
     }
 
+    void doAddressOf() {
+        Type* pR0 = pGen->getR0Type();
+        bool isFuncPtr = pR0->tag == TY_POINTER && pR0->pHead->tag == TY_FUNC;
+        if ((! isFuncPtr) && pGen->getR0ExpressionType() != ET_LVALUE) {
+            error("Expected an lvalue");
+        }
+        Type* pR0Type = pGen->getR0Type();
+        pGen->setR0ExpressionType(ET_RVALUE);
+    }
+
     /* Recursive descent parser for binary operations.
      */
     void binaryOp(int level) {
@@ -4749,13 +4983,13 @@
             next();
             skip('(');
             if (t == TOK_WHILE) {
-                n = codeBuf.getPC(); // top of loop, target of "next" iteration
+                n = pCodeBuf->getPC(); // top of loop, target of "next" iteration
                 a = test_expr();
             } else {
                 if (tok != ';')
                     commaExpr();
                 skip(';');
-                n = codeBuf.getPC();
+                n = pCodeBuf->getPC();
                 a = 0;
                 if (tok != ';')
                     a = test_expr();
@@ -4763,14 +4997,14 @@
                 if (tok != ')') {
                     t = pGen->gjmp(0);
                     commaExpr();
-                    pGen->gjmp(n - codeBuf.getPC() - pGen->jumpOffset());
+                    pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset());
                     pGen->gsym(t);
                     n = t + 4;
                 }
             }
             skip(')');
             block((intptr_t) &a, false);
-            pGen->gjmp(n - codeBuf.getPC() - pGen->jumpOffset()); /* jmp */
+            pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset()); /* jmp */
             pGen->gsym(a);
         } else if (tok == '{') {
             if (! outermostFunctionBlock) {
@@ -5293,7 +5527,7 @@
 
     void checkLVal() {
         if (pGen->getR0ExpressionType() != ET_LVALUE) {
-            error("Expected an lval");
+            error("Expected an lvalue");
         }
     }
 
@@ -5318,6 +5552,16 @@
         mLocals.add(pDecl);
     }
 
+    bool checkUndeclaredStruct(Type* pBaseType) {
+        if (pBaseType->tag == TY_STRUCT && pBaseType->length < 0) {
+            String temp;
+            decodeToken(temp, pBaseType->structTag, false);
+            error("Undeclared struct %s", temp.getUnwrapped());
+            return true;
+        }
+        return false;
+    }
+
     void localDeclarations(Type* pBaseType) {
         intptr_t a;
 
@@ -5330,6 +5574,9 @@
                 if (!pDecl->id) {
                     break;
                 }
+                if (checkUndeclaredStruct(pDecl)) {
+                    break;
+                }
                 int variableAddress = 0;
                 addLocalSymbol(pDecl);
                 size_t alignment = pGen->alignmentOf(pDecl);
@@ -5427,6 +5674,11 @@
                 continue;
             }
 
+            if (checkUndeclaredStruct(pDecl)) {
+                skip(';');
+                continue;
+            }
+
             if (! isDefined(pDecl->id)) {
                 addGlobalSymbol(pDecl);
             }
@@ -5478,7 +5730,7 @@
                         /* patch forward references */
                         pGen->resolveForward((int) name->pForward);
                         /* put function address */
-                        name->pAddress = (void*) codeBuf.getPC();
+                        name->pAddress = (void*) pCodeBuf->getPC();
                     }
                     // Calculate stack offsets for parameters
                     mLocals.pushLevel();
@@ -5545,6 +5797,10 @@
             delete pGen;
             pGen = 0;
         }
+        if (pCodeBuf) {
+            delete pCodeBuf;
+            pCodeBuf = 0;
+        }
         if (file) {
             delete file;
             file = 0;
@@ -5569,6 +5825,7 @@
         dch = 0;
         file = 0;
         pGlobalBase = 0;
+        pCodeBuf = 0;
         pGen = 0;
         mPragmaStringCount = 0;
         mCompileResult = 0;
@@ -5581,10 +5838,14 @@
         delete pGen;
         pGen = 0;
 
+        delete pCodeBuf;
+        pCodeBuf = new CodeBuf();
+
         if (architecture != NULL) {
 #ifdef PROVIDE_ARM_CODEGEN
             if (! pGen && strcmp(architecture, "arm") == 0) {
                 pGen = new ARMCodeGenerator();
+                pCodeBuf = new ARMCodeBuf(pCodeBuf);
             }
 #endif
 #ifdef PROVIDE_X86_CODEGEN
@@ -5600,6 +5861,7 @@
         if (pGen == NULL) {
 #if defined(DEFAULT_ARM_CODEGEN)
             pGen = new ARMCodeGenerator();
+            pCodeBuf = new ARMCodeBuf(pCodeBuf);
 #elif defined(DEFAULT_X86_CODEGEN)
             pGen = new X86CodeGenerator();
 #endif
@@ -5648,7 +5910,6 @@
         mLocals.setTokenTable(&mTokenTable);
 
         internKeywords();
-        codeBuf.init(ALLOC_SIZE);
         setArchitecture(NULL);
         if (!pGen) {
             return -1;
@@ -5656,8 +5917,12 @@
 #ifdef PROVIDE_TRACE_CODEGEN
             pGen = new TraceCodeGenerator(pGen);
 #endif
-            pGen->setErrorSink(this);
-        pGen->init(&codeBuf);
+        pGen->setErrorSink(this);
+
+        if (pCodeBuf) {
+            pCodeBuf->init(ALLOC_SIZE);
+        }
+        pGen->init(pCodeBuf);
         file = new TextInputStream(text, textLength);
         pGlobalBase = (char*) calloc(1, ALLOC_SIZE);
         glo = pGlobalBase;
@@ -5707,15 +5972,6 @@
         return true;
     }
 
-    int dump(FILE* out) {
-        fwrite(codeBuf.getBase(), 1, codeBuf.getSize(), out);
-        return 0;
-    }
-
-    int disassemble(FILE* out) {
-        return pGen->disassemble(out);
-    }
-
     /* Look through the symbol table to find a symbol.
      * If found, return its value.
      */
@@ -5748,10 +6004,14 @@
         }
     }
 
+    void getProgramBinary(ACCvoid** base, ACCsizei* length) {
+        *base = pCodeBuf->getBase();
+        *length = (ACCsizei) pCodeBuf->getSize();
+    }
+
     char* getErrorMessage() {
         return mErrorBuf.getUnwrapped();
     }
-
 };
 
 const char* Compiler::operatorChars =
@@ -5765,10 +6025,6 @@
             2, 2 /* ~ ! */
             };
 
-#ifdef PROVIDE_ARM_CODEGEN
-FILE* Compiler::ARMCodeGenerator::disasmOut;
-#endif
-
 #ifdef PROVIDE_X86_CODEGEN
 const int Compiler::X86CodeGenerator::operatorHelper[] = {
         0x1,     // ++
@@ -5886,6 +6142,29 @@
         dest += len;
     }
     text[totalLength] = '\0';
+
+#ifdef DEBUG_SAVE_INPUT_TO_FILE
+    LOGD("Saving input to file...");
+    int counter;
+    char path[PATH_MAX];
+    for (counter = 0; counter < 4096; counter++) {
+        sprintf(path, DEBUG_DUMP_PATTERN, counter);
+        if(access(path, F_OK) != 0) {
+            break;
+        }
+    }
+    if (counter < 4096) {
+        LOGD("Saving input to file %s", path);
+        FILE* fd = fopen(path, "w");
+        if (fd) {
+            fwrite(text, totalLength, 1, fd);
+            fclose(fd);
+            LOGD("Saved input to file %s", path);
+        } else {
+            LOGD("Could not save. errno: %d", errno);
+        }
+    }
+#endif
 }
 
 extern "C"
@@ -5943,8 +6222,9 @@
 }
 
 extern "C"
-void accDisassemble(ACCscript* script) {
-    script->compiler.disassemble(stderr);
+void accGetProgramBinary(ACCscript* script,
+    ACCvoid** base, ACCsizei* length) {
+    script->compiler.getProgramBinary(base, length);
 }
 
 
diff --git a/libacc/tests/Android.mk b/libacc/tests/Android.mk
index 77e48be..e9fbe03 100644
--- a/libacc/tests/Android.mk
+++ b/libacc/tests/Android.mk
@@ -21,7 +21,8 @@
 LOCAL_MODULE:= acc
 
 LOCAL_SRC_FILES:= \
-	main.cpp
+	main.cpp \
+    disassem.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libacc
diff --git a/libacc/tests/accarm b/libacc/tests/accarm
new file mode 100755
index 0000000..6b1bf66
--- /dev/null
+++ b/libacc/tests/accarm
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+#
+# Run a test on the ARM version of acc.
+
+import unittest
+import subprocess
+import os
+import sys
+
+def compile(args):
+    proc = subprocess.Popen(["acc"] + args, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
+    result = proc.communicate()
+    return result
+
+def runCmd(args):
+    proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    result = proc.communicate()
+    return result[0].strip()
+
+def uname():
+    return runCmd(["uname"])
+
+def unameM():
+    return runCmd(["uname", "-m"])
+
+def which(item):
+    return runCmd(["which", item])
+
+def adb(args):
+    return runCmd(["adb"] + args)
+
+def setupArm(file):
+    print "Setting up arm"
+    adb(["remount"])
+    adb(["shell", "rm", "/system/bin/acc"])
+    adb(["shell", "mkdir", "/system/bin/accdata"])
+    adb(["shell", "mkdir", "/system/bin/accdata/data"])
+
+    remoteFileName = os.path.join("/system/bin/accdata", file)
+    adb(["push", file, remoteFileName])
+
+    # Copy over compiler
+    adb(["sync"])
+    return remoteFileName
+
+def compileArm(args):
+    remoteArgs = []
+    fileName = ""
+    for arg in sys.argv[1:]:
+        if arg.startswith('-'):
+            remoteArgs.append(arg)
+        else:
+            fileName = arg
+
+    remoteFileName = setupArm(fileName)
+    remoteArgs.append(remoteFileName)
+    remoteCmdLine = ["adb", "shell", "/system/bin/acc"] + remoteArgs
+    proc = subprocess.Popen(remoteCmdLine, stdout=subprocess.PIPE)
+    result = proc.communicate()
+    return result[0].replace("\r","")
+
+
+def main():
+    print compileArm(sys.argv[1:])
+
+if __name__ == '__main__':
+    main()
+
+
diff --git a/libacc/armreg.h b/libacc/tests/armreg.h
similarity index 100%
rename from libacc/armreg.h
rename to libacc/tests/armreg.h
diff --git a/libacc/tests/data/addressOf.c b/libacc/tests/data/addressOf.c
new file mode 100644
index 0000000..e7acde5
--- /dev/null
+++ b/libacc/tests/data/addressOf.c
@@ -0,0 +1,31 @@
+void testStruct() {
+    struct str {
+        float x;
+        float y;
+    };
+
+    struct str base;
+    int index = 0;
+
+    base.x = 10.0;
+    struct str *s = &base;
+
+    float *v = &(*s).x;
+    float *v2 = &s[index].x;
+    printf("testStruct: %g %g %g\n",base.x, *v, *v2);
+}
+
+void testArray() {
+    int a[2];
+    a[0] = 1;
+    a[1] = 2;
+    int* p = &a[0];
+    int* p2 = a;
+    printf("testArray: %d %d %d\n", a[0], *p, *p2);
+}
+
+int main() {
+    testStruct();
+    testArray();
+    return 0;
+}
diff --git a/libacc/disassem.cpp b/libacc/tests/disassem.cpp
similarity index 100%
rename from libacc/disassem.cpp
rename to libacc/tests/disassem.cpp
diff --git a/libacc/disassem.h b/libacc/tests/disassem.h
similarity index 100%
rename from libacc/disassem.h
rename to libacc/tests/disassem.h
diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp
index 5e9e816..311fec0 100644
--- a/libacc/tests/main.cpp
+++ b/libacc/tests/main.cpp
@@ -20,6 +20,14 @@
 #include <unistd.h>
 #endif
 
+#if defined(__arm__)
+#define PROVIDE_ARM_DISASSEMBLY
+#endif
+
+#ifdef PROVIDE_ARM_DISASSEMBLY
+#include "disassem.h"
+#endif
+
 #include <acc/acc.h>
 
 
@@ -29,15 +37,57 @@
     return mainFunc(argc, argv);
 }
 
-// Private API for development:
-
-extern "C"
-void accDisassemble(ACCscript* script);
-
 ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) {
     return (ACCvoid*) dlsym(RTLD_DEFAULT, name);
 }
 
+#ifdef PROVIDE_ARM_DISASSEMBLY
+
+static FILE* disasmOut;
+
+static u_int
+disassemble_readword(u_int address)
+{
+    return(*((u_int *)address));
+}
+
+static void
+disassemble_printaddr(u_int address)
+{
+    fprintf(disasmOut, "0x%08x", address);
+}
+
+static void
+disassemble_printf(const char *fmt, ...) {
+    va_list ap;
+    va_start(ap, fmt);
+    vfprintf(disasmOut, fmt, ap);
+    va_end(ap);
+}
+
+static int disassemble(ACCscript* script, FILE* out) {
+    disasmOut = out;
+    disasm_interface_t  di;
+    di.di_readword = disassemble_readword;
+    di.di_printaddr = disassemble_printaddr;
+    di.di_printf = disassemble_printf;
+
+    ACCvoid* base;
+    ACCsizei length;
+
+    accGetProgramBinary(script, &base, &length);
+    unsigned long* pBase = (unsigned long*) base;
+    unsigned long* pEnd = (unsigned long*) (((unsigned char*) base) + length);
+
+    for(unsigned long* pInstruction = pBase; pInstruction < pEnd; pInstruction++) {
+        fprintf(out, "%08x: %08x  ", (int) pInstruction, *pInstruction);
+        ::disasm(&di, (uint) pInstruction, 0);
+    }
+    return 0;
+}
+
+#endif // PROVIDE_ARM_DISASSEMBLY
+
 int main(int argc, char** argv) {
     const char* inFile = NULL;
     bool printListing;
@@ -121,7 +171,9 @@
     }
 
     if (printListing) {
-        accDisassemble(script);
+#ifdef PROVIDE_ARM_DISASSEMBLY
+        disassemble(script, stderr);
+#endif
     }
 
     if (runResults) {
diff --git a/libacc/tests/test.py b/libacc/tests/test.py
index a8575b1..c982d16 100644
--- a/libacc/tests/test.py
+++ b/libacc/tests/test.py
@@ -471,6 +471,13 @@
 result: 6
 ""","""""")
 
+    def testAddressOf(self):
+        self.compileCheck(["-R", "data/addressOf.c"], """Executing compiled code:
+testStruct: 10 10 10
+testArray: 1 1 1
+result: 0
+""","""""")
+
 def main():
     checkEnvironment()
     parseArgv()
diff --git a/libcutils/atomic-android-arm.S b/libcutils/atomic-android-arm.S
index c56ec5d..f4299fd 100644
--- a/libcutils/atomic-android-arm.S
+++ b/libcutils/atomic-android-arm.S
@@ -55,23 +55,8 @@
  */
  
 android_atomic_write:
-    stmdb   sp!, {r4, lr}
-    mov     r2, r1
-    mov     r1, r0
-1: @ android_atomic_write
-    ldr     r0, [r2]
-    mov     r3, #kernel_atomic_base
-#ifdef __ARM_HAVE_PC_INTERWORK
-    add     lr, pc, #4
-    add     pc, r3, #(kernel_cmpxchg - kernel_atomic_base)
-#else
-    add     r3, r3, #(kernel_cmpxchg - kernel_atomic_base)
-    mov     lr, pc
-    bx      r3
-#endif
-    bcc     1b
-    ldmia   sp!, {r4, lr}
-    bx      lr
+    str     r0, [r1]
+    bx      lr;
 
 /*
  * ----------------------------------------------------------------------------
diff --git a/libcutils/atomic-android-armv6.S b/libcutils/atomic-android-armv6.S
index 64146c1..a713089 100644
--- a/libcutils/atomic-android-armv6.S
+++ b/libcutils/atomic-android-armv6.S
@@ -45,11 +45,8 @@
  */
 
 android_atomic_write:
-1:  ldrex   r12, [r1]
-    strex   r12, r0, [r1]
-    cmp     r12, #0
-    bne     1b
-    bx      lr
+    str     r0, [r1]
+    bx      lr;
 
 /*
  * ----------------------------------------------------------------------------
diff --git a/libcutils/tztime.c b/libcutils/tztime.c
index 93bbb29..d6448a1 100644
--- a/libcutils/tztime.c
+++ b/libcutils/tztime.c
@@ -53,6 +53,31 @@
 #define OPEN_MODE	O_RDONLY
 #endif /* !defined O_BINARY */
 
+/* Complex computations to determine the min/max of time_t depending
+ * on TYPE_BIT / TYPE_SIGNED / TYPE_INTEGRAL.
+ * These macros cannot be used in pre-processor directives, so we
+ * let the C compiler do the work, which makes things a bit funky.
+ */
+static const time_t TIME_T_MAX =
+    TYPE_INTEGRAL(time_t) ?
+        ( TYPE_SIGNED(time_t) ?
+            ~((time_t)1 << (TYPE_BIT(time_t)-1))
+        :
+            ~(time_t)0
+        )
+    : /* if time_t is a floating point number */
+        ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MAX : (time_t)FLT_MAX );
+
+static const time_t TIME_T_MIN =
+    TYPE_INTEGRAL(time_t) ?
+        ( TYPE_SIGNED(time_t) ?
+            ((time_t)1 << (TYPE_BIT(time_t)-1))
+        :
+            0
+        )
+    :
+        ( sizeof(time_t) > sizeof(float) ? (time_t)DBL_MIN : (time_t)FLT_MIN );
+
 #ifndef WILDABBR
 /*
 ** Someone might make incorrect use of a time zone abbreviation:
@@ -158,7 +183,7 @@
 static struct tm *	gmtsub P((const time_t * timep, long offset,
 				struct tm * tmp));
 static struct tm *	localsub P((const time_t * timep, long offset,
-				struct tm * tmp, struct state *sp));
+				struct tm * tmp, const struct state *sp));
 static int		increment_overflow P((int * number, int delta));
 static int		leaps_thru_end_of P((int y));
 static int		long_increment_overflow P((long * number, int delta));
@@ -1157,7 +1182,7 @@
 const time_t * const	timep;
 const long		offset;
 struct tm * const	tmp;
-struct state *		sp;
+const struct state *		sp;
 {
 	register const struct ttinfo *	ttisp;
 	register int			i;
@@ -1553,26 +1578,36 @@
 
 static int
 increment_overflow(number, delta)
-int *	number;
-int	delta;
+int *   number;
+int delta;
 {
-	int	number0;
+    unsigned  number0 = (unsigned)*number;
+    unsigned  number1 = (unsigned)(number0 + delta);
 
-	number0 = *number;
-	*number += delta;
-	return (*number < number0) != (delta < 0);
+    *number = (int)number1;
+
+    if (delta >= 0) {
+        return ((int)number1 < (int)number0);
+    } else {
+        return ((int)number1 > (int)number0);
+    }
 }
 
 static int
 long_increment_overflow(number, delta)
-long *	number;
-int	delta;
+long *  number;
+int delta;
 {
-	long	number0;
+    unsigned long  number0 = (unsigned long)*number;
+    unsigned long  number1 = (unsigned long)(number0 + delta);
 
-	number0 = *number;
-	*number += delta;
-	return (*number < number0) != (delta < 0);
+    *number = (long)number1;
+
+    if (delta >= 0) {
+        return ((long)number1 < (long)number0);
+    } else {
+        return ((long)number1 > (long)number0);
+    }
 }
 
 static int
@@ -1741,14 +1776,14 @@
 		} else	dir = tmcomp(&mytm, &yourtm);
 		if (dir != 0) {
 			if (t == lo) {
+			        if (t == TIME_T_MAX)
+			             return WRONG;
 				++t;
-				if (t <= lo)
-					return WRONG;
 				++lo;
 			} else if (t == hi) {
+			        if (t == TIME_T_MIN)
+			             return WRONG;
 				--t;
-				if (t >= hi)
-					return WRONG;
 				--hi;
 			}
 			if (lo > hi)
diff --git a/libzipfile/centraldir.c b/libzipfile/centraldir.c
index 0391c09..0e264a3 100644
--- a/libzipfile/centraldir.c
+++ b/libzipfile/centraldir.c
@@ -233,7 +233,7 @@
     len = (buf+bufsize)-p;

     for (i=0; i < file->totalEntryCount; i++) {

         Zipentry* entry = malloc(sizeof(Zipentry));

-        memset(entry, sizeof(Zipentry), 0);

+        memset(entry, 0, sizeof(Zipentry));

 

         err = read_central_directory_entry(file, entry, &p, &len);

         if (err != 0) {

diff --git a/logcat/event-log-tags b/logcat/event-log-tags
index b5386d3..4db86cb 100644
--- a/logcat/event-log-tags
+++ b/logcat/event-log-tags
@@ -82,6 +82,10 @@
 # disk space free on the /data partition in bytes
 2746 free_storage_left (data|2|2)
 
+# contacts aggregation: time and number of contacts.
+# count is negative for query phase, positive for merge phase
+2747 contacts_aggregation (aggregation time|2|3), (count|1|1)
+
 # when a NotificationManager.notify is called
 2750 notification_enqueue (pkg|3),(id|1|5),(notification|3)
 # when someone tries to cancel a notification, the notification manager sometimes
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 779f2a9..e28dd30 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -5,11 +5,15 @@
 
 copy_from := \
 	etc/dbus.conf \
-	etc/init.goldfish.sh \
 	etc/hosts
 
 ifeq ($(TARGET_PRODUCT),generic)
-copy_from := etc/vold.conf
+copy_from += etc/vold.conf
+endif
+
+# for non -user build, also copy emulator-support script into /system/etc
+ifneq ($(TARGET_BUILD_VARIANT),user)
+copy_from += etc/init.goldfish.sh
 endif
 
 copy_to := $(addprefix $(TARGET_OUT)/,$(copy_from))
@@ -32,11 +36,13 @@
 ALL_PREBUILT += $(file)
 endif
 
+# for non -user build, also copy emulator-specific init script into /
+ifneq ($(TARGET_BUILD_VARIANT),user)
 file := $(TARGET_ROOT_OUT)/init.goldfish.rc
 $(file) : $(LOCAL_PATH)/etc/init.goldfish.rc | $(ACP)
 	$(transform-prebuilt-to-target)
 ALL_PREBUILT += $(file)
-	
+endif
 
 # create some directories (some are mount points)
 DIRS := $(addprefix $(TARGET_ROOT_OUT)/, \
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 7d9869f..5d0c8b5 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -70,26 +70,24 @@
     # storing dumps on platforms which do not have a dedicated dump partition.
    
     mkdir /data/dontpanic
-    chmod 0770 /data/dontpanic
+    chown root system /data/dontpanic
+    chmod 0750 /data/dontpanic
 
     # Collect apanic data, free resources and re-arm trigger
     copy /proc/apanic_console /data/dontpanic/apanic_console
     chown root system /data/dontpanic/apanic_console
-    # STOPSHIP!
-    chmod 0664 /data/dontpanic/apanic_console
+    chmod 0640 /data/dontpanic/apanic_console
 
     copy /proc/apanic_threads /data/dontpanic/apanic_threads
     chown root system /data/dontpanic/apanic_threads
-    # STOPSHIP!
-    chmod 0664 /data/dontpanic/apanic_threads
+    chmod 0640 /data/dontpanic/apanic_threads
 
     write /proc/apanic_console 1
 
     # Collect ramconsole data
     copy /proc/last_kmsg /data/dontpanic/last_kmsg
     chown root system /data/dontpanic/last_kmsg
-    # STOPSHIP!
-    chmod 0664 /data/dontpanic/last_kmsg
+    chmod 0640 /data/dontpanic/last_kmsg
 
     # Same reason as /data above
     mount yaffs2 mtd@cache /cache nosuid nodev
diff --git a/vold/volmgr_vfat.c b/vold/volmgr_vfat.c
index 22e2dcf..4c695e4 100644
--- a/vold/volmgr_vfat.c
+++ b/vold/volmgr_vfat.c
@@ -18,6 +18,7 @@
 #include <errno.h>
 
 #include <sys/mount.h>
+#include <cutils/properties.h>
 
 #include "vold.h"
 #include "volmgr.h"
@@ -108,14 +109,29 @@
     }
 
     /*
-     * The mount masks restrict access so that:
-     * 1. The 'system' user cannot access the SD card at all - 
-     *    (protects system_server from grabbing file references)
-     * 2. Group users can RWX
-     * 3. Others can only RX
+     * Note: This is a temporary hack. If the sampling profiler is enabled,
+     * we make the SD card world-writable so any process can write snapshots.
+     *
+     * TODO: Remove this code once we have a drop box in system_server.
      */
-    rc = mount(devpath, vol->mount_point, "vfat", flags,
-               "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed");
+    char value[PROPERTY_VALUE_MAX];
+    property_get("persist.sampling_profiler", value, "");
+    if (value[0] == '1') {
+        LOGW("The SD card is world-writable because the"
+            " 'persist.sampling_profiler' system property is set to '1'.");
+        rc = mount(devpath, vol->mount_point, "vfat", flags,
+                "utf8,uid=1000,gid=1015,fmask=000,dmask=000,shortname=mixed");
+    } else {
+        /*
+         * The mount masks restrict access so that:
+         * 1. The 'system' user cannot access the SD card at all -
+         *    (protects system_server from grabbing file references)
+         * 2. Group users can RWX
+         * 3. Others can only RX
+         */
+        rc = mount(devpath, vol->mount_point, "vfat", flags,
+                "utf8,uid=1000,gid=1015,fmask=702,dmask=702,shortname=mixed");
+    }
 
     if (rc && errno == EROFS) {
         LOGE("vfat_mount(%d:%d, %s): Read only filesystem - retrying mount RO",