diff options
Diffstat (limited to 'vm/compiler/codegen/arm')
-rw-r--r-- | vm/compiler/codegen/arm/ArchUtility.c | 27 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/ArmLIR.h | 11 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/Assemble.c | 5 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/CodegenDriver.c | 73 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c | 7 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/armv5te/ArchVariant.c | 7 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c | 8 | ||||
-rw-r--r-- | vm/compiler/codegen/arm/armv7-a/ArchVariant.c | 8 |
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 +} |