[MIPS] Use sync instruction in dvmCompilerGenMemBarrier

Change-Id: Id647a126b0d6b1666c001a87c59a0930762778b2
Signed-off-by: Douglas Leung <douglas@mips.com>
diff --git a/vm/compiler/codegen/mips/ArchUtility.cpp b/vm/compiler/codegen/mips/ArchUtility.cpp
index 1f6d593..47c4c6d 100644
--- a/vm/compiler/codegen/mips/ArchUtility.cpp
+++ b/vm/compiler/codegen/mips/ArchUtility.cpp
@@ -38,6 +38,7 @@
     char *bufEnd = &buf[size-1];
     const char *fmtEnd = &fmt[strlen(fmt)];
     char tbuf[256];
+    const char *name;
     char nc;
     while (fmt < fmtEnd) {
         int operand;
@@ -142,6 +143,32 @@
                        assert(operand >= 0 && operand < MIPS_REG_COUNT);
                        strcpy(tbuf, mipsRegName[operand]);
                        break;
+                   case 'B':
+                       switch (operand) {
+                           case kSY:
+                               name = "0/sy";
+                               break;
+                           case kWMB:
+                               name = "4/wmb";
+                               break;
+                           case kMB:
+                               name = "16/mb";
+                               break;
+                           case kACQUIRE:
+                               name = "17/acquire";
+                               break;
+                           case kRELEASE:
+                               name = "18/release";
+                               break;
+                           case kRMB:
+                               name = "19/rmb";
+                               break;
+                           default:
+                               name = "DecodeError";
+                               break;
+                       }
+                       strcpy(tbuf, name);
+                       break;
                    default:
                        strcpy(tbuf,"DecodeError");
                        break;
diff --git a/vm/compiler/codegen/mips/Assemble.cpp b/vm/compiler/codegen/mips/Assemble.cpp
index 713bced..36a301c 100644
--- a/vm/compiler/codegen/mips/Assemble.cpp
+++ b/vm/compiler/codegen/mips/Assemble.cpp
@@ -73,6 +73,7 @@
  *     n -> complimented Thumb2 modified immediate
  *     M -> Thumb2 16-bit zero-extended immediate
  *     b -> 4-digit binary
+ *     B -> sync option string (SY, WMB, MB, ACQUIRE, RELEASE, RMB)
  *
  *  [!] escape.  To insert "!", use "!!"
  */
@@ -294,6 +295,10 @@
                  kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtBitBlt, 25, 21,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_USE02 | IS_STORE,
                  "sw", "!0r,!1d(!2r)", 2),
+    ENCODING_MAP(kMipsSync, 0x0000000F,
+                 kFmtBitBlt, 10, 6, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
+                 kFmtUnused, -1, -1, IS_UNARY_OP,
+                 "sync", "!0B", 2),
     ENCODING_MAP(kMipsXor, 0x00000026,
                  kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16,
                  kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12,
diff --git a/vm/compiler/codegen/mips/CodegenDriver.cpp b/vm/compiler/codegen/mips/CodegenDriver.cpp
index 62a9a4f..273a154 100644
--- a/vm/compiler/codegen/mips/CodegenDriver.cpp
+++ b/vm/compiler/codegen/mips/CodegenDriver.cpp
@@ -428,7 +428,7 @@
                  size, rlObj.sRegLow);
     HEAP_ACCESS_SHADOW(false);
     if (isVolatile) {
-        dvmCompilerGenMemBarrier(cUnit, 0);
+        dvmCompilerGenMemBarrier(cUnit, kSY);
     }
 
     storeValue(cUnit, rlDest, rlResult);
@@ -450,13 +450,13 @@
                  NULL);/* null object? */
 
     if (isVolatile) {
-        dvmCompilerGenMemBarrier(cUnit, 0);
+        dvmCompilerGenMemBarrier(cUnit, kSY);
     }
     HEAP_ACCESS_SHADOW(true);
     storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
     HEAP_ACCESS_SHADOW(false);
     if (isVolatile) {
-        dvmCompilerGenMemBarrier(cUnit, 0);
+        dvmCompilerGenMemBarrier(cUnit, kSY);
     }
     if (isObject) {
         /* NOTE: marking card based on object head */
@@ -1558,7 +1558,7 @@
     }
     switch (dalvikOpcode) {
         case OP_RETURN_VOID_BARRIER:
-            dvmCompilerGenMemBarrier(cUnit, 0);
+            dvmCompilerGenMemBarrier(cUnit, kSY);
             // Intentional fallthrough
         case OP_RETURN_VOID:
             genReturnCommon(cUnit,mir);
@@ -1732,7 +1732,7 @@
             loadConstant(cUnit, tReg,  (int) fieldPtr + valOffset);
 
             if (isVolatile) {
-                dvmCompilerGenMemBarrier(cUnit, 0);
+                dvmCompilerGenMemBarrier(cUnit, kSY);
             }
             HEAP_ACCESS_SHADOW(true);
             loadWordDisp(cUnit, tReg, 0, rlResult.lowReg);
@@ -1810,14 +1810,14 @@
                 loadWordDisp(cUnit, tReg, OFFSETOF_MEMBER(Field, clazz), objHead);
             }
             if (isVolatile) {
-                dvmCompilerGenMemBarrier(cUnit, 0);
+                dvmCompilerGenMemBarrier(cUnit, kSY);
             }
             HEAP_ACCESS_SHADOW(true);
             storeWordDisp(cUnit, tReg, valOffset ,rlSrc.lowReg);
             dvmCompilerFreeTemp(cUnit, tReg);
             HEAP_ACCESS_SHADOW(false);
             if (isVolatile) {
-                dvmCompilerGenMemBarrier(cUnit, 0);
+                dvmCompilerGenMemBarrier(cUnit, kSY);
             }
             if (isSputObject) {
                 /* NOTE: marking card based sfield->clazz */
diff --git a/vm/compiler/codegen/mips/MipsLIR.h b/vm/compiler/codegen/mips/MipsLIR.h
index fc82da2..de40755 100644
--- a/vm/compiler/codegen/mips/MipsLIR.h
+++ b/vm/compiler/codegen/mips/MipsLIR.h
@@ -457,6 +457,7 @@
     kMipsSrlv,    /* srlv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000110] */
     kMipsSubu,    /* subu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100011] */
     kMipsSw,      /* sw t,o(b) [101011] b[25..21] t[20..16] o[15..0] */
+    kMipsSync,    /* sync hint [000000000000000000000] hint[10..6] [001111] */
     kMipsXor,     /* xor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100110] */
     kMipsXori,    /* xori t,s,imm16 [001110] s[25..21] t[20..16] imm16[15..0] */
 #ifdef __mips_hard_float
@@ -487,6 +488,24 @@
     kMipsLast
 } MipsOpCode;
 
+/* Sync option encodings */
+typedef enum MipsSyncOptions {
+    /*
+     * sync guarantees ordering of Load/Store operations wrt itself
+     *
+     * Older: instruction classes that must be ordered before the sync instruction completes
+     * Younger: instruction classes that must be ordered after the sync instruction completes
+     * Global: instruction classes that must be performed globally when the sync completes
+     */
+                                /* Older        Younger         Global          */
+    kSY = 0x00,                 /* Load,Store   Load,Store      Load,Store      */
+    kWMB = 0x04,                /* Store        Store                           */
+    kMB = 0x10,                 /* Load,Store   Load,Store                      */
+    kACQUIRE = 0x11,            /* Load         Load,Store                      */
+    kRELEASE = 0x12,            /* Load,Store   Store                           */
+    kRMB = 0x13                 /* Load         Load                            */
+} MipsSyncOptions;
+
 /* Bit flags describing the behavior of each native opcode */
 typedef enum MipsOpFeatureFlags {
     kIsBranch = 0,
diff --git a/vm/compiler/codegen/mips/mips/ArchVariant.cpp b/vm/compiler/codegen/mips/mips/ArchVariant.cpp
index d720f85..4362961 100644
--- a/vm/compiler/codegen/mips/mips/ArchVariant.cpp
+++ b/vm/compiler/codegen/mips/mips/ArchVariant.cpp
@@ -105,5 +105,8 @@
 
 void dvmCompilerGenMemBarrier(CompilationUnit *cUnit, int barrierKind)
 {
-    __asm__ __volatile__ ("" : : : "memory");
+#if ANDROID_SMP != 0
+    MipsLIR *sync = newLIR1(cUnit, kMipsSync, barrierKind);
+    sync->defMask = ENCODE_ALL;
+#endif
 }