Make wide-volatile loads and stores atomic.

This implements the four wide-volatile instructions added in a previous
change, and modifies the verifier to substitute the opcodes into the
instruction stream when appropriate.

For mterp, the ARM wide get/put instructions now have conditional code
that replaces ldrd/strd with a call to the quasiatomic functions.  The
C version does essentially the same thing.  ARMv4T lacks ldrd/stdrd, and
uses separate implementations for the wide field accesses, so those were
updated as well.  x86 will just use stubs.

The JIT should punt these to the interpreter.

Change-Id: Ife88559ed1a698c3267d43c454896f6b12081c0f
Also:
 - We don't seem to be using the negative widths in the instruction
   table.  Not sure they're useful anymore.
 - Tabs -> spaces in x86-atom throw-verification-error impl.
diff --git a/docs/verifier.html b/docs/verifier.html
index 022923b..21bbdf0 100644
--- a/docs/verifier.html
+++ b/docs/verifier.html
@@ -45,6 +45,10 @@
     it's very helpful to start with the assumption that the bytecode
     is valid.
 </ol>
+<p>
+It's also a convenient framework to deal with certain situations, notably
+replacement of instructions that access volatile 64-bit fields with
+more rigorous versions that guarantee atomicity.
 
 
 <h2>Verifier Differences</h2>
diff --git a/libdex/InstrUtils.c b/libdex/InstrUtils.c
index 05faf23..8961ce5 100644
--- a/libdex/InstrUtils.c
+++ b/libdex/InstrUtils.c
@@ -35,6 +35,9 @@
  *
  * (To save space in the binary we could generate a static table with a
  * command-line utility.)
+ *
+ * TODO: it doesn't look like we're using the negative values anymore.
+ * Consider switching to only positive values.
  */
 InstructionWidth* dexCreateInstrWidthTable(void)
 {
diff --git a/libdex/InstrUtils.h b/libdex/InstrUtils.h
index 8449ae5..0c4e162 100644
--- a/libdex/InstrUtils.h
+++ b/libdex/InstrUtils.h
@@ -111,6 +111,7 @@
  */
 InstructionWidth* dexCreateInstrWidthTable(void);
 
+#if 0       // no longer used
 /*
  * Returns the width of the specified instruction, or 0 if not defined.
  * Optimized instructions use negative values.
@@ -120,6 +121,7 @@
    // assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
     return widths[opCode];
 }
+#endif
 
 /*
  * Return the width of the specified instruction, or 0 if not defined.
@@ -128,7 +130,7 @@
 {
     //assert(/*opCode >= 0 &&*/ opCode < kNumDalvikInstructions);
 
-    int val = dexGetInstrWidth(widths, opCode);
+    int val = widths[opCode];
     if (val < 0)
         val = -val;
     /* XXX - the no-compare trick may be a cycle slower on ARM */
diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c
index 7ef559b..8187354 100644
--- a/vm/analysis/CodeVerify.c
+++ b/vm/analysis/CodeVerify.c
@@ -2921,6 +2921,10 @@
  * Replace an instruction with "throw-verification-error".  This allows us to
  * defer error reporting until the code path is first used.
  *
+ * This is expected to be called during "just in time" verification, not
+ * from within dexopt.  (Verification failures in dexopt will result in
+ * postponement of verification to first use of the class.)
+ *
  * The throw-verification-error instruction requires two code units.  Some
  * of the replaced instructions require three; the third code unit will
  * receive a "nop".  The instruction's length will be left unchanged
@@ -2942,8 +2946,6 @@
     u2 oldInsn = *oldInsns;
     bool result = false;
 
-    //dvmMakeCodeReadWrite(meth);
-
     //LOGD("  was 0x%04x\n", oldInsn);
     u2* newInsns = (u2*) meth->insns + insnIdx;
 
@@ -3040,10 +3042,53 @@
     result = true;
 
 bail:
-    //dvmMakeCodeReadOnly(meth);
     return result;
 }
 
+/*
+ * Replace {iget,iput,sget,sput}-wide with the -wide-volatile form.
+ *
+ * If this is called during dexopt, we can modify the instruction in
+ * place.  If this happens during just-in-time verification, we need to
+ * use the DEX read/write page feature.
+ *
+ * NOTE:
+ * This shouldn't really be tied to verification.  It ought to be a
+ * separate pass that is run before or after the verifier.  However, that
+ * requires a bunch of extra code, and the only advantage of doing so is
+ * that the feature isn't disabled when verification is turned off.  At
+ * some point we may need to revisit this choice.
+ */
+static void replaceVolatileInstruction(Method* meth, InsnFlags* insnFlags,
+    int insnIdx)
+{
+    u2* oldInsns = (u2*)meth->insns + insnIdx;
+    u2 oldInsn = *oldInsns;
+    u2 newVal;
+
+    switch (oldInsn & 0xff) {
+    case OP_IGET_WIDE:  newVal = OP_IGET_WIDE_VOLATILE;     break;
+    case OP_IPUT_WIDE:  newVal = OP_IPUT_WIDE_VOLATILE;     break;
+    case OP_SGET_WIDE:  newVal = OP_SGET_WIDE_VOLATILE;     break;
+    case OP_SPUT_WIDE:  newVal = OP_SPUT_WIDE_VOLATILE;     break;
+    default:
+        LOGE("wide-volatile op mismatch (0x%x)\n", oldInsn);
+        dvmAbort();
+        return;     // in-lieu-of noreturn attribute
+    }
+
+    /* merge new opcode into 16-bit code unit */
+    newVal |= (oldInsn & 0xff00);
+
+    if (gDvm.optimizing) {
+        /* dexopt time, alter the output */
+        *oldInsns = newVal;
+    } else {
+        /* runtime, make the page read/write */
+        dvmDexChangeDex2(meth->clazz->pDvmDex, oldInsns, newVal);
+    }
+}
+
 
 /*
  * ===========================================================================
@@ -4472,6 +4517,7 @@
         }
         break;
     case OP_IGET_WIDE:
+    case OP_IGET_WIDE_VOLATILE:
         {
             RegType dstType;
             ClassObject* fieldClass;
@@ -4506,6 +4552,13 @@
                 setRegisterType(workRegs, insnRegCount, decInsn.vA,
                     dstType, &failure);
             }
+            if (VERIFY_OK(failure)) {
+                if (decInsn.opCode != OP_IGET_WIDE_VOLATILE &&
+                    dvmIsVolatileField(&instField->field))
+                {
+                    replaceVolatileInstruction(meth, insnFlags, insnIdx);
+                }
+            }
         }
         break;
     case OP_IGET_OBJECT:
@@ -4602,6 +4655,7 @@
         }
         break;
     case OP_IPUT_WIDE:
+    case OP_IPUT_WIDE_VOLATILE:
         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
         if (VERIFY_OK(failure)) {
             RegType typeHi =
@@ -4639,6 +4693,13 @@
                 failure = VERIFY_ERROR_GENERIC;
                 break;
             }
+            if (VERIFY_OK(failure)) {
+                if (decInsn.opCode != OP_IPUT_WIDE_VOLATILE &&
+                    dvmIsVolatileField(&instField->field))
+                {
+                    replaceVolatileInstruction(meth, insnFlags, insnIdx);
+                }
+            }
         }
         break;
     case OP_IPUT_OBJECT:
@@ -4748,6 +4809,7 @@
         }
         break;
     case OP_SGET_WIDE:
+    case OP_SGET_WIDE_VOLATILE:
         {
             StaticField* staticField;
             RegType dstType;
@@ -4775,6 +4837,13 @@
                 setRegisterType(workRegs, insnRegCount, decInsn.vA,
                     dstType, &failure);
             }
+            if (VERIFY_OK(failure)) {
+                if (decInsn.opCode != OP_SGET_WIDE_VOLATILE &&
+                    dvmIsVolatileField(&staticField->field))
+                {
+                    replaceVolatileInstruction(meth, insnFlags, insnIdx);
+                }
+            }
         }
         break;
     case OP_SGET_OBJECT:
@@ -4864,6 +4933,7 @@
         }
         break;
     case OP_SPUT_WIDE:
+    case OP_SPUT_WIDE_VOLATILE:
         tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
         if (VERIFY_OK(failure)) {
             RegType typeHi =
@@ -4894,6 +4964,13 @@
                 failure = VERIFY_ERROR_GENERIC;
                 break;
             }
+            if (VERIFY_OK(failure)) {
+                if (decInsn.opCode != OP_SPUT_WIDE_VOLATILE &&
+                    dvmIsVolatileField(&staticField->field))
+                {
+                    replaceVolatileInstruction(meth, insnFlags, insnIdx);
+                }
+            }
         }
         break;
     case OP_SPUT_OBJECT:
@@ -5420,10 +5497,6 @@
     case OP_IPUT_QUICK:
     case OP_IPUT_WIDE_QUICK:
     case OP_IPUT_OBJECT_QUICK:
-    case OP_IGET_WIDE_VOLATILE:
-    case OP_IPUT_WIDE_VOLATILE:
-    case OP_SGET_WIDE_VOLATILE:
-    case OP_SPUT_WIDE_VOLATILE:
     case OP_INVOKE_VIRTUAL_QUICK:
     case OP_INVOKE_VIRTUAL_QUICK_RANGE:
     case OP_INVOKE_SUPER_QUICK:
diff --git a/vm/analysis/DexOptimize.c b/vm/analysis/DexOptimize.c
index a5b8b6f..ae1edfc 100644
--- a/vm/analysis/DexOptimize.c
+++ b/vm/analysis/DexOptimize.c
@@ -1667,7 +1667,7 @@
             u4 len = insns[2] | (((u4)insns[3]) << 16);
             width = 4 + (elemWidth * len + 1) / 2;
         } else {
-            width = dexGetInstrWidth(gDvm.instrWidth, inst);
+            width = dexGetInstrWidthAbs(gDvm.instrWidth, inst);
         }
         assert(width > 0);
 
diff --git a/vm/mterp/armv4t/OP_IGET_WIDE.S b/vm/mterp/armv4t/OP_IGET_WIDE.S
index 576b43d..dabaeba 100644
--- a/vm/mterp/armv4t/OP_IGET_WIDE.S
+++ b/vm/mterp/armv4t/OP_IGET_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
 %verify "executed"
 %verify "null object"
 %verify "field already resolved"
@@ -33,11 +34,16 @@
     cmp     r9, #0                      @ check object for null
     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
     beq     common_errNullObject        @ object was null
-    mov     r2, rINST, lsr #8           @ r2<- A+
+    .if $volatile
+    add     r0, r9, r3                  @ r0<- address of field
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
     add     r9, r9, r3                  @ r9<- obj + field offset
     ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64-bit align ok)
-    and     r2, r2, #15                 @ r2<- A
+    .endif
+    mov     r2, rINST, lsr #8           @ r2<- A+
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
diff --git a/vm/mterp/armv4t/OP_IGET_WIDE_VOLATILE.S b/vm/mterp/armv4t/OP_IGET_WIDE_VOLATILE.S
new file mode 100644
index 0000000..cdd8708
--- /dev/null
+++ b/vm/mterp/armv4t/OP_IGET_WIDE_VOLATILE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv4t/OP_IGET_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv4t/OP_IPUT_WIDE.S b/vm/mterp/armv4t/OP_IPUT_WIDE.S
index c4b43b3..d824d9d 100644
--- a/vm/mterp/armv4t/OP_IPUT_WIDE.S
+++ b/vm/mterp/armv4t/OP_IPUT_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
 %verify "executed"
 %verify "null object"
 %verify "field already resolved"
@@ -35,8 +36,12 @@
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    add     r9, r9, r3                  @ r9<- object + byte offset
-    stmia   r9, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    add     r2, r9, r3                  @ r2<- object + byte offset
+    .if $volatile
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    stmia   r2, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
diff --git a/vm/mterp/armv4t/OP_IPUT_WIDE_VOLATILE.S b/vm/mterp/armv4t/OP_IPUT_WIDE_VOLATILE.S
new file mode 100644
index 0000000..6b297f0
--- /dev/null
+++ b/vm/mterp/armv4t/OP_IPUT_WIDE_VOLATILE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv4t/OP_IPUT_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv4t/OP_SGET_WIDE.S b/vm/mterp/armv4t/OP_SGET_WIDE.S
index 61a7a43..2556a7c 100644
--- a/vm/mterp/armv4t/OP_SGET_WIDE.S
+++ b/vm/mterp/armv4t/OP_SGET_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
 %verify "executed"
 %verify "field already resolved"
 %verify "field not yet resolved"
@@ -13,12 +14,16 @@
     cmp     r0, #0                      @ is resolved entry null?
     beq     .L${opcode}_resolve         @ yes, do resolve
 .L${opcode}_finish:
-    mov     r1, rINST, lsr #8           @ r1<- AA
-    add     r0, r0, #offStaticField_value
-    ldmia   r0, {r2-r3}                 @ r2/r3<- field value (aligned)
-    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    add     r0, r0, #offStaticField_value @ r0<- pointer to data
+    .if $volatile
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldmia   r0, {r0-r1}                 @ r0/r1<- field value (aligned)
+    .endif
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 %break
@@ -26,6 +31,8 @@
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
+     *
+     * Returns StaticField pointer in r0.
      */
 .L${opcode}_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
diff --git a/vm/mterp/armv4t/OP_SGET_WIDE_VOLATILE.S b/vm/mterp/armv4t/OP_SGET_WIDE_VOLATILE.S
new file mode 100644
index 0000000..5615ab6
--- /dev/null
+++ b/vm/mterp/armv4t/OP_SGET_WIDE_VOLATILE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv4t/OP_SGET_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv4t/OP_SPUT_WIDE.S b/vm/mterp/armv4t/OP_SPUT_WIDE.S
index b90cf50..237233c 100644
--- a/vm/mterp/armv4t/OP_SPUT_WIDE.S
+++ b/vm/mterp/armv4t/OP_SPUT_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
 %verify "executed"
 %verify "field already resolved"
 %verify "field not yet resolved"
@@ -6,27 +7,33 @@
      * 64-bit SPUT handler.
      */
     /* sput-wide vAA, field@BBBB */
-    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- DvmDex
     FETCH(r1, 1)                        @ r1<- field ref BBBB
-    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
     mov     r9, rINST, lsr #8           @ r9<- AA
-    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
-    cmp     r0, #0                      @ is resolved entry null?
+    cmp     r2, #0                      @ is resolved entry null?
     beq     .L${opcode}_resolve         @ yes, do resolve
-.L${opcode}_finish: @ field ptr in r0, AA in r9
+.L${opcode}_finish: @ field ptr in r2, AA in r9
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    add     r0, r0, #offStaticField_value
-    stmia   r0, {r2-r3}                 @ field<- vAA/vAA+1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    add     r2, r2, #offStaticField_value @ r2<- pointer to data
+    .if $volatile
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    stmia   r2, {r0-r1}                 @ field<- vAA/vAA+1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 %break
 
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
      *  r9: &fp[AA]
+     *
+     * Returns StaticField pointer in r2.
      */
 .L${opcode}_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -34,6 +41,7 @@
     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
+    mov     r2, r0                      @ copy to r2
     bne     .L${opcode}_finish          @ yes, finish
     b       common_exceptionThrown      @ no, handle exception
 
diff --git a/vm/mterp/armv4t/OP_SPUT_WIDE_VOLATILE.S b/vm/mterp/armv4t/OP_SPUT_WIDE_VOLATILE.S
new file mode 100644
index 0000000..850e83b
--- /dev/null
+++ b/vm/mterp/armv4t/OP_SPUT_WIDE_VOLATILE.S
@@ -0,0 +1,2 @@
+%verify "executed"
+%include "armv4t/OP_SPUT_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv5te/OP_IGET_WIDE.S b/vm/mterp/armv5te/OP_IGET_WIDE.S
index 22377d9..6d3eb45 100644
--- a/vm/mterp/armv5te/OP_IGET_WIDE.S
+++ b/vm/mterp/armv5te/OP_IGET_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
 %verify "executed"
 %verify "null object"
 %verify "field already resolved"
@@ -33,10 +34,15 @@
     cmp     r9, #0                      @ check object for null
     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
     beq     common_errNullObject        @ object was null
-    mov     r2, rINST, lsr #8           @ r2<- A+
+    .if $volatile
+    add     r0, r9, r3                  @ r0<- address of field
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
-    and     r2, r2, #15                 @ r2<- A
+    .endif
+    mov     r2, rINST, lsr #8           @ r2<- A+
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
diff --git a/vm/mterp/armv5te/OP_IGET_WIDE_VOLATILE.S b/vm/mterp/armv5te/OP_IGET_WIDE_VOLATILE.S
index f7d5254..face363 100644
--- a/vm/mterp/armv5te/OP_IGET_WIDE_VOLATILE.S
+++ b/vm/mterp/armv5te/OP_IGET_WIDE_VOLATILE.S
@@ -1,2 +1,2 @@
 %verify "executed"
-%include "armv5te/OP_IGET_WIDE.S"
+%include "armv5te/OP_IGET_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv5te/OP_IPUT_WIDE.S b/vm/mterp/armv5te/OP_IPUT_WIDE.S
index 75465ec..763c6a8 100644
--- a/vm/mterp/armv5te/OP_IPUT_WIDE.S
+++ b/vm/mterp/armv5te/OP_IPUT_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
 %verify "executed"
 %verify "null object"
 %verify "field already resolved"
@@ -35,7 +36,12 @@
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if $volatile
+    add     r2, r9, r3                  @ r2<- target address
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
diff --git a/vm/mterp/armv5te/OP_IPUT_WIDE_VOLATILE.S b/vm/mterp/armv5te/OP_IPUT_WIDE_VOLATILE.S
index 2de16c8..944811b 100644
--- a/vm/mterp/armv5te/OP_IPUT_WIDE_VOLATILE.S
+++ b/vm/mterp/armv5te/OP_IPUT_WIDE_VOLATILE.S
@@ -1,2 +1,2 @@
 %verify "executed"
-%include "armv5te/OP_IPUT_WIDE.S"
+%include "armv5te/OP_IPUT_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv5te/OP_SGET_WIDE.S b/vm/mterp/armv5te/OP_SGET_WIDE.S
index 1f93a2f..ff0238c 100644
--- a/vm/mterp/armv5te/OP_SGET_WIDE.S
+++ b/vm/mterp/armv5te/OP_SGET_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
 %verify "executed"
 %verify "field already resolved"
 %verify "field not yet resolved"
@@ -13,11 +14,16 @@
     cmp     r0, #0                      @ is resolved entry null?
     beq     .L${opcode}_resolve         @ yes, do resolve
 .L${opcode}_finish:
-    mov     r1, rINST, lsr #8           @ r1<- AA
-    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
-    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    .if $volatile
+    add     r0, r0, #offStaticField_value @ r0<- pointer to data
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+    .endif
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 %break
@@ -25,6 +31,8 @@
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
+     *
+     * Returns StaticField pointer in r0.
      */
 .L${opcode}_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
diff --git a/vm/mterp/armv5te/OP_SGET_WIDE_VOLATILE.S b/vm/mterp/armv5te/OP_SGET_WIDE_VOLATILE.S
index 964c8b1..b852348 100644
--- a/vm/mterp/armv5te/OP_SGET_WIDE_VOLATILE.S
+++ b/vm/mterp/armv5te/OP_SGET_WIDE_VOLATILE.S
@@ -1,2 +1,2 @@
 %verify "executed"
-%include "armv5te/OP_SGET_WIDE.S"
+%include "armv5te/OP_SGET_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/armv5te/OP_SPUT_WIDE.S b/vm/mterp/armv5te/OP_SPUT_WIDE.S
index a7bc5f2..69b106c 100644
--- a/vm/mterp/armv5te/OP_SPUT_WIDE.S
+++ b/vm/mterp/armv5te/OP_SPUT_WIDE.S
@@ -1,3 +1,4 @@
+%default {"volatile":"0"}
 %verify "executed"
 %verify "field already resolved"
 %verify "field not yet resolved"
@@ -6,26 +7,33 @@
      * 64-bit SPUT handler.
      */
     /* sput-wide vAA, field@BBBB */
-    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
     FETCH(r1, 1)                        @ r1<- field ref BBBB
-    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
     mov     r9, rINST, lsr #8           @ r9<- AA
-    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
-    cmp     r0, #0                      @ is resolved entry null?
+    cmp     r2, #0                      @ is resolved entry null?
     beq     .L${opcode}_resolve         @ yes, do resolve
-.L${opcode}_finish: @ field ptr in r0, AA in r9
+.L${opcode}_finish: @ field ptr in r2, AA in r9
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if $volatile
+    add     r2, r2, #offStaticField_value @ r2<- pointer to data
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 %break
 
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
      *  r9: &fp[AA]
+     *
+     * Returns StaticField pointer in r2.
      */
 .L${opcode}_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -33,6 +41,7 @@
     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
+    mov     r2, r0                      @ copy to r2
     bne     .L${opcode}_finish          @ yes, finish
     b       common_exceptionThrown      @ no, handle exception
 
diff --git a/vm/mterp/armv5te/OP_SPUT_WIDE_VOLATILE.S b/vm/mterp/armv5te/OP_SPUT_WIDE_VOLATILE.S
index 7c618f1..a88de85 100644
--- a/vm/mterp/armv5te/OP_SPUT_WIDE_VOLATILE.S
+++ b/vm/mterp/armv5te/OP_SPUT_WIDE_VOLATILE.S
@@ -1,2 +1,2 @@
 %verify "executed"
-%include "armv5te/OP_SPUT_WIDE.S"
+%include "armv5te/OP_SPUT_WIDE.S" {"volatile":"1"}
diff --git a/vm/mterp/c/OP_IGET_WIDE_VOLATILE.c b/vm/mterp/c/OP_IGET_WIDE_VOLATILE.c
index 954c2d7..a080823 100644
--- a/vm/mterp/c/OP_IGET_WIDE_VOLATILE.c
+++ b/vm/mterp/c/OP_IGET_WIDE_VOLATILE.c
@@ -1,2 +1,2 @@
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
diff --git a/vm/mterp/c/OP_IPUT_WIDE_VOLATILE.c b/vm/mterp/c/OP_IPUT_WIDE_VOLATILE.c
index a0c015b..d888b4a 100644
--- a/vm/mterp/c/OP_IPUT_WIDE_VOLATILE.c
+++ b/vm/mterp/c/OP_IPUT_WIDE_VOLATILE.c
@@ -1,2 +1,2 @@
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
diff --git a/vm/mterp/c/OP_SGET_WIDE_VOLATILE.c b/vm/mterp/c/OP_SGET_WIDE_VOLATILE.c
index b7812fa..26a67bf 100644
--- a/vm/mterp/c/OP_SGET_WIDE_VOLATILE.c
+++ b/vm/mterp/c/OP_SGET_WIDE_VOLATILE.c
@@ -1,2 +1,2 @@
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
diff --git a/vm/mterp/c/OP_SPUT_WIDE_VOLATILE.c b/vm/mterp/c/OP_SPUT_WIDE_VOLATILE.c
index 684099c..bdf552c 100644
--- a/vm/mterp/c/OP_SPUT_WIDE_VOLATILE.c
+++ b/vm/mterp/c/OP_SPUT_WIDE_VOLATILE.c
@@ -1,2 +1,2 @@
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
diff --git a/vm/mterp/config-armv4t b/vm/mterp/config-armv4t
index 01eddb2..9746376 100644
--- a/vm/mterp/config-armv4t
+++ b/vm/mterp/config-armv4t
@@ -50,6 +50,10 @@
     op OP_IPUT_WIDE_QUICK armv4t
     op OP_SGET_WIDE armv4t
     op OP_SPUT_WIDE armv4t
+    op OP_IGET_WIDE_VOLATILE armv4t
+    op OP_IPUT_WIDE_VOLATILE armv4t
+    op OP_SGET_WIDE_VOLATILE armv4t
+    op OP_SPUT_WIDE_VOLATILE armv4t
 op-end
 
 # "helper" code for C; include if you use any of the C stubs (this generates
diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S
index 6068de5..302e9c8 100644
--- a/vm/mterp/out/InterpAsm-armv4t.S
+++ b/vm/mterp/out/InterpAsm-armv4t.S
@@ -2888,12 +2888,16 @@
     cmp     r0, #0                      @ is resolved entry null?
     beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
 .LOP_SGET_WIDE_finish:
-    mov     r1, rINST, lsr #8           @ r1<- AA
-    add     r0, r0, #offStaticField_value
-    ldmia   r0, {r2-r3}                 @ r2/r3<- field value (aligned)
-    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    add     r0, r0, #offStaticField_value @ r0<- pointer to data
+    .if 0
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldmia   r0, {r0-r1}                 @ r0/r1<- field value (aligned)
+    .endif
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -3059,21 +3063,25 @@
      * 64-bit SPUT handler.
      */
     /* sput-wide vAA, field@BBBB */
-    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- DvmDex
     FETCH(r1, 1)                        @ r1<- field ref BBBB
-    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
     mov     r9, rINST, lsr #8           @ r9<- AA
-    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
-    cmp     r0, #0                      @ is resolved entry null?
+    cmp     r2, #0                      @ is resolved entry null?
     beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
-.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    add     r0, r0, #offStaticField_value
-    stmia   r0, {r2-r3}                 @ field<- vAA/vAA+1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    add     r2, r2, #offStaticField_value @ r2<- pointer to data
+    .if 0
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    stmia   r2, {r0-r1}                 @ field<- vAA/vAA+1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 /* ------------------------------ */
     .balign 64
@@ -7591,8 +7599,8 @@
 /* ------------------------------ */
     .balign 64
 .L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
-/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
-/* File: armv5te/OP_IGET_WIDE.S */
+/* File: armv4t/OP_IGET_WIDE_VOLATILE.S */
+/* File: armv4t/OP_IGET_WIDE.S */
     /*
      * Wide 32-bit instance field get.
      */
@@ -7617,8 +7625,8 @@
 /* ------------------------------ */
     .balign 64
 .L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
-/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
-/* File: armv5te/OP_IPUT_WIDE.S */
+/* File: armv4t/OP_IPUT_WIDE_VOLATILE.S */
+/* File: armv4t/OP_IPUT_WIDE.S */
     /* iput-wide vA, vB, field@CCCC */
     mov     r0, rINST, lsr #12          @ r0<- B
     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
@@ -7640,8 +7648,8 @@
 /* ------------------------------ */
     .balign 64
 .L_OP_SGET_WIDE_VOLATILE: /* 0xea */
-/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
-/* File: armv5te/OP_SGET_WIDE.S */
+/* File: armv4t/OP_SGET_WIDE_VOLATILE.S */
+/* File: armv4t/OP_SGET_WIDE.S */
     /*
      * 64-bit SGET handler.
      */
@@ -7653,11 +7661,16 @@
     cmp     r0, #0                      @ is resolved entry null?
     beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
 .LOP_SGET_WIDE_VOLATILE_finish:
-    mov     r1, rINST, lsr #8           @ r1<- AA
-    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
-    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    add     r0, r0, #offStaticField_value @ r0<- pointer to data
+    .if 1
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldmia   r0, {r0-r1}                 @ r0/r1<- field value (aligned)
+    .endif
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -7665,26 +7678,31 @@
 /* ------------------------------ */
     .balign 64
 .L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
-/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
-/* File: armv5te/OP_SPUT_WIDE.S */
+/* File: armv4t/OP_SPUT_WIDE_VOLATILE.S */
+/* File: armv4t/OP_SPUT_WIDE.S */
     /*
      * 64-bit SPUT handler.
      */
     /* sput-wide vAA, field@BBBB */
-    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- DvmDex
     FETCH(r1, 1)                        @ r1<- field ref BBBB
-    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
     mov     r9, rINST, lsr #8           @ r9<- AA
-    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
-    cmp     r0, #0                      @ is resolved entry null?
+    cmp     r2, #0                      @ is resolved entry null?
     beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
-.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    add     r2, r2, #offStaticField_value @ r2<- pointer to data
+    .if 1
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    stmia   r2, {r0-r1}                 @ field<- vAA/vAA+1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 
 /* ------------------------------ */
@@ -8744,11 +8762,16 @@
     cmp     r9, #0                      @ check object for null
     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
     beq     common_errNullObject        @ object was null
-    mov     r2, rINST, lsr #8           @ r2<- A+
+    .if 0
+    add     r0, r9, r3                  @ r0<- address of field
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
     add     r9, r9, r3                  @ r9<- obj + field offset
     ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64-bit align ok)
-    and     r2, r2, #15                 @ r2<- A
+    .endif
+    mov     r2, rINST, lsr #8           @ r2<- A+
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
@@ -8897,10 +8920,14 @@
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    add     r9, r9, r3                  @ r9<- object + byte offset
-    stmia   r9, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    add     r2, r9, r3                  @ r2<- object + byte offset
+    .if 0
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    stmia   r2, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 
 /* continuation for OP_IPUT_OBJECT */
@@ -9029,6 +9056,8 @@
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
+     *
+     * Returns StaticField pointer in r0.
      */
 .LOP_SGET_WIDE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -9142,6 +9171,8 @@
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
      *  r9: &fp[AA]
+     *
+     * Returns StaticField pointer in r2.
      */
 .LOP_SPUT_WIDE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -9149,6 +9180,7 @@
     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
+    mov     r2, r0                      @ copy to r2
     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
     b       common_exceptionThrown      @ no, handle exception
 
@@ -9534,10 +9566,16 @@
     cmp     r9, #0                      @ check object for null
     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
     beq     common_errNullObject        @ object was null
+    .if 1
+    add     r0, r9, r3                  @ r0<- address of field
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    add     r9, r9, r3                  @ r9<- obj + field offset
+    ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64-bit align ok)
+    .endif
     mov     r2, rINST, lsr #8           @ r2<- A+
-    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
-    and     r2, r2, #15                 @ r2<- A
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
@@ -9560,9 +9598,14 @@
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    add     r2, r9, r3                  @ r2<- object + byte offset
+    .if 1
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    stmia   r2, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 
 /* continuation for OP_SGET_WIDE_VOLATILE */
@@ -9570,6 +9613,8 @@
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
+     *
+     * Returns StaticField pointer in r0.
      */
 .LOP_SGET_WIDE_VOLATILE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -9587,6 +9632,8 @@
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
      *  r9: &fp[AA]
+     *
+     * Returns StaticField pointer in r2.
      */
 .LOP_SPUT_WIDE_VOLATILE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -9594,6 +9641,7 @@
     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
+    mov     r2, r0                      @ copy to r2
     bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
     b       common_exceptionThrown      @ no, handle exception
 
diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S
index 6ab1a37..f886355 100644
--- a/vm/mterp/out/InterpAsm-armv5te-vfp.S
+++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S
@@ -2868,11 +2868,16 @@
     cmp     r0, #0                      @ is resolved entry null?
     beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
 .LOP_SGET_WIDE_finish:
-    mov     r1, rINST, lsr #8           @ r1<- AA
-    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
-    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    .if 0
+    add     r0, r0, #offStaticField_value @ r0<- pointer to data
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+    .endif
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -3038,20 +3043,25 @@
      * 64-bit SPUT handler.
      */
     /* sput-wide vAA, field@BBBB */
-    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
     FETCH(r1, 1)                        @ r1<- field ref BBBB
-    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
     mov     r9, rINST, lsr #8           @ r9<- AA
-    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
-    cmp     r0, #0                      @ is resolved entry null?
+    cmp     r2, #0                      @ is resolved entry null?
     beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
-.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 0
+    add     r2, r2, #offStaticField_value @ r2<- pointer to data
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 /* ------------------------------ */
     .balign 64
@@ -7313,11 +7323,16 @@
     cmp     r0, #0                      @ is resolved entry null?
     beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
 .LOP_SGET_WIDE_VOLATILE_finish:
-    mov     r1, rINST, lsr #8           @ r1<- AA
-    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
-    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    .if 1
+    add     r0, r0, #offStaticField_value @ r0<- pointer to data
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+    .endif
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -7331,20 +7346,25 @@
      * 64-bit SPUT handler.
      */
     /* sput-wide vAA, field@BBBB */
-    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
     FETCH(r1, 1)                        @ r1<- field ref BBBB
-    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
     mov     r9, rINST, lsr #8           @ r9<- AA
-    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
-    cmp     r0, #0                      @ is resolved entry null?
+    cmp     r2, #0                      @ is resolved entry null?
     beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
-.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 1
+    add     r2, r2, #offStaticField_value @ r2<- pointer to data
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 
 /* ------------------------------ */
@@ -8264,10 +8284,15 @@
     cmp     r9, #0                      @ check object for null
     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
     beq     common_errNullObject        @ object was null
-    mov     r2, rINST, lsr #8           @ r2<- A+
+    .if 0
+    add     r0, r9, r3                  @ r0<- address of field
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
-    and     r2, r2, #15                 @ r2<- A
+    .endif
+    mov     r2, rINST, lsr #8           @ r2<- A+
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
@@ -8416,9 +8441,14 @@
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 0
+    add     r2, r9, r3                  @ r2<- target address
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 
 /* continuation for OP_IPUT_OBJECT */
@@ -8547,6 +8577,8 @@
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
+     *
+     * Returns StaticField pointer in r0.
      */
 .LOP_SGET_WIDE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -8660,6 +8692,8 @@
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
      *  r9: &fp[AA]
+     *
+     * Returns StaticField pointer in r2.
      */
 .LOP_SPUT_WIDE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -8667,6 +8701,7 @@
     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
+    mov     r2, r0                      @ copy to r2
     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
     b       common_exceptionThrown      @ no, handle exception
 
@@ -9052,10 +9087,15 @@
     cmp     r9, #0                      @ check object for null
     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
     beq     common_errNullObject        @ object was null
-    mov     r2, rINST, lsr #8           @ r2<- A+
+    .if 1
+    add     r0, r9, r3                  @ r0<- address of field
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
-    and     r2, r2, #15                 @ r2<- A
+    .endif
+    mov     r2, rINST, lsr #8           @ r2<- A+
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
@@ -9078,9 +9118,14 @@
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 1
+    add     r2, r9, r3                  @ r2<- target address
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 
 /* continuation for OP_SGET_WIDE_VOLATILE */
@@ -9088,6 +9133,8 @@
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
+     *
+     * Returns StaticField pointer in r0.
      */
 .LOP_SGET_WIDE_VOLATILE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -9105,6 +9152,8 @@
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
      *  r9: &fp[AA]
+     *
+     * Returns StaticField pointer in r2.
      */
 .LOP_SPUT_WIDE_VOLATILE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -9112,6 +9161,7 @@
     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
+    mov     r2, r0                      @ copy to r2
     bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
     b       common_exceptionThrown      @ no, handle exception
 
diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S
index 6990b44..c21aee7 100644
--- a/vm/mterp/out/InterpAsm-armv5te.S
+++ b/vm/mterp/out/InterpAsm-armv5te.S
@@ -2890,11 +2890,16 @@
     cmp     r0, #0                      @ is resolved entry null?
     beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
 .LOP_SGET_WIDE_finish:
-    mov     r1, rINST, lsr #8           @ r1<- AA
-    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
-    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    .if 0
+    add     r0, r0, #offStaticField_value @ r0<- pointer to data
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+    .endif
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -3060,20 +3065,25 @@
      * 64-bit SPUT handler.
      */
     /* sput-wide vAA, field@BBBB */
-    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
     FETCH(r1, 1)                        @ r1<- field ref BBBB
-    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
     mov     r9, rINST, lsr #8           @ r9<- AA
-    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
-    cmp     r0, #0                      @ is resolved entry null?
+    cmp     r2, #0                      @ is resolved entry null?
     beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
-.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 0
+    add     r2, r2, #offStaticField_value @ r2<- pointer to data
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 /* ------------------------------ */
     .balign 64
@@ -7653,11 +7663,16 @@
     cmp     r0, #0                      @ is resolved entry null?
     beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
 .LOP_SGET_WIDE_VOLATILE_finish:
-    mov     r1, rINST, lsr #8           @ r1<- AA
-    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
-    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    .if 1
+    add     r0, r0, #offStaticField_value @ r0<- pointer to data
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+    .endif
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -7671,20 +7686,25 @@
      * 64-bit SPUT handler.
      */
     /* sput-wide vAA, field@BBBB */
-    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
     FETCH(r1, 1)                        @ r1<- field ref BBBB
-    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
     mov     r9, rINST, lsr #8           @ r9<- AA
-    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
-    cmp     r0, #0                      @ is resolved entry null?
+    cmp     r2, #0                      @ is resolved entry null?
     beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
-.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 1
+    add     r2, r2, #offStaticField_value @ r2<- pointer to data
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 
 /* ------------------------------ */
@@ -8740,10 +8760,15 @@
     cmp     r9, #0                      @ check object for null
     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
     beq     common_errNullObject        @ object was null
-    mov     r2, rINST, lsr #8           @ r2<- A+
+    .if 0
+    add     r0, r9, r3                  @ r0<- address of field
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
-    and     r2, r2, #15                 @ r2<- A
+    .endif
+    mov     r2, rINST, lsr #8           @ r2<- A+
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
@@ -8892,9 +8917,14 @@
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 0
+    add     r2, r9, r3                  @ r2<- target address
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 
 /* continuation for OP_IPUT_OBJECT */
@@ -9023,6 +9053,8 @@
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
+     *
+     * Returns StaticField pointer in r0.
      */
 .LOP_SGET_WIDE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -9136,6 +9168,8 @@
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
      *  r9: &fp[AA]
+     *
+     * Returns StaticField pointer in r2.
      */
 .LOP_SPUT_WIDE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -9143,6 +9177,7 @@
     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
+    mov     r2, r0                      @ copy to r2
     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
     b       common_exceptionThrown      @ no, handle exception
 
@@ -9528,10 +9563,15 @@
     cmp     r9, #0                      @ check object for null
     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
     beq     common_errNullObject        @ object was null
-    mov     r2, rINST, lsr #8           @ r2<- A+
+    .if 1
+    add     r0, r9, r3                  @ r0<- address of field
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
-    and     r2, r2, #15                 @ r2<- A
+    .endif
+    mov     r2, rINST, lsr #8           @ r2<- A+
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
@@ -9554,9 +9594,14 @@
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 1
+    add     r2, r9, r3                  @ r2<- target address
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 
 /* continuation for OP_SGET_WIDE_VOLATILE */
@@ -9564,6 +9609,8 @@
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
+     *
+     * Returns StaticField pointer in r0.
      */
 .LOP_SGET_WIDE_VOLATILE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -9581,6 +9628,8 @@
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
      *  r9: &fp[AA]
+     *
+     * Returns StaticField pointer in r2.
      */
 .LOP_SPUT_WIDE_VOLATILE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -9588,6 +9637,7 @@
     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
+    mov     r2, r0                      @ copy to r2
     bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
     b       common_exceptionThrown      @ no, handle exception
 
diff --git a/vm/mterp/out/InterpAsm-armv7-a-neon.S b/vm/mterp/out/InterpAsm-armv7-a-neon.S
index a60f78c..37316d8 100644
--- a/vm/mterp/out/InterpAsm-armv7-a-neon.S
+++ b/vm/mterp/out/InterpAsm-armv7-a-neon.S
@@ -2858,11 +2858,16 @@
     cmp     r0, #0                      @ is resolved entry null?
     beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
 .LOP_SGET_WIDE_finish:
-    mov     r1, rINST, lsr #8           @ r1<- AA
-    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
-    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    .if 0
+    add     r0, r0, #offStaticField_value @ r0<- pointer to data
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+    .endif
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -3028,20 +3033,25 @@
      * 64-bit SPUT handler.
      */
     /* sput-wide vAA, field@BBBB */
-    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
     FETCH(r1, 1)                        @ r1<- field ref BBBB
-    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
     mov     r9, rINST, lsr #8           @ r9<- AA
-    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
-    cmp     r0, #0                      @ is resolved entry null?
+    cmp     r2, #0                      @ is resolved entry null?
     beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
-.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 0
+    add     r2, r2, #offStaticField_value @ r2<- pointer to data
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 /* ------------------------------ */
     .balign 64
@@ -7194,38 +7204,111 @@
 
 /* ------------------------------ */
     .balign 64
-.L_OP_UNUSED_E8: /* 0xe8 */
-/* File: armv5te/OP_UNUSED_E8.S */
-/* File: armv5te/unused.S */
-    bl      common_abort
-
+.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
+/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
+/* File: armv5te/OP_IGET_WIDE.S */
+    /*
+     * Wide 32-bit instance field get.
+     */
+    /* iget-wide vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0
+    bne     .LOP_IGET_WIDE_VOLATILE_finish
+    b       common_exceptionThrown
 
 
 /* ------------------------------ */
     .balign 64
-.L_OP_UNUSED_E9: /* 0xe9 */
-/* File: armv5te/OP_UNUSED_E9.S */
-/* File: armv5te/unused.S */
-    bl      common_abort
-
+.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
+/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
+/* File: armv5te/OP_IPUT_WIDE.S */
+    /* iput-wide vA, vB, field@CCCC */
+    mov     r0, rINST, lsr #12          @ r0<- B
+    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref CCCC
+    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
+    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
+8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
+    b       common_exceptionThrown
 
 
 /* ------------------------------ */
     .balign 64
-.L_OP_UNUSED_EA: /* 0xea */
-/* File: armv5te/OP_UNUSED_EA.S */
-/* File: armv5te/unused.S */
-    bl      common_abort
-
+.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
+/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
+/* File: armv5te/OP_SGET_WIDE.S */
+    /*
+     * 64-bit SGET handler.
+     */
+    /* sget-wide vAA, field@BBBB */
+    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ is resolved entry null?
+    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
+.LOP_SGET_WIDE_VOLATILE_finish:
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    .if 1
+    add     r0, r0, #offStaticField_value @ r0<- pointer to data
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+    .endif
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    GOTO_OPCODE(ip)                     @ jump to next instruction
 
 
 /* ------------------------------ */
     .balign 64
-.L_OP_UNUSED_EB: /* 0xeb */
-/* File: armv5te/OP_UNUSED_EB.S */
-/* File: armv5te/unused.S */
-    bl      common_abort
-
+.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
+/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
+/* File: armv5te/OP_SPUT_WIDE.S */
+    /*
+     * 64-bit SPUT handler.
+     */
+    /* sput-wide vAA, field@BBBB */
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
+    FETCH(r1, 1)                        @ r1<- field ref BBBB
+    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
+    cmp     r2, #0                      @ is resolved entry null?
+    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
+.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 1
+    add     r2, r2, #offStaticField_value @ r2<- pointer to data
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 
 /* ------------------------------ */
@@ -8420,6 +8503,8 @@
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
+     *
+     * Returns StaticField pointer in r0.
      */
 .LOP_SGET_WIDE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -8533,6 +8618,8 @@
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
      *  r9: &fp[AA]
+     *
+     * Returns StaticField pointer in r2.
      */
 .LOP_SPUT_WIDE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -8540,6 +8627,7 @@
     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
+    mov     r2, r0                      @ copy to r2
     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
     b       common_exceptionThrown      @ no, handle exception
 
@@ -8914,6 +9002,96 @@
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
 
+/* continuation for OP_IGET_WIDE_VOLATILE */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IGET_WIDE_VOLATILE_finish:
+    cmp     r9, #0                      @ check object for null
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    beq     common_errNullObject        @ object was null
+    .if 1
+    add     r0, r9, r3                  @ r0<- address of field
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
+    .endif
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
+    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
+    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
+    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
+    GOTO_OPCODE(ip)                     @ jump to next instruction
+
+
+/* continuation for OP_IPUT_WIDE_VOLATILE */
+
+    /*
+     * Currently:
+     *  r0 holds resolved field
+     *  r9 holds object
+     */
+.LOP_IPUT_WIDE_VOLATILE_finish:
+    mov     r2, rINST, lsr #8           @ r2<- A+
+    cmp     r9, #0                      @ check object for null
+    and     r2, r2, #15                 @ r2<- A
+    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
+    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
+    beq     common_errNullObject        @ object was null
+    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 1
+    add     r2, r9, r3                  @ r2<- target address
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
+
+
+/* continuation for OP_SGET_WIDE_VOLATILE */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     *
+     * Returns StaticField pointer in r0.
+     */
+.LOP_SGET_WIDE_VOLATILE_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
+/* continuation for OP_SPUT_WIDE_VOLATILE */
+
+    /*
+     * Continuation if the field has not yet been resolved.
+     *  r1: BBBB field ref
+     *  r9: &fp[AA]
+     *
+     * Returns StaticField pointer in r2.
+     */
+.LOP_SPUT_WIDE_VOLATILE_resolve:
+    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
+    EXPORT_PC()                         @ resolve() could throw, so export now
+    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
+    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
+    cmp     r0, #0                      @ success?
+    mov     r2, r0                      @ copy to r2
+    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
+    b       common_exceptionThrown      @ no, handle exception
+
+
 /* continuation for OP_EXECUTE_INLINE */
 
     /*
diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S
index 2e48175..5a78a34 100644
--- a/vm/mterp/out/InterpAsm-armv7-a.S
+++ b/vm/mterp/out/InterpAsm-armv7-a.S
@@ -2858,11 +2858,16 @@
     cmp     r0, #0                      @ is resolved entry null?
     beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
 .LOP_SGET_WIDE_finish:
-    mov     r1, rINST, lsr #8           @ r1<- AA
-    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
-    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    .if 0
+    add     r0, r0, #offStaticField_value @ r0<- pointer to data
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+    .endif
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -3028,20 +3033,25 @@
      * 64-bit SPUT handler.
      */
     /* sput-wide vAA, field@BBBB */
-    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
     FETCH(r1, 1)                        @ r1<- field ref BBBB
-    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
     mov     r9, rINST, lsr #8           @ r9<- AA
-    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
-    cmp     r0, #0                      @ is resolved entry null?
+    cmp     r2, #0                      @ is resolved entry null?
     beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
-.LOP_SPUT_WIDE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 0
+    add     r2, r2, #offStaticField_value @ r2<- pointer to data
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 /* ------------------------------ */
     .balign 64
@@ -7257,11 +7267,16 @@
     cmp     r0, #0                      @ is resolved entry null?
     beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
 .LOP_SGET_WIDE_VOLATILE_finish:
-    mov     r1, rINST, lsr #8           @ r1<- AA
-    ldrd    r2, [r0, #offStaticField_value] @ r2/r3<- field value (aligned)
-    add     r1, rFP, r1, lsl #2         @ r1<- &fp[AA]
+    mov     r9, rINST, lsr #8           @ r9<- AA
+    .if 1
+    add     r0, r0, #offStaticField_value @ r0<- pointer to data
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
+    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
+    .endif
+    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    stmia   r1, {r2-r3}                 @ vAA/vAA+1<- r2/r3
+    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     GOTO_OPCODE(ip)                     @ jump to next instruction
 
@@ -7275,20 +7290,25 @@
      * 64-bit SPUT handler.
      */
     /* sput-wide vAA, field@BBBB */
-    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
+    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
     FETCH(r1, 1)                        @ r1<- field ref BBBB
-    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
+    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
     mov     r9, rINST, lsr #8           @ r9<- AA
-    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
+    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
-    cmp     r0, #0                      @ is resolved entry null?
+    cmp     r2, #0                      @ is resolved entry null?
     beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
-.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r0, AA in r9
+.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
-    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r2, [r0, #offStaticField_value] @ field<- vAA/vAA+1
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 1
+    add     r2, r2, #offStaticField_value @ r2<- pointer to data
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 
 /* ------------------------------ */
@@ -8483,6 +8503,8 @@
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
+     *
+     * Returns StaticField pointer in r0.
      */
 .LOP_SGET_WIDE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -8596,6 +8618,8 @@
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
      *  r9: &fp[AA]
+     *
+     * Returns StaticField pointer in r2.
      */
 .LOP_SPUT_WIDE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -8603,6 +8627,7 @@
     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
+    mov     r2, r0                      @ copy to r2
     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
     b       common_exceptionThrown      @ no, handle exception
 
@@ -8988,10 +9013,15 @@
     cmp     r9, #0                      @ check object for null
     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
     beq     common_errNullObject        @ object was null
-    mov     r2, rINST, lsr #8           @ r2<- A+
+    .if 1
+    add     r0, r9, r3                  @ r0<- address of field
+    bl      android_quasiatomic_read_64 @ r0/r1<- contents of field
+    .else
     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
-    and     r2, r2, #15                 @ r2<- A
+    .endif
+    mov     r2, rINST, lsr #8           @ r2<- A+
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
+    and     r2, r2, #15                 @ r2<- A
     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
@@ -9014,9 +9044,14 @@
     beq     common_errNullObject        @ object was null
     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
-    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
-    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
-    GOTO_OPCODE(ip)                     @ jump to next instruction
+    GET_INST_OPCODE(r10)                @ extract opcode from rINST
+    .if 1
+    add     r2, r9, r3                  @ r2<- target address
+    bl      android_quasiatomic_swap_64 @ stores r0/r1 into addr r2
+    .else
+    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
+    .endif
+    GOTO_OPCODE(r10)                    @ jump to next instruction
 
 
 /* continuation for OP_SGET_WIDE_VOLATILE */
@@ -9024,6 +9059,8 @@
     /*
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
+     *
+     * Returns StaticField pointer in r0.
      */
 .LOP_SGET_WIDE_VOLATILE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -9041,6 +9078,8 @@
      * Continuation if the field has not yet been resolved.
      *  r1: BBBB field ref
      *  r9: &fp[AA]
+     *
+     * Returns StaticField pointer in r2.
      */
 .LOP_SPUT_WIDE_VOLATILE_resolve:
     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
@@ -9048,6 +9087,7 @@
     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
     cmp     r0, #0                      @ success?
+    mov     r2, r0                      @ copy to r2
     bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
     b       common_exceptionThrown      @ no, handle exception
 
diff --git a/vm/mterp/out/InterpAsm-x86-atom.S b/vm/mterp/out/InterpAsm-x86-atom.S
index 860ec44..d32ff2f 100644
--- a/vm/mterp/out/InterpAsm-x86-atom.S
+++ b/vm/mterp/out/InterpAsm-x86-atom.S
@@ -14810,16 +14810,16 @@
     * Syntax: op vAA, ref@BBBB
     */
 
-    movl        rGLUE, %edx            		# %edx<- pMterpGlue
-    movl        offGlue_method(%edx), %ecx 	# %ecx<- glue->method
-    EXPORT_PC                          	  	# in case an exception is thrown
-    FETCH       1, %eax                 	# %eax<- BBBB
-    movl        %eax, -4(%esp)          	# push parameter BBBB; ref
-    movl        rINST, -8(%esp)          	# push parameter AA
-    movl        %ecx, -12(%esp)          	# push parameter glue->method
+    movl        rGLUE, %edx                 # %edx<- pMterpGlue
+    movl        offGlue_method(%edx), %ecx  # %ecx<- glue->method
+    EXPORT_PC                               # in case an exception is thrown
+    FETCH       1, %eax                     # %eax<- BBBB
+    movl        %eax, -4(%esp)              # push parameter BBBB; ref
+    movl        rINST, -8(%esp)             # push parameter AA
+    movl        %ecx, -12(%esp)             # push parameter glue->method
     lea         -12(%esp), %esp
-    call        dvmThrowVerificationError	# call: (const Method* method, int kind, int ref)
-    jmp 	common_exceptionThrown  	# failed; handle exception
+    call        dvmThrowVerificationError   # call: (const Method* method, int kind, int ref)
+    jmp     common_exceptionThrown      # failed; handle exception
 
 /* ------------------------------ */
     .balign 64
diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c
index 65b0b89..6c90b34 100644
--- a/vm/mterp/out/InterpC-allstubs.c
+++ b/vm/mterp/out/InterpC-allstubs.c
@@ -2775,19 +2775,19 @@
 OP_END
 
 /* File: c/OP_IGET_WIDE_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_IPUT_WIDE_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_SGET_WIDE_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_SPUT_WIDE_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_BREAKPOINT.c */
diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c
index 7bd8ad3..26c2c7b 100644
--- a/vm/mterp/out/InterpC-portdbg.c
+++ b/vm/mterp/out/InterpC-portdbg.c
@@ -3138,19 +3138,19 @@
 OP_END
 
 /* File: c/OP_IGET_WIDE_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_IPUT_WIDE_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_SGET_WIDE_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_SPUT_WIDE_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_BREAKPOINT.c */
diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c
index f8b3a75..927664e 100644
--- a/vm/mterp/out/InterpC-portstd.c
+++ b/vm/mterp/out/InterpC-portstd.c
@@ -2877,19 +2877,19 @@
 OP_END
 
 /* File: c/OP_IGET_WIDE_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_IPUT_WIDE_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_SGET_WIDE_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_SPUT_WIDE_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_BREAKPOINT.c */
diff --git a/vm/mterp/out/InterpC-x86-atom.c b/vm/mterp/out/InterpC-x86-atom.c
index a5b9fd8..a922509 100644
--- a/vm/mterp/out/InterpC-x86-atom.c
+++ b/vm/mterp/out/InterpC-x86-atom.c
@@ -1193,19 +1193,19 @@
 
 
 /* File: c/OP_IGET_WIDE_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_IPUT_WIDE_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_SGET_WIDE_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_SPUT_WIDE_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_BREAKPOINT.c */
diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.c
index 97fbe01..209b450 100644
--- a/vm/mterp/out/InterpC-x86.c
+++ b/vm/mterp/out/InterpC-x86.c
@@ -1193,19 +1193,19 @@
 
 
 /* File: c/OP_IGET_WIDE_VOLATILE.c */
-HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_IPUT_WIDE_VOLATILE.c */
-HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_IPUT_X(OP_IPUT_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_SGET_WIDE_VOLATILE.c */
-HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_SGET_X(OP_SGET_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_SPUT_WIDE_VOLATILE.c */
-HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE,    "-wide-volatile", Long, _WIDE)
+HANDLE_SPUT_X(OP_SPUT_WIDE_VOLATILE,    "-wide-volatile", LongVolatile, _WIDE)
 OP_END
 
 /* File: c/OP_EXECUTE_INLINE_RANGE.c */
diff --git a/vm/mterp/x86-atom/OP_THROW_VERIFICATION_ERROR.S b/vm/mterp/x86-atom/OP_THROW_VERIFICATION_ERROR.S
index 94b7ec6..52e52bf 100644
--- a/vm/mterp/x86-atom/OP_THROW_VERIFICATION_ERROR.S
+++ b/vm/mterp/x86-atom/OP_THROW_VERIFICATION_ERROR.S
@@ -28,13 +28,13 @@
     * Syntax: op vAA, ref@BBBB
     */
 
-    movl        rGLUE, %edx            		# %edx<- pMterpGlue
-    movl        offGlue_method(%edx), %ecx 	# %ecx<- glue->method
-    EXPORT_PC                          	  	# in case an exception is thrown
-    FETCH       1, %eax                 	# %eax<- BBBB
-    movl        %eax, -4(%esp)          	# push parameter BBBB; ref
-    movl        rINST, -8(%esp)          	# push parameter AA
-    movl        %ecx, -12(%esp)          	# push parameter glue->method
+    movl        rGLUE, %edx                 # %edx<- pMterpGlue
+    movl        offGlue_method(%edx), %ecx  # %ecx<- glue->method
+    EXPORT_PC                               # in case an exception is thrown
+    FETCH       1, %eax                     # %eax<- BBBB
+    movl        %eax, -4(%esp)              # push parameter BBBB; ref
+    movl        rINST, -8(%esp)             # push parameter AA
+    movl        %ecx, -12(%esp)             # push parameter glue->method
     lea         -12(%esp), %esp
-    call        dvmThrowVerificationError	# call: (const Method* method, int kind, int ref)
-    jmp 	common_exceptionThrown  	# failed; handle exception
+    call        dvmThrowVerificationError   # call: (const Method* method, int kind, int ref)
+    jmp     common_exceptionThrown      # failed; handle exception
diff --git a/vm/oo/Array.c b/vm/oo/Array.c
index 4af03a9..7edb823 100644
--- a/vm/oo/Array.c
+++ b/vm/oo/Array.c
@@ -616,9 +616,6 @@
 /*
  * Synthesize a primitive class.
  *
- * The spec for java.lang.Class.isPrimitive describes the names to
- * be used for these classes.
- *
  * Just creates the class and returns it (does not add it to the class list).
  */
 static ClassObject* createPrimitiveClass(int idx)
diff --git a/vm/oo/Object.h b/vm/oo/Object.h
index be2c9f2..5ceb42c 100644
--- a/vm/oo/Object.h
+++ b/vm/oo/Object.h
@@ -21,6 +21,8 @@
 #ifndef _DALVIK_OO_OBJECT
 #define _DALVIK_OO_OBJECT
 
+#include <Atomic.h>
+
 #include <stddef.h>
 
 /* fwd decl */
@@ -713,6 +715,10 @@
 INLINE Object* dvmGetFieldObject(const Object* obj, int offset) {
     return ((JValue*)BYTE_OFFSET(obj, offset))->l;
 }
+INLINE s8 dvmGetFieldLongVolatile(const Object* obj, int offset) {
+    const s8* addr = BYTE_OFFSET(obj, offset);
+    return android_quasiatomic_read_64((s8*)addr);
+}
 
 INLINE void dvmSetFieldBoolean(Object* obj, int offset, bool val) {
     ((JValue*)BYTE_OFFSET(obj, offset))->i = val;
@@ -741,6 +747,10 @@
 INLINE void dvmSetFieldObject(Object* obj, int offset, Object* val) {
     ((JValue*)BYTE_OFFSET(obj, offset))->l = val;
 }
+INLINE void dvmSetFieldLongVolatile(Object* obj, int offset, s8 val) {
+    s8* addr = BYTE_OFFSET(obj, offset);
+    android_quasiatomic_swap_64(val, addr);
+}
 
 /*
  * Static field access functions.
@@ -776,6 +786,10 @@
 INLINE Object* dvmGetStaticFieldObject(const StaticField* sfield) {
     return sfield->value.l;
 }
+INLINE s8 dvmGetStaticFieldLongVolatile(const StaticField* sfield) {
+    const s8* addr = &sfield->value.j;
+    return android_quasiatomic_read_64((s8*)addr);
+}
 
 INLINE void dvmSetStaticFieldBoolean(StaticField* sfield, bool val) {
     sfield->value.i = val;
@@ -804,6 +818,10 @@
 INLINE void dvmSetStaticFieldObject(StaticField* sfield, Object* val) {
     sfield->value.l = val;
 }
+INLINE void dvmSetStaticFieldLongVolatile(StaticField* sfield, s8 val) {
+    s8* addr = &sfield->value.j;
+    android_quasiatomic_swap_64(val, addr);
+}
 
 /*
  * Helpers.
@@ -859,6 +877,9 @@
 INLINE bool dvmIsFinalField(const Field* field) {
     return (field->accessFlags & ACC_FINAL) != 0;
 }
+INLINE bool dvmIsVolatileField(const Field* field) {
+    return (field->accessFlags & ACC_VOLATILE) != 0;
+}
 
 INLINE bool dvmIsInterfaceClass(const ClassObject* clazz) {
     return (clazz->accessFlags & ACC_INTERFACE) != 0;