summaryrefslogtreecommitdiffstats
path: root/vm/compiler/codegen/arm
diff options
context:
space:
mode:
Diffstat (limited to 'vm/compiler/codegen/arm')
-rw-r--r--vm/compiler/codegen/arm/ArchUtility.c27
-rw-r--r--vm/compiler/codegen/arm/ArmLIR.h11
-rw-r--r--vm/compiler/codegen/arm/Assemble.c5
-rw-r--r--vm/compiler/codegen/arm/CodegenDriver.c73
-rw-r--r--vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c7
-rw-r--r--vm/compiler/codegen/arm/armv5te/ArchVariant.c7
-rw-r--r--vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c8
-rw-r--r--vm/compiler/codegen/arm/armv7-a/ArchVariant.c8
8 files changed, 126 insertions, 20 deletions
diff --git a/vm/compiler/codegen/arm/ArchUtility.c b/vm/compiler/codegen/arm/ArchUtility.c
index 4e0df2884..2daa871ca 100644
--- a/vm/compiler/codegen/arm/ArchUtility.c
+++ b/vm/compiler/codegen/arm/ArchUtility.c
@@ -68,6 +68,7 @@ static void buildInsnString(char *fmt, ArmLIR *lir, char* buf,
char *bufEnd = &buf[size-1];
char *fmtEnd = &fmt[strlen(fmt)];
char tbuf[256];
+ char *name;
char nc;
while (fmt < fmtEnd) {
int operand;
@@ -82,6 +83,32 @@ static void buildInsnString(char *fmt, ArmLIR *lir, char* buf,
assert((unsigned)(nc-'0') < 4);
operand = lir->operands[nc-'0'];
switch(*fmt++) {
+ case 'B':
+ switch (operand) {
+ case kSY:
+ name = "sy";
+ break;
+ case kST:
+ name = "st";
+ break;
+ case kISH:
+ name = "ish";
+ break;
+ case kISHST:
+ name = "ishst";
+ break;
+ case kNSH:
+ name = "nsh";
+ break;
+ case kNSHST:
+ name = "shst";
+ break;
+ default:
+ name = "DecodeError";
+ break;
+ }
+ strcpy(tbuf, name);
+ break;
case 'b':
strcpy(tbuf,"0000");
for (i=3; i>= 0; i--) {
diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h
index c397a391e..24f5240bd 100644
--- a/vm/compiler/codegen/arm/ArmLIR.h
+++ b/vm/compiler/codegen/arm/ArmLIR.h
@@ -622,10 +622,21 @@ typedef enum ArmOpCode {
rd[11-8] imm2[7-6] [0] msb[4-0] */
kThumb2Bfc, /* bfc [11110011011011110] [0] imm3[14-12]
rd[11-8] imm2[7-6] [0] msb[4-0] */
+ kThumb2Dmb, /* dmb [1111001110111111100011110101] option[3-0] */
kArmLast,
} ArmOpCode;
+/* DMB option encodings */
+typedef enum ArmOpDmbOptions {
+ kSY = 0xf,
+ kST = 0xe,
+ kISH = 0xb,
+ kISHST = 0xa,
+ kNSH = 0x7,
+ kNSHST = 0x6
+} ArmOpDmbOptions;
+
/* Bit flags describing the behavior of each native opcode */
typedef enum ArmOpFeatureFlags {
kIsBranch = 0,
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index 05c4a0ee2..832ee0fea 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -70,6 +70,7 @@
* n -> complimented Thumb2 modified immediate
* M -> Thumb2 16-bit zero-extended immediate
* b -> 4-digit binary
+ * B -> dmb option string (sy, st, ish, ishst, nsh, hshst)
*
* [!] escape. To insert "!", use "!!"
*/
@@ -869,6 +870,10 @@ ArmEncodingMap EncodingMap[kArmLast] = {
kFmtBitBlt, 11, 8, kFmtShift5, -1, -1, kFmtBitBlt, 4, 0,
kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0,
"bfc", "r!0d,#!1d,#!2d", 2),
+ ENCODING_MAP(kThumb2Dmb, 0xf3bf8f50,
+ kFmtBitBlt, 3, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
+ kFmtUnused, -1, -1, IS_UNARY_OP,
+ "dmb","#!0B",2),
};
/*
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index d69991d5d..0bcdd0e96 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -77,7 +77,6 @@ static bool genConversionCall(CompilationUnit *cUnit, MIR *mir, void *funct,
return false;
}
-
static bool genArithOpFloatPortable(CompilationUnit *cUnit, MIR *mir,
RegLocation rlDest, RegLocation rlSrc1,
RegLocation rlSrc2)
@@ -301,7 +300,7 @@ static void genIPutWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
*
*/
static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
- int fieldOffset)
+ int fieldOffset, bool isVolatile)
{
RegLocation rlResult;
RegisterClass regClass = dvmCompilerRegClassBySize(size);
@@ -316,6 +315,9 @@ static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
size, rlObj.sRegLow);
HEAP_ACCESS_SHADOW(false);
+ if (isVolatile) {
+ dvmCompilerGenMemBarrier(cUnit);
+ }
storeValue(cUnit, rlDest, rlResult);
}
@@ -325,7 +327,7 @@ static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
*
*/
static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
- int fieldOffset, bool isObject)
+ int fieldOffset, bool isObject, bool isVolatile)
{
RegisterClass regClass = dvmCompilerRegClassBySize(size);
RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
@@ -335,6 +337,9 @@ static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
NULL);/* null object? */
+ if (isVolatile) {
+ dvmCompilerGenMemBarrier(cUnit);
+ }
HEAP_ACCESS_SHADOW(true);
storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
HEAP_ACCESS_SHADOW(false);
@@ -1444,6 +1449,8 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
storeValue(cUnit, rlDest, rlResult);
break;
}
+ case OP_SGET_VOLATILE:
+ case OP_SGET_OBJECT_VOLATILE:
case OP_SGET_OBJECT:
case OP_SGET_BOOLEAN:
case OP_SGET_CHAR:
@@ -1452,6 +1459,7 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
case OP_SGET: {
int valOffset = offsetof(StaticField, value);
int tReg = dvmCompilerAllocTemp(cUnit);
+ bool isVolatile;
void *fieldPtr = (void*)
(cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
@@ -1460,10 +1468,17 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
dvmAbort();
}
+ isVolatile = (mir->dalvikInsn.opCode == OP_SGET_VOLATILE) ||
+ (mir->dalvikInsn.opCode == OP_SGET_OBJECT_VOLATILE) ||
+ dvmIsVolatileField(fieldPtr);
+
rlDest = dvmCompilerGetDest(cUnit, mir, 0);
rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
+ if (isVolatile) {
+ dvmCompilerGenMemBarrier(cUnit);
+ }
HEAP_ACCESS_SHADOW(true);
loadWordDisp(cUnit, tReg, 0, rlResult.lowReg);
HEAP_ACCESS_SHADOW(false);
@@ -1501,9 +1516,14 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
case OP_SPUT: {
int valOffset = offsetof(StaticField, value);
int tReg = dvmCompilerAllocTemp(cUnit);
- void *fieldPtr = (void*)
+ bool isVolatile;
+ Field *fieldPtr =
(cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
+ isVolatile = (mir->dalvikInsn.opCode == OP_SPUT_VOLATILE) ||
+ (mir->dalvikInsn.opCode == OP_SPUT_OBJECT_VOLATILE) ||
+ dvmIsVolatileField(fieldPtr);
+
if (fieldPtr == NULL) {
LOGE("Unexpected null static field");
dvmAbort();
@@ -1516,6 +1536,9 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
HEAP_ACCESS_SHADOW(true);
storeWordDisp(cUnit, tReg, 0 ,rlSrc.lowReg);
HEAP_ACCESS_SHADOW(false);
+ if (isVolatile) {
+ dvmCompilerGenMemBarrier(cUnit);
+ }
if (mir->dalvikInsn.opCode == OP_SPUT_OBJECT) {
/* NOTE: marking card based on field address */
markCard(cUnit, rlSrc.lowReg, tReg);
@@ -2120,17 +2143,18 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
{
OpCode dalvikOpCode = mir->dalvikInsn.opCode;
int fieldOffset;
+ bool isVolatile = false;
if (dalvikOpCode >= OP_IGET && dalvikOpCode <= OP_IPUT_SHORT) {
- InstField *pInstField = (InstField *)
+ Field *fieldPtr =
cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC];
- if (pInstField == NULL) {
+ if (fieldPtr == NULL) {
LOGE("Unexpected null instance field");
dvmAbort();
}
-
- fieldOffset = pInstField->byteOffset;
+ isVolatile = dvmIsVolatileField(fieldPtr);
+ fieldOffset = ((InstField *)fieldPtr)->byteOffset;
} else {
/* Deliberately break the code while make the compiler happy */
fieldOffset = -1;
@@ -2230,38 +2254,47 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
case OP_IGET_WIDE:
genIGetWide(cUnit, mir, fieldOffset);
break;
+ case OP_IGET_VOLATILE:
+ case OP_IGET_OBJECT_VOLATILE:
+ isVolatile = true;
+ // NOTE: intentional fallthrough
case OP_IGET:
case OP_IGET_OBJECT:
- genIGet(cUnit, mir, kWord, fieldOffset);
+ genIGet(cUnit, mir, kWord, fieldOffset, isVolatile);
break;
case OP_IGET_BOOLEAN:
- genIGet(cUnit, mir, kUnsignedByte, fieldOffset);
+ genIGet(cUnit, mir, kUnsignedByte, fieldOffset, isVolatile);
break;
case OP_IGET_BYTE:
- genIGet(cUnit, mir, kSignedByte, fieldOffset);
+ genIGet(cUnit, mir, kSignedByte, fieldOffset, isVolatile);
break;
case OP_IGET_CHAR:
- genIGet(cUnit, mir, kUnsignedHalf, fieldOffset);
+ genIGet(cUnit, mir, kUnsignedHalf, fieldOffset, isVolatile);
break;
case OP_IGET_SHORT:
- genIGet(cUnit, mir, kSignedHalf, fieldOffset);
+ genIGet(cUnit, mir, kSignedHalf, fieldOffset, isVolatile);
break;
case OP_IPUT_WIDE:
genIPutWide(cUnit, mir, fieldOffset);
break;
case OP_IPUT:
- genIPut(cUnit, mir, kWord, fieldOffset, false);
+ genIPut(cUnit, mir, kWord, fieldOffset, false, isVolatile);
break;
+ case OP_IPUT_OBJECT_VOLATILE:
+ isVolatile = true;
+ // NOTE: intentional fallthrough
case OP_IPUT_OBJECT:
- genIPut(cUnit, mir, kWord, fieldOffset, true);
+ genIPut(cUnit, mir, kWord, fieldOffset, true, isVolatile);
break;
case OP_IPUT_SHORT:
case OP_IPUT_CHAR:
- genIPut(cUnit, mir, kUnsignedHalf, fieldOffset, false);
+ genIPut(cUnit, mir, kUnsignedHalf, fieldOffset, false, isVolatile);
break;
case OP_IPUT_BYTE:
+ genIPut(cUnit, mir, kSignedByte, fieldOffset, false, isVolatile);
+ break;
case OP_IPUT_BOOLEAN:
- genIPut(cUnit, mir, kUnsignedByte, fieldOffset, false);
+ genIPut(cUnit, mir, kUnsignedByte, fieldOffset, false, isVolatile);
break;
case OP_IGET_WIDE_VOLATILE:
case OP_IPUT_WIDE_VOLATILE:
@@ -2282,13 +2315,13 @@ static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir)
switch (dalvikOpCode) {
case OP_IGET_QUICK:
case OP_IGET_OBJECT_QUICK:
- genIGet(cUnit, mir, kWord, fieldOffset);
+ genIGet(cUnit, mir, kWord, fieldOffset, false);
break;
case OP_IPUT_QUICK:
- genIPut(cUnit, mir, kWord, fieldOffset, false);
+ genIPut(cUnit, mir, kWord, fieldOffset, false, false);
break;
case OP_IPUT_OBJECT_QUICK:
- genIPut(cUnit, mir, kWord, fieldOffset, true);
+ genIPut(cUnit, mir, kWord, fieldOffset, true, false);
break;
case OP_IGET_WIDE_QUICK:
genIGetWide(cUnit, mir, fieldOffset);
diff --git a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
index 7f9fa3ba9..6511eac22 100644
--- a/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
@@ -92,3 +92,10 @@ int dvmCompilerTargetOptHint(int key)
}
return res;
}
+
+void dvmCompilerGenMemBarrier(CompilationUnit *cUnit)
+{
+#if ANDROID_SMP != 0
+#error armv5+smp not supported
+#endif
+}
diff --git a/vm/compiler/codegen/arm/armv5te/ArchVariant.c b/vm/compiler/codegen/arm/armv5te/ArchVariant.c
index e018ea11b..814f410ff 100644
--- a/vm/compiler/codegen/arm/armv5te/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv5te/ArchVariant.c
@@ -92,3 +92,10 @@ int dvmCompilerTargetOptHint(int key)
}
return res;
}
+
+void dvmCompilerGenMemBarrier(CompilationUnit *cUnit)
+{
+#if ANDROID_SMP != 0
+#error armv5+smp not supported
+#endif
+}
diff --git a/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c b/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c
index 5a14774c0..f1727c6f1 100644
--- a/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c
@@ -87,3 +87,11 @@ int dvmCompilerTargetOptHint(int key)
}
return res;
}
+
+void dvmCompilerGenMemBarrier(CompilationUnit *cUnit)
+{
+#if ANDROID_SMP != 0
+ ArmLIR *dmb = newLIR1(cUnit, kThumb2Dmb, kSY); // Full system DMB
+ dmb->defMask = ENCODE_ALL;
+#endif
+}
diff --git a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
index 5a14774c0..f1727c6f1 100644
--- a/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
+++ b/vm/compiler/codegen/arm/armv7-a/ArchVariant.c
@@ -87,3 +87,11 @@ int dvmCompilerTargetOptHint(int key)
}
return res;
}
+
+void dvmCompilerGenMemBarrier(CompilationUnit *cUnit)
+{
+#if ANDROID_SMP != 0
+ ArmLIR *dmb = newLIR1(cUnit, kThumb2Dmb, kSY); // Full system DMB
+ dmb->defMask = ENCODE_ALL;
+#endif
+}