diff options
author | Andy McFadden <fadden@android.com> | 2010-06-17 12:36:00 -0700 |
---|---|---|
committer | Andy McFadden <fadden@android.com> | 2010-06-18 12:43:08 -0700 |
commit | c35a2ef53d0cccd6f924eeba36633220ec67c32e (patch) | |
tree | 3dca5c629067edc9f6968d11b91621198de18387 | |
parent | 54c91f8f33fc12d741aaa0dcdb375991e252c994 (diff) | |
download | android_dalvik-c35a2ef53d0cccd6f924eeba36633220ec67c32e.tar.gz android_dalvik-c35a2ef53d0cccd6f924eeba36633220ec67c32e.tar.bz2 android_dalvik-c35a2ef53d0cccd6f924eeba36633220ec67c32e.zip |
Add opcodes for volatile field accesses
This adds instructions for {i,s}{get,put}{,-object}-volatile, for a
total of eight new instructions.
On SMP systems, these instructions will be substituted in for existing
field access instructions, either by dexopt or during just-in-time
verification. Unlike the wide-volatile instructions, these will not be
used at all when the VM is not built for SMP.
(Ideally we'd omit the volatile instruction implementations entirely on
non-SMP builds, but that requires a little work in gen-mterp.py.)
The change defines and implements the opcodes and support methods, but
does not cause them to be used.
Also, changed dvmQuasiAtomicRead64's argument to be const.
Change-Id: I9e44fe881e87f27aa41f6c6e898ec4402cb5493e
69 files changed, 2368 insertions, 666 deletions
diff --git a/dexdump/OpCodeNames.c b/dexdump/OpCodeNames.c index e3155743d..1901f15ea 100644 --- a/dexdump/OpCodeNames.c +++ b/dexdump/OpCodeNames.c @@ -287,11 +287,11 @@ static const char* gOpNames[256] = { "shl-int/lit8", "shr-int/lit8", "ushr-int/lit8", - "UNUSED", - "UNUSED", - "UNUSED", - "UNUSED", - "UNUSED", + "+iget-volatile", + "+iput-volatile", + "+sget-volatile", + "+sput-volatile", + "+iget-object-volatile", "+iget-wide-volatile", "+iput-wide-volatile", "+sget-wide-volatile", @@ -314,9 +314,9 @@ static const char* gOpNames[256] = { "+invoke-virtual-quick/range", "+invoke-super-quick", "+invoke-super-quick/range", - "UNUSED", - "UNUSED", - "UNUSED", + "+iput-object-volatile", + "+sget-object-volatile", + "+sput-object-volatile", "UNUSED", }; diff --git a/libdex/InstrUtils.c b/libdex/InstrUtils.c index 79095ae9e..a3ee859bb 100644 --- a/libdex/InstrUtils.c +++ b/libdex/InstrUtils.c @@ -297,6 +297,14 @@ InstructionWidth* dexCreateInstrWidthTable(void) case OP_IPUT_QUICK: case OP_IPUT_WIDE_QUICK: case OP_IPUT_OBJECT_QUICK: + case OP_IGET_VOLATILE: + case OP_IPUT_VOLATILE: + case OP_SGET_VOLATILE: + case OP_SPUT_VOLATILE: + case OP_IGET_OBJECT_VOLATILE: + case OP_IPUT_OBJECT_VOLATILE: + case OP_SGET_OBJECT_VOLATILE: + case OP_SPUT_OBJECT_VOLATILE: case OP_IGET_WIDE_VOLATILE: case OP_IPUT_WIDE_VOLATILE: case OP_SGET_WIDE_VOLATILE: @@ -324,16 +332,8 @@ InstructionWidth* dexCreateInstrWidthTable(void) case OP_UNUSED_73: case OP_UNUSED_79: case OP_UNUSED_7A: - case OP_UNUSED_E3: - case OP_UNUSED_E4: - case OP_UNUSED_E5: - case OP_UNUSED_E6: - case OP_UNUSED_E7: case OP_BREAKPOINT: case OP_UNUSED_F1: - case OP_UNUSED_FC: - case OP_UNUSED_FD: - case OP_UNUSED_FE: case OP_UNUSED_FF: assert(width == 0); break; @@ -628,6 +628,14 @@ InstructionFlags* dexCreateInstrFlagsTable(void) case OP_IPUT_QUICK: case OP_IPUT_WIDE_QUICK: case OP_IPUT_OBJECT_QUICK: + case OP_IGET_VOLATILE: + case OP_IPUT_VOLATILE: + case OP_SGET_VOLATILE: + case OP_SPUT_VOLATILE: + case OP_IGET_OBJECT_VOLATILE: + case OP_IPUT_OBJECT_VOLATILE: + case OP_SGET_OBJECT_VOLATILE: + case OP_SPUT_OBJECT_VOLATILE: case OP_IGET_WIDE_VOLATILE: case OP_IPUT_WIDE_VOLATILE: case OP_SGET_WIDE_VOLATILE: @@ -653,16 +661,8 @@ InstructionFlags* dexCreateInstrFlagsTable(void) case OP_UNUSED_73: case OP_UNUSED_79: case OP_UNUSED_7A: - case OP_UNUSED_E3: - case OP_UNUSED_E4: - case OP_UNUSED_E5: - case OP_UNUSED_E6: - case OP_UNUSED_E7: case OP_BREAKPOINT: case OP_UNUSED_F1: - case OP_UNUSED_FC: - case OP_UNUSED_FD: - case OP_UNUSED_FE: case OP_UNUSED_FF: break; @@ -973,6 +973,14 @@ InstructionFormat* dexCreateInstrFormatTable(void) case OP_IPUT_WIDE_VOLATILE: case OP_SGET_WIDE_VOLATILE: case OP_SPUT_WIDE_VOLATILE: + case OP_IGET_VOLATILE: + case OP_IPUT_VOLATILE: + case OP_SGET_VOLATILE: + case OP_SPUT_VOLATILE: + case OP_IGET_OBJECT_VOLATILE: + case OP_IPUT_OBJECT_VOLATILE: + case OP_SGET_OBJECT_VOLATILE: + case OP_SPUT_OBJECT_VOLATILE: fmt = kFmt22c; break; case OP_IGET_QUICK: @@ -1011,16 +1019,8 @@ InstructionFormat* dexCreateInstrFormatTable(void) case OP_UNUSED_73: case OP_UNUSED_79: case OP_UNUSED_7A: - case OP_UNUSED_E3: - case OP_UNUSED_E4: - case OP_UNUSED_E5: - case OP_UNUSED_E6: - case OP_UNUSED_E7: case OP_BREAKPOINT: case OP_UNUSED_F1: - case OP_UNUSED_FC: - case OP_UNUSED_FD: - case OP_UNUSED_FE: case OP_UNUSED_FF: fmt = kFmtUnknown; break; diff --git a/libdex/OpCode.h b/libdex/OpCode.h index f0bc423b4..312ff0175 100644 --- a/libdex/OpCode.h +++ b/libdex/OpCode.h @@ -321,13 +321,13 @@ typedef enum OpCode { OP_SHR_INT_LIT8 = 0xe1, OP_USHR_INT_LIT8 = 0xe2, - OP_UNUSED_E3 = 0xe3, - OP_UNUSED_E4 = 0xe4, - OP_UNUSED_E5 = 0xe5, - OP_UNUSED_E6 = 0xe6, - OP_UNUSED_E7 = 0xe7, - /* verifier/optimizer output -- nothing below here is generated by "dx" */ + OP_IGET_VOLATILE = 0xe3, + OP_IPUT_VOLATILE = 0xe4, + OP_SGET_VOLATILE = 0xe5, + OP_SPUT_VOLATILE = 0xe6, + OP_IGET_OBJECT_VOLATILE = 0xe7, + OP_IGET_WIDE_VOLATILE = 0xe8, OP_IPUT_WIDE_VOLATILE = 0xe9, OP_SGET_WIDE_VOLATILE = 0xea, @@ -359,10 +359,11 @@ typedef enum OpCode { OP_INVOKE_VIRTUAL_QUICK_RANGE = 0xf9, OP_INVOKE_SUPER_QUICK = 0xfa, OP_INVOKE_SUPER_QUICK_RANGE = 0xfb, - OP_UNUSED_FC = 0xfc, /* OP_INVOKE_DIRECT_QUICK? */ - OP_UNUSED_FD = 0xfd, /* OP_INVOKE_DIRECT_QUICK_RANGE? */ - OP_UNUSED_FE = 0xfe, /* OP_INVOKE_INTERFACE_QUICK? */ - OP_UNUSED_FF = 0xff, /* OP_INVOKE_INTERFACE_QUICK_RANGE*/ + OP_IPUT_OBJECT_VOLATILE = 0xfc, + OP_SGET_OBJECT_VOLATILE = 0xfd, + OP_SPUT_OBJECT_VOLATILE = 0xfe, + + OP_UNUSED_FF = 0xff, /* reserved for code expansion */ } OpCode; #define kNumDalvikInstructions 256 @@ -628,11 +629,11 @@ typedef enum OpCode { H(OP_SHL_INT_LIT8), \ H(OP_SHR_INT_LIT8), \ H(OP_USHR_INT_LIT8), \ - H(OP_UNUSED_E3), \ - H(OP_UNUSED_E4), \ - H(OP_UNUSED_E5), \ - H(OP_UNUSED_E6), \ - H(OP_UNUSED_E7), \ + H(OP_IGET_VOLATILE), \ + H(OP_IPUT_VOLATILE), \ + H(OP_SGET_VOLATILE), \ + H(OP_SPUT_VOLATILE), \ + H(OP_IGET_OBJECT_VOLATILE), \ H(OP_IGET_WIDE_VOLATILE), \ H(OP_IPUT_WIDE_VOLATILE), \ H(OP_SGET_WIDE_VOLATILE), \ @@ -654,9 +655,9 @@ typedef enum OpCode { H(OP_INVOKE_VIRTUAL_QUICK_RANGE), \ H(OP_INVOKE_SUPER_QUICK), \ H(OP_INVOKE_SUPER_QUICK_RANGE), \ - H(OP_UNUSED_FC), \ - H(OP_UNUSED_FD), \ - H(OP_UNUSED_FE), \ + H(OP_IPUT_OBJECT_VOLATILE), \ + H(OP_SGET_OBJECT_VOLATILE), \ + H(OP_SPUT_OBJECT_VOLATILE), \ H(OP_UNUSED_FF), \ }; diff --git a/vm/Atomic.c b/vm/Atomic.c index 6a5381cda..4473c8568 100644 --- a/vm/Atomic.c +++ b/vm/Atomic.c @@ -56,7 +56,7 @@ int64_t dvmQuasiAtomicSwap64(int64_t value, volatile int64_t* addr) return oldValue; } -int64_t dvmQuasiAtomicRead64(volatile int64_t* addr) +int64_t dvmQuasiAtomicRead64(volatile const int64_t* addr) { return OSAtomicAdd64Barrier(0, addr); } @@ -103,7 +103,7 @@ int dvmQuasiAtomicCas64(int64_t oldvalue, int64_t newvalue, return prev != oldvalue; } -int64_t dvmQuasiAtomicRead64(volatile int64_t* addr) +int64_t dvmQuasiAtomicRead64(volatile const int64_t* addr) { int64_t value; __asm__ __volatile__ ("@ dvmQuasiAtomicRead64\n" @@ -171,7 +171,7 @@ int dvmQuasiAtomicCas64(int64_t oldvalue, int64_t newvalue, return result; } -int64_t dvmQuasiAtomicRead64(volatile int64_t* addr) +int64_t dvmQuasiAtomicRead64(volatile const int64_t* addr) { int64_t result; pthread_mutex_t* lock = SWAP_LOCK(addr); @@ -242,7 +242,7 @@ int dvmQuasiAtomicCas64(int64_t oldvalue, int64_t newvalue, return result; } -int64_t dvmQuasiAtomicRead64(volatile int64_t* addr) +int64_t dvmQuasiAtomicRead64(volatile const int64_t* addr) { int64_t result; diff --git a/vm/Atomic.h b/vm/Atomic.h index 0585c95cf..6c3a66f6b 100644 --- a/vm/Atomic.h +++ b/vm/Atomic.h @@ -43,7 +43,7 @@ int64_t dvmQuasiAtomicSwap64(int64_t value, volatile int64_t* addr); /* * Read the 64-bit value at "addr". */ -int64_t dvmQuasiAtomicRead64(volatile int64_t* addr); +int64_t dvmQuasiAtomicRead64(volatile const int64_t* addr); /* * If the value at "addr" is equal to "oldvalue", replace it with "newvalue" diff --git a/vm/DalvikVersion.h b/vm/DalvikVersion.h index 97976ddfd..3bc37b081 100644 --- a/vm/DalvikVersion.h +++ b/vm/DalvikVersion.h @@ -32,6 +32,6 @@ * way classes load changes, e.g. field ordering or vtable layout. Changing * this guarantees that the optimized form of the DEX file is regenerated. */ -#define DALVIK_VM_BUILD 22 +#define DALVIK_VM_BUILD 23 #endif /*_DALVIK_VERSION*/ diff --git a/vm/analysis/CodeVerify.c b/vm/analysis/CodeVerify.c index 30670ec8c..4310a067f 100644 --- a/vm/analysis/CodeVerify.c +++ b/vm/analysis/CodeVerify.c @@ -4459,6 +4459,7 @@ aput_1nr_common: break; case OP_IGET: + case OP_IGET_VOLATILE: tmpType = kRegTypeInteger; goto iget_1nr_common; case OP_IGET_BOOLEAN: @@ -4548,6 +4549,7 @@ iget_1nr_common: } break; case OP_IGET_OBJECT: + case OP_IGET_OBJECT_VOLATILE: { ClassObject* fieldClass; InstField* instField; @@ -4577,6 +4579,7 @@ iget_1nr_common: } break; case OP_IPUT: + case OP_IPUT_VOLATILE: tmpType = kRegTypeInteger; goto iput_1nr_common; case OP_IPUT_BOOLEAN: @@ -4687,6 +4690,7 @@ iput_1nr_common: } break; case OP_IPUT_OBJECT: + case OP_IPUT_OBJECT_VOLATILE: { ClassObject* fieldClass; ClassObject* valueClass; @@ -4748,6 +4752,7 @@ iput_1nr_common: break; case OP_SGET: + case OP_SGET_VOLATILE: tmpType = kRegTypeInteger; goto sget_1nr_common; case OP_SGET_BOOLEAN: @@ -4831,6 +4836,7 @@ sget_1nr_common: } break; case OP_SGET_OBJECT: + case OP_SGET_OBJECT_VOLATILE: { StaticField* staticField; ClassObject* fieldClass; @@ -4855,6 +4861,7 @@ sget_1nr_common: } break; case OP_SPUT: + case OP_SPUT_VOLATILE: tmpType = kRegTypeInteger; goto sput_1nr_common; case OP_SPUT_BOOLEAN: @@ -4958,6 +4965,7 @@ sput_1nr_common: } break; case OP_SPUT_OBJECT: + case OP_SPUT_OBJECT_VOLATILE: { ClassObject* fieldClass; ClassObject* valueClass; @@ -5497,16 +5505,8 @@ sput_1nr_common: case OP_UNUSED_73: case OP_UNUSED_79: case OP_UNUSED_7A: - case OP_UNUSED_E3: - case OP_UNUSED_E4: - case OP_UNUSED_E5: - case OP_UNUSED_E6: - case OP_UNUSED_E7: case OP_BREAKPOINT: case OP_UNUSED_F1: - case OP_UNUSED_FC: - case OP_UNUSED_FD: - case OP_UNUSED_FE: case OP_UNUSED_FF: failure = VERIFY_ERROR_GENERIC; break; diff --git a/vm/compiler/Dataflow.c b/vm/compiler/Dataflow.c index fe04c6733..108420129 100644 --- a/vm/compiler/Dataflow.c +++ b/vm/compiler/Dataflow.c @@ -710,19 +710,19 @@ int dvmCompilerDataFlowAttributes[kMirOpLast] = { // E2 OP_USHR_INT_LIT8 vAA, vBB, #+CC DF_DA | DF_UB, - // E3 OP_UNUSED_E3 + // E3 OP_IGET_VOLATILE DF_NOP, - // E4 OP_UNUSED_E4 + // E4 OP_IPUT_VOLATILE DF_NOP, - // E5 OP_UNUSED_E5 + // E5 OP_SGET_VOLATILE DF_NOP, - // E6 OP_UNUSED_E6 + // E6 OP_SPUT_VOLATILE DF_NOP, - // E7 OP_UNUSED_E7 + // E7 OP_IGET_OBJECT_VOLATILE DF_NOP, // E8 OP_IGET_WIDE_VOLATILE @@ -785,13 +785,13 @@ int dvmCompilerDataFlowAttributes[kMirOpLast] = { // FB OP_INVOKE_SUPER_QUICK_RANGE DF_FORMAT_3RC, - // FC OP_UNUSED_FC + // FC OP_IPUT_OBJECT_VOLATILE DF_NOP, - // FD OP_UNUSED_FD + // FD OP_SGET_OBJECT_VOLATILE DF_NOP, - // FE OP_UNUSED_FE + // FE OP_SPUT_OBJECT_VOLATILE DF_NOP, // FF OP_UNUSED_FF diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c index a28e4114d..7f601575c 100644 --- a/vm/compiler/codegen/arm/CodegenDriver.c +++ b/vm/compiler/codegen/arm/CodegenDriver.c @@ -1280,8 +1280,7 @@ static bool handleFmt10t_Fmt20t_Fmt30t(CompilationUnit *cUnit, MIR *mir, static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir) { OpCode dalvikOpCode = mir->dalvikInsn.opCode; - if (((dalvikOpCode >= OP_UNUSED_3E) && (dalvikOpCode <= OP_UNUSED_43)) || - ((dalvikOpCode >= OP_UNUSED_E3) && (dalvikOpCode <= OP_UNUSED_E7))) { + if ((dalvikOpCode >= OP_UNUSED_3E) && (dalvikOpCode <= OP_UNUSED_43)) { LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode); return true; } @@ -1292,6 +1291,8 @@ static bool handleFmt10x(CompilationUnit *cUnit, MIR *mir) case OP_UNUSED_73: case OP_UNUSED_79: case OP_UNUSED_7A: + case OP_UNUSED_F1: + case OP_UNUSED_FF: LOGE("Codegen: got unused opcode 0x%x\n",dalvikOpCode); return true; case OP_NOP: diff --git a/vm/mterp/armv4t/platform.S b/vm/mterp/armv4t/platform.S index bb2854a23..ff8d8f18d 100644 --- a/vm/mterp/armv4t/platform.S +++ b/vm/mterp/armv4t/platform.S @@ -36,3 +36,9 @@ ldmfd sp!, {\regs,lr} bx lr .endm + +/* + * Macro for data memory barrier; not meaningful pre-ARMv6K. + */ +.macro SMP_DMB gen +.endm diff --git a/vm/mterp/armv5te/OP_IGET.S b/vm/mterp/armv5te/OP_IGET.S index f463d3f62..202148463 100644 --- a/vm/mterp/armv5te/OP_IGET.S +++ b/vm/mterp/armv5te/OP_IGET.S @@ -1,4 +1,4 @@ -%default { "load":"ldr", "sqnum":"0" } +%default { "load":"ldr", "volatile":"0", "sqnum":"0" } %verify "executed" %verify "null object" %verify "field already resolved" @@ -38,6 +38,7 @@ ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null $load r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB $volatile @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A diff --git a/vm/mterp/armv5te/OP_IGET_OBJECT_VOLATILE.S b/vm/mterp/armv5te/OP_IGET_OBJECT_VOLATILE.S new file mode 100644 index 000000000..2ff232177 --- /dev/null +++ b/vm/mterp/armv5te/OP_IGET_OBJECT_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "armv5te/OP_IGET.S" {"volatile":"1"} diff --git a/vm/mterp/armv5te/OP_IGET_VOLATILE.S b/vm/mterp/armv5te/OP_IGET_VOLATILE.S new file mode 100644 index 000000000..2ff232177 --- /dev/null +++ b/vm/mterp/armv5te/OP_IGET_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "armv5te/OP_IGET.S" {"volatile":"1"} diff --git a/vm/mterp/armv5te/OP_IGET_WIDE.S b/vm/mterp/armv5te/OP_IGET_WIDE.S index b1572baf5..95944de17 100644 --- a/vm/mterp/armv5te/OP_IGET_WIDE.S +++ b/vm/mterp/armv5te/OP_IGET_WIDE.S @@ -34,7 +34,7 @@ cmp r9, #0 @ check object for null ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null - .if $volatile + .if $volatile add r0, r9, r3 @ r0<- address of field bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field .else diff --git a/vm/mterp/armv5te/OP_IPUT.S b/vm/mterp/armv5te/OP_IPUT.S index cbc5e316d..292ccd7f5 100644 --- a/vm/mterp/armv5te/OP_IPUT.S +++ b/vm/mterp/armv5te/OP_IPUT.S @@ -1,4 +1,4 @@ -%default { "store":"str", "sqnum":"0" } +%default { "store":"str", "volatile":"0", "sqnum":"0" } %verify "executed" %verify "null object" %verify "field already resolved" @@ -42,5 +42,6 @@ beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB $volatile @ releasing store $store r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction diff --git a/vm/mterp/armv5te/OP_IPUT_OBJECT_VOLATILE.S b/vm/mterp/armv5te/OP_IPUT_OBJECT_VOLATILE.S new file mode 100644 index 000000000..3b5eedd11 --- /dev/null +++ b/vm/mterp/armv5te/OP_IPUT_OBJECT_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "armv5te/OP_IPUT.S" {"volatile":"1"} diff --git a/vm/mterp/armv5te/OP_IPUT_VOLATILE.S b/vm/mterp/armv5te/OP_IPUT_VOLATILE.S new file mode 100644 index 000000000..3b5eedd11 --- /dev/null +++ b/vm/mterp/armv5te/OP_IPUT_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "armv5te/OP_IPUT.S" {"volatile":"1"} diff --git a/vm/mterp/armv5te/OP_IPUT_WIDE.S b/vm/mterp/armv5te/OP_IPUT_WIDE.S index 4a287215c..8796cbbcc 100644 --- a/vm/mterp/armv5te/OP_IPUT_WIDE.S +++ b/vm/mterp/armv5te/OP_IPUT_WIDE.S @@ -37,7 +37,7 @@ 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 $volatile + .if $volatile add r2, r9, r3 @ r2<- target address bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 .else diff --git a/vm/mterp/armv5te/OP_SGET.S b/vm/mterp/armv5te/OP_SGET.S index b71383602..a9a8eedac 100644 --- a/vm/mterp/armv5te/OP_SGET.S +++ b/vm/mterp/armv5te/OP_SGET.S @@ -1,3 +1,4 @@ +%default { "volatile":"0" } %verify "executed" %verify "field already resolved" %verify "field not yet resolved" @@ -16,6 +17,7 @@ beq .L${opcode}_resolve @ yes, do resolve .L${opcode}_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB $volatile @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 diff --git a/vm/mterp/armv5te/OP_SGET_OBJECT_VOLATILE.S b/vm/mterp/armv5te/OP_SGET_OBJECT_VOLATILE.S new file mode 100644 index 000000000..f319b8e3b --- /dev/null +++ b/vm/mterp/armv5te/OP_SGET_OBJECT_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "armv5te/OP_SGET.S" {"volatile":"1"} diff --git a/vm/mterp/armv5te/OP_SGET_VOLATILE.S b/vm/mterp/armv5te/OP_SGET_VOLATILE.S new file mode 100644 index 000000000..f319b8e3b --- /dev/null +++ b/vm/mterp/armv5te/OP_SGET_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "armv5te/OP_SGET.S" {"volatile":"1"} diff --git a/vm/mterp/armv5te/OP_SPUT.S b/vm/mterp/armv5te/OP_SPUT.S index 2dd542af8..52bfe5209 100644 --- a/vm/mterp/armv5te/OP_SPUT.S +++ b/vm/mterp/armv5te/OP_SPUT.S @@ -1,3 +1,4 @@ +%default { "volatile":"0" } %verify "executed" %verify "field already resolved" %verify "field not yet resolved" @@ -19,6 +20,7 @@ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB $volatile @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction %break diff --git a/vm/mterp/armv5te/OP_SPUT_OBJECT_VOLATILE.S b/vm/mterp/armv5te/OP_SPUT_OBJECT_VOLATILE.S new file mode 100644 index 000000000..196d8b8e9 --- /dev/null +++ b/vm/mterp/armv5te/OP_SPUT_OBJECT_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "armv5te/OP_SPUT.S" {"volatile":"1"} diff --git a/vm/mterp/armv5te/OP_SPUT_VOLATILE.S b/vm/mterp/armv5te/OP_SPUT_VOLATILE.S new file mode 100644 index 000000000..196d8b8e9 --- /dev/null +++ b/vm/mterp/armv5te/OP_SPUT_VOLATILE.S @@ -0,0 +1,2 @@ +%verify "executed" +%include "armv5te/OP_SPUT.S" {"volatile":"1"} diff --git a/vm/mterp/armv5te/OP_UNUSED_E3.S b/vm/mterp/armv5te/OP_UNUSED_E3.S deleted file mode 100644 index faa7246f5..000000000 --- a/vm/mterp/armv5te/OP_UNUSED_E3.S +++ /dev/null @@ -1 +0,0 @@ -%include "armv5te/unused.S" diff --git a/vm/mterp/armv5te/OP_UNUSED_E4.S b/vm/mterp/armv5te/OP_UNUSED_E4.S deleted file mode 100644 index faa7246f5..000000000 --- a/vm/mterp/armv5te/OP_UNUSED_E4.S +++ /dev/null @@ -1 +0,0 @@ -%include "armv5te/unused.S" diff --git a/vm/mterp/armv5te/OP_UNUSED_E5.S b/vm/mterp/armv5te/OP_UNUSED_E5.S deleted file mode 100644 index faa7246f5..000000000 --- a/vm/mterp/armv5te/OP_UNUSED_E5.S +++ /dev/null @@ -1 +0,0 @@ -%include "armv5te/unused.S" diff --git a/vm/mterp/armv5te/OP_UNUSED_E6.S b/vm/mterp/armv5te/OP_UNUSED_E6.S deleted file mode 100644 index faa7246f5..000000000 --- a/vm/mterp/armv5te/OP_UNUSED_E6.S +++ /dev/null @@ -1 +0,0 @@ -%include "armv5te/unused.S" diff --git a/vm/mterp/armv5te/OP_UNUSED_E7.S b/vm/mterp/armv5te/OP_UNUSED_E7.S deleted file mode 100644 index faa7246f5..000000000 --- a/vm/mterp/armv5te/OP_UNUSED_E7.S +++ /dev/null @@ -1 +0,0 @@ -%include "armv5te/unused.S" diff --git a/vm/mterp/armv5te/OP_UNUSED_FC.S b/vm/mterp/armv5te/OP_UNUSED_FC.S deleted file mode 100644 index faa7246f5..000000000 --- a/vm/mterp/armv5te/OP_UNUSED_FC.S +++ /dev/null @@ -1 +0,0 @@ -%include "armv5te/unused.S" diff --git a/vm/mterp/armv5te/OP_UNUSED_FD.S b/vm/mterp/armv5te/OP_UNUSED_FD.S deleted file mode 100644 index faa7246f5..000000000 --- a/vm/mterp/armv5te/OP_UNUSED_FD.S +++ /dev/null @@ -1 +0,0 @@ -%include "armv5te/unused.S" diff --git a/vm/mterp/armv5te/OP_UNUSED_FE.S b/vm/mterp/armv5te/OP_UNUSED_FE.S deleted file mode 100644 index faa7246f5..000000000 --- a/vm/mterp/armv5te/OP_UNUSED_FE.S +++ /dev/null @@ -1 +0,0 @@ -%include "armv5te/unused.S" diff --git a/vm/mterp/armv5te/header.S b/vm/mterp/armv5te/header.S index b6e98914a..bd6b7eec8 100644 --- a/vm/mterp/armv5te/header.S +++ b/vm/mterp/armv5te/header.S @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /* * ARMv5 definitions and declarations. */ diff --git a/vm/mterp/armv5te/platform.S b/vm/mterp/armv5te/platform.S index fd8533838..cd4519898 100644 --- a/vm/mterp/armv5te/platform.S +++ b/vm/mterp/armv5te/platform.S @@ -33,3 +33,9 @@ .macro LDMFD_PC regs ldmfd sp!, {\regs,pc} .endm + +/* + * Macro for data memory barrier; not meaningful pre-ARMv6K. + */ +.macro SMP_DMB gen +.endm diff --git a/vm/mterp/armv7-a/platform.S b/vm/mterp/armv7-a/platform.S new file mode 100644 index 000000000..42713b857 --- /dev/null +++ b/vm/mterp/armv7-a/platform.S @@ -0,0 +1,53 @@ +/* + * =========================================================================== + * CPU-version-specific defines + * =========================================================================== + */ + +/* + * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5. Essentially a + * one-way branch. + * + * May modify IP. Does not modify LR. + */ +.macro LDR_PC source + ldr pc, \source +.endm + +/* + * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5. + * Jump to subroutine. + * + * May modify IP and LR. + */ +.macro LDR_PC_LR source + mov lr, pc + ldr pc, \source +.endm + +/* + * Macro for "LDMFD SP!, {...regs...,PC}". + * + * May modify IP and LR. + */ +.macro LDMFD_PC regs + ldmfd sp!, {\regs,pc} +.endm + +#if !defined(ANDROID_SMP) +# error "Must define ANDROID_SMP" +#endif + +/* + * Macro for data memory barrier; not meaningful pre-ARMv6K. + * If the argument is nonzero, emit barrier; otherwise, emit nothing. + */ +.macro SMP_DMB gen +#if ANDROID_SMP != 0 + .if \gen + dmb + .endif +#else + /* not SMP */ +#endif +.endm diff --git a/vm/mterp/c/OP_IGET_OBJECT_VOLATILE.c b/vm/mterp/c/OP_IGET_OBJECT_VOLATILE.c new file mode 100644 index 000000000..35775521f --- /dev/null +++ b/vm/mterp/c/OP_IGET_OBJECT_VOLATILE.c @@ -0,0 +1,2 @@ +HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) +OP_END diff --git a/vm/mterp/c/OP_IGET_VOLATILE.c b/vm/mterp/c/OP_IGET_VOLATILE.c new file mode 100644 index 000000000..7a3be56c8 --- /dev/null +++ b/vm/mterp/c/OP_IGET_VOLATILE.c @@ -0,0 +1,2 @@ +HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, ) +OP_END diff --git a/vm/mterp/c/OP_IPUT_OBJECT_VOLATILE.c b/vm/mterp/c/OP_IPUT_OBJECT_VOLATILE.c new file mode 100644 index 000000000..cce63c130 --- /dev/null +++ b/vm/mterp/c/OP_IPUT_OBJECT_VOLATILE.c @@ -0,0 +1,2 @@ +HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) +OP_END diff --git a/vm/mterp/c/OP_IPUT_VOLATILE.c b/vm/mterp/c/OP_IPUT_VOLATILE.c new file mode 100644 index 000000000..814379e45 --- /dev/null +++ b/vm/mterp/c/OP_IPUT_VOLATILE.c @@ -0,0 +1,2 @@ +HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, ) +OP_END diff --git a/vm/mterp/c/OP_SGET_OBJECT_VOLATILE.c b/vm/mterp/c/OP_SGET_OBJECT_VOLATILE.c new file mode 100644 index 000000000..0a9049f64 --- /dev/null +++ b/vm/mterp/c/OP_SGET_OBJECT_VOLATILE.c @@ -0,0 +1,2 @@ +HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) +OP_END diff --git a/vm/mterp/c/OP_SGET_VOLATILE.c b/vm/mterp/c/OP_SGET_VOLATILE.c new file mode 100644 index 000000000..6713a54bb --- /dev/null +++ b/vm/mterp/c/OP_SGET_VOLATILE.c @@ -0,0 +1,2 @@ +HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, ) +OP_END diff --git a/vm/mterp/c/OP_SPUT_OBJECT_VOLATILE.c b/vm/mterp/c/OP_SPUT_OBJECT_VOLATILE.c new file mode 100644 index 000000000..38d6c0d2a --- /dev/null +++ b/vm/mterp/c/OP_SPUT_OBJECT_VOLATILE.c @@ -0,0 +1,2 @@ +HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) +OP_END diff --git a/vm/mterp/c/OP_SPUT_VOLATILE.c b/vm/mterp/c/OP_SPUT_VOLATILE.c new file mode 100644 index 000000000..7899d0546 --- /dev/null +++ b/vm/mterp/c/OP_SPUT_VOLATILE.c @@ -0,0 +1,2 @@ +HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, ) +OP_END diff --git a/vm/mterp/c/OP_UNUSED_E3.c b/vm/mterp/c/OP_UNUSED_E3.c deleted file mode 100644 index d52836b9e..000000000 --- a/vm/mterp/c/OP_UNUSED_E3.c +++ /dev/null @@ -1,2 +0,0 @@ -HANDLE_OPCODE(OP_UNUSED_E3) -OP_END diff --git a/vm/mterp/c/OP_UNUSED_E4.c b/vm/mterp/c/OP_UNUSED_E4.c deleted file mode 100644 index 30a714fc3..000000000 --- a/vm/mterp/c/OP_UNUSED_E4.c +++ /dev/null @@ -1,2 +0,0 @@ -HANDLE_OPCODE(OP_UNUSED_E4) -OP_END diff --git a/vm/mterp/c/OP_UNUSED_E5.c b/vm/mterp/c/OP_UNUSED_E5.c deleted file mode 100644 index 0cc6ff9a2..000000000 --- a/vm/mterp/c/OP_UNUSED_E5.c +++ /dev/null @@ -1,2 +0,0 @@ -HANDLE_OPCODE(OP_UNUSED_E5) -OP_END diff --git a/vm/mterp/c/OP_UNUSED_E6.c b/vm/mterp/c/OP_UNUSED_E6.c deleted file mode 100644 index 255dcd14b..000000000 --- a/vm/mterp/c/OP_UNUSED_E6.c +++ /dev/null @@ -1,2 +0,0 @@ -HANDLE_OPCODE(OP_UNUSED_E6) -OP_END diff --git a/vm/mterp/c/OP_UNUSED_E7.c b/vm/mterp/c/OP_UNUSED_E7.c deleted file mode 100644 index b910f714f..000000000 --- a/vm/mterp/c/OP_UNUSED_E7.c +++ /dev/null @@ -1,2 +0,0 @@ -HANDLE_OPCODE(OP_UNUSED_E7) -OP_END diff --git a/vm/mterp/c/OP_UNUSED_FC.c b/vm/mterp/c/OP_UNUSED_FC.c deleted file mode 100644 index 4b49684a6..000000000 --- a/vm/mterp/c/OP_UNUSED_FC.c +++ /dev/null @@ -1,2 +0,0 @@ -HANDLE_OPCODE(OP_UNUSED_FC) -OP_END diff --git a/vm/mterp/c/OP_UNUSED_FD.c b/vm/mterp/c/OP_UNUSED_FD.c deleted file mode 100644 index c10efaf0b..000000000 --- a/vm/mterp/c/OP_UNUSED_FD.c +++ /dev/null @@ -1,2 +0,0 @@ -HANDLE_OPCODE(OP_UNUSED_FD) -OP_END diff --git a/vm/mterp/c/OP_UNUSED_FE.c b/vm/mterp/c/OP_UNUSED_FE.c deleted file mode 100644 index 7b097d905..000000000 --- a/vm/mterp/c/OP_UNUSED_FE.c +++ /dev/null @@ -1,2 +0,0 @@ -HANDLE_OPCODE(OP_UNUSED_FE) -OP_END diff --git a/vm/mterp/config-armv7-a b/vm/mterp/config-armv7-a index be32042ef..e66640c65 100644 --- a/vm/mterp/config-armv7-a +++ b/vm/mterp/config-armv7-a @@ -34,7 +34,7 @@ import armv5te/header.S import cstubs/stubdefs.c # highly-platform-specific defs -import armv5te/platform.S +import armv7-a/platform.S # common defs for the C helpers; include this before the instruction handlers import c/opcommon.c diff --git a/vm/mterp/config-armv7-a-neon b/vm/mterp/config-armv7-a-neon index be32042ef..e66640c65 100644 --- a/vm/mterp/config-armv7-a-neon +++ b/vm/mterp/config-armv7-a-neon @@ -34,7 +34,7 @@ import armv5te/header.S import cstubs/stubdefs.c # highly-platform-specific defs -import armv5te/platform.S +import armv7-a/platform.S # common defs for the C helpers; include this before the instruction handlers import c/opcommon.c diff --git a/vm/mterp/config-x86 b/vm/mterp/config-x86 index 627e06cd6..78ae1a0e3 100644 --- a/vm/mterp/config-x86 +++ b/vm/mterp/config-x86 @@ -35,6 +35,14 @@ import c/opcommon.c op-start x86 # stub -- need native impl op OP_EXECUTE_INLINE_RANGE c + op OP_IGET_VOLATILE c + op OP_IPUT_VOLATILE c + op OP_SGET_VOLATILE c + op OP_SPUT_VOLATILE c + op OP_IGET_OBJECT_VOLATILE c + op OP_IPUT_OBJECT_VOLATILE c + op OP_SGET_OBJECT_VOLATILE c + op OP_SPUT_OBJECT_VOLATILE c op OP_IGET_WIDE_VOLATILE c op OP_IPUT_WIDE_VOLATILE c op OP_SGET_WIDE_VOLATILE c diff --git a/vm/mterp/config-x86-atom b/vm/mterp/config-x86-atom index 0d9b193de..970253c09 100644 --- a/vm/mterp/config-x86-atom +++ b/vm/mterp/config-x86-atom @@ -286,6 +286,14 @@ op-start x86-atom # TODO: provide native implementations op OP_BREAKPOINT c op OP_EXECUTE_INLINE_RANGE c +op OP_IGET_VOLATILE c +op OP_IPUT_VOLATILE c +op OP_SGET_VOLATILE c +op OP_SPUT_VOLATILE c +op OP_IGET_OBJECT_VOLATILE c +op OP_IPUT_OBJECT_VOLATILE c +op OP_SGET_OBJECT_VOLATILE c +op OP_SPUT_OBJECT_VOLATILE c op OP_IGET_WIDE_VOLATILE c op OP_IPUT_WIDE_VOLATILE c op OP_SGET_WIDE_VOLATILE c diff --git a/vm/mterp/out/InterpAsm-armv4t.S b/vm/mterp/out/InterpAsm-armv4t.S index 17fb783e6..ec129a341 100644 --- a/vm/mterp/out/InterpAsm-armv4t.S +++ b/vm/mterp/out/InterpAsm-armv4t.S @@ -20,6 +20,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /* * ARMv5 definitions and declarations. */ @@ -242,6 +243,13 @@ unspecified registers or condition codes. ldmfd sp!, {\regs,pc} .endm +/* + * Macro for data memory barrier; not meaningful pre-ARMv6K. + */ +.macro SMP_DMB gen +.endm + + /* File: armv5te/entry.S */ /* * Copyright (C) 2008 The Android Open Source Project @@ -2807,6 +2815,7 @@ dalvik_inst: beq .LOP_SGET_resolve @ yes, do resolve .LOP_SGET_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2860,6 +2869,7 @@ dalvik_inst: beq .LOP_SGET_OBJECT_resolve @ yes, do resolve .LOP_SGET_OBJECT_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2886,6 +2896,7 @@ dalvik_inst: beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve .LOP_SGET_BOOLEAN_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2912,6 +2923,7 @@ dalvik_inst: beq .LOP_SGET_BYTE_resolve @ yes, do resolve .LOP_SGET_BYTE_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2938,6 +2950,7 @@ dalvik_inst: beq .LOP_SGET_CHAR_resolve @ yes, do resolve .LOP_SGET_CHAR_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2964,6 +2977,7 @@ dalvik_inst: beq .LOP_SGET_SHORT_resolve @ yes, do resolve .LOP_SGET_SHORT_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2992,6 +3006,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3045,6 +3060,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3071,6 +3087,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3097,6 +3114,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3123,6 +3141,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3149,6 +3168,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -7402,42 +7422,140 @@ d2i_doconv: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E3: /* 0xe3 */ -/* File: armv5te/OP_UNUSED_E3.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IGET_VOLATILE: /* 0xe3 */ +/* File: armv5te/OP_IGET_VOLATILE.S */ +/* File: armv5te/OP_IGET.S */ + /* + * General 32-bit instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + /* op 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<- pDvmDex->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_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_VOLATILE_finish + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E4: /* 0xe4 */ -/* File: armv5te/OP_UNUSED_E4.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IPUT_VOLATILE: /* 0xe4 */ +/* File: armv5te/OP_IPUT_VOLATILE.S */ +/* File: armv5te/OP_IPUT.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op 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<- pDvmDex->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_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_VOLATILE_finish @ yes, finish up + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E5: /* 0xe5 */ -/* File: armv5te/OP_UNUSED_E5.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SGET_VOLATILE: /* 0xe5 */ +/* File: armv5te/OP_SGET_VOLATILE.S */ +/* File: armv5te/OP_SGET.S */ + /* + * General 32-bit SGET handler. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op 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_VOLATILE_resolve @ yes, do resolve +.LOP_SGET_VOLATILE_finish: @ field ptr in r0 + ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + SET_VREG(r1, r2) @ fp[AA]<- r1 + GET_INST_OPCODE(ip) @ extract opcode from rINST + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E6: /* 0xe6 */ -/* File: armv5te/OP_UNUSED_E6.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SPUT_VOLATILE: /* 0xe6 */ +/* File: armv5te/OP_SPUT_VOLATILE.S */ +/* File: armv5te/OP_SPUT.S */ + /* + * General 32-bit SPUT handler. + * + * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op 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_SPUT_VOLATILE_resolve @ yes, do resolve +.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_VREG(r1, r2) @ r1<- fp[AA] + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r1, [r0, #offStaticField_value] @ field<- vAA + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E7: /* 0xe7 */ -/* File: armv5te/OP_UNUSED_E7.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ +/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_IGET.S */ + /* + * General 32-bit instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + /* op 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<- pDvmDex->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_OBJECT_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_OBJECT_VOLATILE_finish + b common_exceptionThrown /* ------------------------------ */ @@ -7882,26 +8000,84 @@ d2i_doconv: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FC: /* 0xfc */ -/* File: armv5te/OP_UNUSED_FC.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ +/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_IPUT.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op 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<- pDvmDex->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_OBJECT_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_OBJECT_VOLATILE_finish @ yes, finish up + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FD: /* 0xfd */ -/* File: armv5te/OP_UNUSED_FD.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ +/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_SGET.S */ + /* + * General 32-bit SGET handler. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op 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_OBJECT_VOLATILE_resolve @ yes, do resolve +.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 + ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + SET_VREG(r1, r2) @ fp[AA]<- r1 + GET_INST_OPCODE(ip) @ extract opcode from rINST + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FE: /* 0xfe */ -/* File: armv5te/OP_UNUSED_FE.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ +/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_SPUT.S */ + /* + * General 32-bit SPUT handler. + * + * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op 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_SPUT_OBJECT_VOLATILE_resolve @ yes, do resolve +.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_VREG(r1, r2) @ r1<- fp[AA] + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r1, [r0, #offStaticField_value] @ field<- vAA + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ @@ -8555,6 +8731,7 @@ OP_CMPG_FLOAT_nan: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8601,6 +8778,7 @@ OP_CMPG_FLOAT_nan: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8621,6 +8799,7 @@ OP_CMPG_FLOAT_nan: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8641,6 +8820,7 @@ OP_CMPG_FLOAT_nan: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8661,6 +8841,7 @@ OP_CMPG_FLOAT_nan: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8681,6 +8862,7 @@ OP_CMPG_FLOAT_nan: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8705,6 +8887,7 @@ OP_CMPG_FLOAT_nan: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8750,6 +8933,7 @@ OP_CMPG_FLOAT_nan: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8770,6 +8954,7 @@ OP_CMPG_FLOAT_nan: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8790,6 +8975,7 @@ OP_CMPG_FLOAT_nan: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8810,6 +8996,7 @@ OP_CMPG_FLOAT_nan: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8830,6 +9017,7 @@ OP_CMPG_FLOAT_nan: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -9324,6 +9512,99 @@ d2l_doconv: stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 GOTO_OPCODE(ip) @ jump to next instruction +/* continuation for OP_IGET_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IGET_VOLATILE_finish: + @bl common_squeak0 + cmp r9, #0 @ check object for null + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + beq common_errNullObject @ object was null + ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- A+ + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + and r2, r2, #15 @ r2<- A + GET_INST_OPCODE(ip) @ extract opcode from rINST + SET_VREG(r0, r2) @ fp[A]<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_IPUT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IPUT_VOLATILE_finish: + @bl common_squeak0 + mov r1, rINST, lsr #8 @ r1<- A+ + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + and r1, r1, #15 @ r1<- A + cmp r9, #0 @ check object for null + GET_VREG(r0, r1) @ r0<- fp[A] + beq common_errNullObject @ object was null + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_SGET_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SGET_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_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_SPUT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SPUT_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_SPUT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_IGET_OBJECT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IGET_OBJECT_VOLATILE_finish: + @bl common_squeak0 + cmp r9, #0 @ check object for null + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + beq common_errNullObject @ object was null + ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- A+ + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + and r2, r2, #15 @ r2<- A + GET_INST_OPCODE(ip) @ extract opcode from rINST + SET_VREG(r0, r2) @ fp[A]<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + /* continuation for OP_IGET_WIDE_VOLATILE */ /* @@ -9475,6 +9756,57 @@ d2l_doconv: .LOP_EXECUTE_INLINE_RANGE_table: .word gDvmInlineOpsTable +/* continuation for OP_IPUT_OBJECT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IPUT_OBJECT_VOLATILE_finish: + @bl common_squeak0 + mov r1, rINST, lsr #8 @ r1<- A+ + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + and r1, r1, #15 @ r1<- A + cmp r9, #0 @ check object for null + GET_VREG(r0, r1) @ r0<- fp[A] + beq common_errNullObject @ object was null + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_SGET_OBJECT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SGET_OBJECT_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_OBJECT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_SPUT_OBJECT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SPUT_OBJECT_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_SPUT_OBJECT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + .size dvmAsmSisterStart, .-dvmAsmSisterStart .global dvmAsmSisterEnd dvmAsmSisterEnd: diff --git a/vm/mterp/out/InterpAsm-armv5te-vfp.S b/vm/mterp/out/InterpAsm-armv5te-vfp.S index bfcd1108a..de4d148c5 100644 --- a/vm/mterp/out/InterpAsm-armv5te-vfp.S +++ b/vm/mterp/out/InterpAsm-armv5te-vfp.S @@ -20,6 +20,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /* * ARMv5 definitions and declarations. */ @@ -242,6 +243,13 @@ unspecified registers or condition codes. ldmfd sp!, {\regs,pc} .endm +/* + * Macro for data memory barrier; not meaningful pre-ARMv6K. + */ +.macro SMP_DMB gen +.endm + + /* File: armv5te/entry.S */ /* * Copyright (C) 2008 The Android Open Source Project @@ -2787,6 +2795,7 @@ dalvik_inst: beq .LOP_SGET_resolve @ yes, do resolve .LOP_SGET_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2840,6 +2849,7 @@ dalvik_inst: beq .LOP_SGET_OBJECT_resolve @ yes, do resolve .LOP_SGET_OBJECT_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2866,6 +2876,7 @@ dalvik_inst: beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve .LOP_SGET_BOOLEAN_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2892,6 +2903,7 @@ dalvik_inst: beq .LOP_SGET_BYTE_resolve @ yes, do resolve .LOP_SGET_BYTE_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2918,6 +2930,7 @@ dalvik_inst: beq .LOP_SGET_CHAR_resolve @ yes, do resolve .LOP_SGET_CHAR_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2944,6 +2957,7 @@ dalvik_inst: beq .LOP_SGET_SHORT_resolve @ yes, do resolve .LOP_SGET_SHORT_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2972,6 +2986,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3025,6 +3040,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3051,6 +3067,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3077,6 +3094,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3103,6 +3121,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3129,6 +3148,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -7082,42 +7102,140 @@ dalvik_inst: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E3: /* 0xe3 */ -/* File: armv5te/OP_UNUSED_E3.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IGET_VOLATILE: /* 0xe3 */ +/* File: armv5te/OP_IGET_VOLATILE.S */ +/* File: armv5te/OP_IGET.S */ + /* + * General 32-bit instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + /* op 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<- pDvmDex->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_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_VOLATILE_finish + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E4: /* 0xe4 */ -/* File: armv5te/OP_UNUSED_E4.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IPUT_VOLATILE: /* 0xe4 */ +/* File: armv5te/OP_IPUT_VOLATILE.S */ +/* File: armv5te/OP_IPUT.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op 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<- pDvmDex->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_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_VOLATILE_finish @ yes, finish up + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E5: /* 0xe5 */ -/* File: armv5te/OP_UNUSED_E5.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SGET_VOLATILE: /* 0xe5 */ +/* File: armv5te/OP_SGET_VOLATILE.S */ +/* File: armv5te/OP_SGET.S */ + /* + * General 32-bit SGET handler. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op 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_VOLATILE_resolve @ yes, do resolve +.LOP_SGET_VOLATILE_finish: @ field ptr in r0 + ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + SET_VREG(r1, r2) @ fp[AA]<- r1 + GET_INST_OPCODE(ip) @ extract opcode from rINST + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E6: /* 0xe6 */ -/* File: armv5te/OP_UNUSED_E6.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SPUT_VOLATILE: /* 0xe6 */ +/* File: armv5te/OP_SPUT_VOLATILE.S */ +/* File: armv5te/OP_SPUT.S */ + /* + * General 32-bit SPUT handler. + * + * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op 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_SPUT_VOLATILE_resolve @ yes, do resolve +.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_VREG(r1, r2) @ r1<- fp[AA] + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r1, [r0, #offStaticField_value] @ field<- vAA + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E7: /* 0xe7 */ -/* File: armv5te/OP_UNUSED_E7.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ +/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_IGET.S */ + /* + * General 32-bit instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + /* op 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<- pDvmDex->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_OBJECT_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_OBJECT_VOLATILE_finish + b common_exceptionThrown /* ------------------------------ */ @@ -7560,26 +7678,84 @@ dalvik_inst: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FC: /* 0xfc */ -/* File: armv5te/OP_UNUSED_FC.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ +/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_IPUT.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op 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<- pDvmDex->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_OBJECT_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_OBJECT_VOLATILE_finish @ yes, finish up + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FD: /* 0xfd */ -/* File: armv5te/OP_UNUSED_FD.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ +/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_SGET.S */ + /* + * General 32-bit SGET handler. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op 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_OBJECT_VOLATILE_resolve @ yes, do resolve +.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 + ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + SET_VREG(r1, r2) @ fp[AA]<- r1 + GET_INST_OPCODE(ip) @ extract opcode from rINST + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FE: /* 0xfe */ -/* File: armv5te/OP_UNUSED_FE.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ +/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_SPUT.S */ + /* + * General 32-bit SPUT handler. + * + * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op 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_SPUT_OBJECT_VOLATILE_resolve @ yes, do resolve +.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_VREG(r1, r2) @ r1<- fp[AA] + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r1, [r0, #offStaticField_value] @ field<- vAA + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ @@ -8095,6 +8271,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8113,7 +8290,7 @@ dvmAsmSisterStart: cmp r9, #0 @ check object for null ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null - .if 0 + .if 0 add r0, r9, r3 @ r0<- address of field bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field .else @@ -8140,6 +8317,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8160,6 +8338,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8180,6 +8359,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8200,6 +8380,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8220,6 +8401,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8244,6 +8426,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8264,7 +8447,7 @@ dvmAsmSisterStart: 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 0 + .if 0 add r2, r9, r3 @ r2<- target address bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 .else @@ -8289,6 +8472,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8309,6 +8493,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8329,6 +8514,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8349,6 +8535,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8369,6 +8556,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8863,6 +9051,99 @@ d2l_doconv: stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 GOTO_OPCODE(ip) @ jump to next instruction +/* continuation for OP_IGET_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IGET_VOLATILE_finish: + @bl common_squeak0 + cmp r9, #0 @ check object for null + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + beq common_errNullObject @ object was null + ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- A+ + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + and r2, r2, #15 @ r2<- A + GET_INST_OPCODE(ip) @ extract opcode from rINST + SET_VREG(r0, r2) @ fp[A]<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_IPUT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IPUT_VOLATILE_finish: + @bl common_squeak0 + mov r1, rINST, lsr #8 @ r1<- A+ + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + and r1, r1, #15 @ r1<- A + cmp r9, #0 @ check object for null + GET_VREG(r0, r1) @ r0<- fp[A] + beq common_errNullObject @ object was null + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_SGET_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SGET_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_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_SPUT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SPUT_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_SPUT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_IGET_OBJECT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IGET_OBJECT_VOLATILE_finish: + @bl common_squeak0 + cmp r9, #0 @ check object for null + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + beq common_errNullObject @ object was null + ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- A+ + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + and r2, r2, #15 @ r2<- A + GET_INST_OPCODE(ip) @ extract opcode from rINST + SET_VREG(r0, r2) @ fp[A]<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + /* continuation for OP_IGET_WIDE_VOLATILE */ /* @@ -8874,7 +9155,7 @@ d2l_doconv: 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 + .if 1 add r0, r9, r3 @ r0<- address of field bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field .else @@ -8905,7 +9186,7 @@ d2l_doconv: 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 + .if 1 add r2, r9, r3 @ r2<- target address bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 .else @@ -9013,6 +9294,57 @@ d2l_doconv: .LOP_EXECUTE_INLINE_RANGE_table: .word gDvmInlineOpsTable +/* continuation for OP_IPUT_OBJECT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IPUT_OBJECT_VOLATILE_finish: + @bl common_squeak0 + mov r1, rINST, lsr #8 @ r1<- A+ + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + and r1, r1, #15 @ r1<- A + cmp r9, #0 @ check object for null + GET_VREG(r0, r1) @ r0<- fp[A] + beq common_errNullObject @ object was null + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_SGET_OBJECT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SGET_OBJECT_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_OBJECT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_SPUT_OBJECT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SPUT_OBJECT_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_SPUT_OBJECT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + .size dvmAsmSisterStart, .-dvmAsmSisterStart .global dvmAsmSisterEnd dvmAsmSisterEnd: diff --git a/vm/mterp/out/InterpAsm-armv5te.S b/vm/mterp/out/InterpAsm-armv5te.S index 9f69bd016..f82518367 100644 --- a/vm/mterp/out/InterpAsm-armv5te.S +++ b/vm/mterp/out/InterpAsm-armv5te.S @@ -20,6 +20,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /* * ARMv5 definitions and declarations. */ @@ -242,6 +243,13 @@ unspecified registers or condition codes. ldmfd sp!, {\regs,pc} .endm +/* + * Macro for data memory barrier; not meaningful pre-ARMv6K. + */ +.macro SMP_DMB gen +.endm + + /* File: armv5te/entry.S */ /* * Copyright (C) 2008 The Android Open Source Project @@ -2809,6 +2817,7 @@ dalvik_inst: beq .LOP_SGET_resolve @ yes, do resolve .LOP_SGET_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2862,6 +2871,7 @@ dalvik_inst: beq .LOP_SGET_OBJECT_resolve @ yes, do resolve .LOP_SGET_OBJECT_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2888,6 +2898,7 @@ dalvik_inst: beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve .LOP_SGET_BOOLEAN_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2914,6 +2925,7 @@ dalvik_inst: beq .LOP_SGET_BYTE_resolve @ yes, do resolve .LOP_SGET_BYTE_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2940,6 +2952,7 @@ dalvik_inst: beq .LOP_SGET_CHAR_resolve @ yes, do resolve .LOP_SGET_CHAR_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2966,6 +2979,7 @@ dalvik_inst: beq .LOP_SGET_SHORT_resolve @ yes, do resolve .LOP_SGET_SHORT_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2994,6 +3008,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3047,6 +3062,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3073,6 +3089,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3099,6 +3116,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3125,6 +3143,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3151,6 +3170,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -7404,42 +7424,140 @@ d2i_doconv: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E3: /* 0xe3 */ -/* File: armv5te/OP_UNUSED_E3.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IGET_VOLATILE: /* 0xe3 */ +/* File: armv5te/OP_IGET_VOLATILE.S */ +/* File: armv5te/OP_IGET.S */ + /* + * General 32-bit instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + /* op 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<- pDvmDex->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_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_VOLATILE_finish + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E4: /* 0xe4 */ -/* File: armv5te/OP_UNUSED_E4.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IPUT_VOLATILE: /* 0xe4 */ +/* File: armv5te/OP_IPUT_VOLATILE.S */ +/* File: armv5te/OP_IPUT.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op 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<- pDvmDex->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_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_VOLATILE_finish @ yes, finish up + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E5: /* 0xe5 */ -/* File: armv5te/OP_UNUSED_E5.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SGET_VOLATILE: /* 0xe5 */ +/* File: armv5te/OP_SGET_VOLATILE.S */ +/* File: armv5te/OP_SGET.S */ + /* + * General 32-bit SGET handler. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op 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_VOLATILE_resolve @ yes, do resolve +.LOP_SGET_VOLATILE_finish: @ field ptr in r0 + ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + SET_VREG(r1, r2) @ fp[AA]<- r1 + GET_INST_OPCODE(ip) @ extract opcode from rINST + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E6: /* 0xe6 */ -/* File: armv5te/OP_UNUSED_E6.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SPUT_VOLATILE: /* 0xe6 */ +/* File: armv5te/OP_SPUT_VOLATILE.S */ +/* File: armv5te/OP_SPUT.S */ + /* + * General 32-bit SPUT handler. + * + * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op 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_SPUT_VOLATILE_resolve @ yes, do resolve +.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_VREG(r1, r2) @ r1<- fp[AA] + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r1, [r0, #offStaticField_value] @ field<- vAA + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E7: /* 0xe7 */ -/* File: armv5te/OP_UNUSED_E7.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ +/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_IGET.S */ + /* + * General 32-bit instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + /* op 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<- pDvmDex->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_OBJECT_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_OBJECT_VOLATILE_finish + b common_exceptionThrown /* ------------------------------ */ @@ -7882,26 +8000,84 @@ d2i_doconv: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FC: /* 0xfc */ -/* File: armv5te/OP_UNUSED_FC.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ +/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_IPUT.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op 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<- pDvmDex->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_OBJECT_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_OBJECT_VOLATILE_finish @ yes, finish up + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FD: /* 0xfd */ -/* File: armv5te/OP_UNUSED_FD.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ +/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_SGET.S */ + /* + * General 32-bit SGET handler. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op 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_OBJECT_VOLATILE_resolve @ yes, do resolve +.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 + ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + SET_VREG(r1, r2) @ fp[AA]<- r1 + GET_INST_OPCODE(ip) @ extract opcode from rINST + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FE: /* 0xfe */ -/* File: armv5te/OP_UNUSED_FE.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ +/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_SPUT.S */ + /* + * General 32-bit SPUT handler. + * + * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op 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_SPUT_OBJECT_VOLATILE_resolve @ yes, do resolve +.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_VREG(r1, r2) @ r1<- fp[AA] + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r1, [r0, #offStaticField_value] @ field<- vAA + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ @@ -8553,6 +8729,7 @@ OP_CMPG_FLOAT_nan: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8571,7 +8748,7 @@ OP_CMPG_FLOAT_nan: cmp r9, #0 @ check object for null ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null - .if 0 + .if 0 add r0, r9, r3 @ r0<- address of field bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field .else @@ -8598,6 +8775,7 @@ OP_CMPG_FLOAT_nan: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8618,6 +8796,7 @@ OP_CMPG_FLOAT_nan: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8638,6 +8817,7 @@ OP_CMPG_FLOAT_nan: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8658,6 +8838,7 @@ OP_CMPG_FLOAT_nan: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8678,6 +8859,7 @@ OP_CMPG_FLOAT_nan: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8702,6 +8884,7 @@ OP_CMPG_FLOAT_nan: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8722,7 +8905,7 @@ OP_CMPG_FLOAT_nan: 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 0 + .if 0 add r2, r9, r3 @ r2<- target address bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 .else @@ -8747,6 +8930,7 @@ OP_CMPG_FLOAT_nan: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8767,6 +8951,7 @@ OP_CMPG_FLOAT_nan: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8787,6 +8972,7 @@ OP_CMPG_FLOAT_nan: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8807,6 +8993,7 @@ OP_CMPG_FLOAT_nan: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8827,6 +9014,7 @@ OP_CMPG_FLOAT_nan: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -9321,6 +9509,99 @@ d2l_doconv: stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 GOTO_OPCODE(ip) @ jump to next instruction +/* continuation for OP_IGET_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IGET_VOLATILE_finish: + @bl common_squeak0 + cmp r9, #0 @ check object for null + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + beq common_errNullObject @ object was null + ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- A+ + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + and r2, r2, #15 @ r2<- A + GET_INST_OPCODE(ip) @ extract opcode from rINST + SET_VREG(r0, r2) @ fp[A]<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_IPUT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IPUT_VOLATILE_finish: + @bl common_squeak0 + mov r1, rINST, lsr #8 @ r1<- A+ + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + and r1, r1, #15 @ r1<- A + cmp r9, #0 @ check object for null + GET_VREG(r0, r1) @ r0<- fp[A] + beq common_errNullObject @ object was null + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_SGET_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SGET_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_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_SPUT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SPUT_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_SPUT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_IGET_OBJECT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IGET_OBJECT_VOLATILE_finish: + @bl common_squeak0 + cmp r9, #0 @ check object for null + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + beq common_errNullObject @ object was null + ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- A+ + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + and r2, r2, #15 @ r2<- A + GET_INST_OPCODE(ip) @ extract opcode from rINST + SET_VREG(r0, r2) @ fp[A]<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + /* continuation for OP_IGET_WIDE_VOLATILE */ /* @@ -9332,7 +9613,7 @@ d2l_doconv: 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 + .if 1 add r0, r9, r3 @ r0<- address of field bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field .else @@ -9363,7 +9644,7 @@ d2l_doconv: 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 + .if 1 add r2, r9, r3 @ r2<- target address bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 .else @@ -9471,6 +9752,57 @@ d2l_doconv: .LOP_EXECUTE_INLINE_RANGE_table: .word gDvmInlineOpsTable +/* continuation for OP_IPUT_OBJECT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IPUT_OBJECT_VOLATILE_finish: + @bl common_squeak0 + mov r1, rINST, lsr #8 @ r1<- A+ + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + and r1, r1, #15 @ r1<- A + cmp r9, #0 @ check object for null + GET_VREG(r0, r1) @ r0<- fp[A] + beq common_errNullObject @ object was null + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_SGET_OBJECT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SGET_OBJECT_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_OBJECT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_SPUT_OBJECT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SPUT_OBJECT_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_SPUT_OBJECT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + .size dvmAsmSisterStart, .-dvmAsmSisterStart .global dvmAsmSisterEnd dvmAsmSisterEnd: diff --git a/vm/mterp/out/InterpAsm-armv7-a-neon.S b/vm/mterp/out/InterpAsm-armv7-a-neon.S index 3ac09aaf2..a7f7eb0e1 100644 --- a/vm/mterp/out/InterpAsm-armv7-a-neon.S +++ b/vm/mterp/out/InterpAsm-armv7-a-neon.S @@ -20,6 +20,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /* * ARMv5 definitions and declarations. */ @@ -205,7 +206,7 @@ unspecified registers or condition codes. #include "../common/jit-config.h" #endif -/* File: armv5te/platform.S */ +/* File: armv7-a/platform.S */ /* * =========================================================================== * CPU-version-specific defines @@ -242,6 +243,24 @@ unspecified registers or condition codes. ldmfd sp!, {\regs,pc} .endm +#if !defined(ANDROID_SMP) +# error "Must define ANDROID_SMP" +#endif + +/* + * Macro for data memory barrier; not meaningful pre-ARMv6K. + * If the argument is nonzero, emit barrier; otherwise, emit nothing. + */ +.macro SMP_DMB gen +#if ANDROID_SMP != 0 + .if \gen + dmb + .endif +#else + /* not SMP */ +#endif +.endm + /* File: armv5te/entry.S */ /* * Copyright (C) 2008 The Android Open Source Project @@ -2777,6 +2796,7 @@ dalvik_inst: beq .LOP_SGET_resolve @ yes, do resolve .LOP_SGET_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2830,6 +2850,7 @@ dalvik_inst: beq .LOP_SGET_OBJECT_resolve @ yes, do resolve .LOP_SGET_OBJECT_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2856,6 +2877,7 @@ dalvik_inst: beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve .LOP_SGET_BOOLEAN_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2882,6 +2904,7 @@ dalvik_inst: beq .LOP_SGET_BYTE_resolve @ yes, do resolve .LOP_SGET_BYTE_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2908,6 +2931,7 @@ dalvik_inst: beq .LOP_SGET_CHAR_resolve @ yes, do resolve .LOP_SGET_CHAR_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2934,6 +2958,7 @@ dalvik_inst: beq .LOP_SGET_SHORT_resolve @ yes, do resolve .LOP_SGET_SHORT_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2962,6 +2987,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3015,6 +3041,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3041,6 +3068,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3067,6 +3095,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3093,6 +3122,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3119,6 +3149,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -7026,42 +7057,140 @@ dalvik_inst: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E3: /* 0xe3 */ -/* File: armv5te/OP_UNUSED_E3.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IGET_VOLATILE: /* 0xe3 */ +/* File: armv5te/OP_IGET_VOLATILE.S */ +/* File: armv5te/OP_IGET.S */ + /* + * General 32-bit instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + /* op 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<- pDvmDex->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_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_VOLATILE_finish + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E4: /* 0xe4 */ -/* File: armv5te/OP_UNUSED_E4.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IPUT_VOLATILE: /* 0xe4 */ +/* File: armv5te/OP_IPUT_VOLATILE.S */ +/* File: armv5te/OP_IPUT.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op 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<- pDvmDex->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_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_VOLATILE_finish @ yes, finish up + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E5: /* 0xe5 */ -/* File: armv5te/OP_UNUSED_E5.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SGET_VOLATILE: /* 0xe5 */ +/* File: armv5te/OP_SGET_VOLATILE.S */ +/* File: armv5te/OP_SGET.S */ + /* + * General 32-bit SGET handler. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op 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_VOLATILE_resolve @ yes, do resolve +.LOP_SGET_VOLATILE_finish: @ field ptr in r0 + ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + SET_VREG(r1, r2) @ fp[AA]<- r1 + GET_INST_OPCODE(ip) @ extract opcode from rINST + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E6: /* 0xe6 */ -/* File: armv5te/OP_UNUSED_E6.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SPUT_VOLATILE: /* 0xe6 */ +/* File: armv5te/OP_SPUT_VOLATILE.S */ +/* File: armv5te/OP_SPUT.S */ + /* + * General 32-bit SPUT handler. + * + * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op 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_SPUT_VOLATILE_resolve @ yes, do resolve +.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_VREG(r1, r2) @ r1<- fp[AA] + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r1, [r0, #offStaticField_value] @ field<- vAA + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E7: /* 0xe7 */ -/* File: armv5te/OP_UNUSED_E7.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ +/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_IGET.S */ + /* + * General 32-bit instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + /* op 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<- pDvmDex->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_OBJECT_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_OBJECT_VOLATILE_finish + b common_exceptionThrown /* ------------------------------ */ @@ -7500,26 +7629,84 @@ dalvik_inst: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FC: /* 0xfc */ -/* File: armv5te/OP_UNUSED_FC.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ +/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_IPUT.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op 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<- pDvmDex->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_OBJECT_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_OBJECT_VOLATILE_finish @ yes, finish up + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FD: /* 0xfd */ -/* File: armv5te/OP_UNUSED_FD.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ +/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_SGET.S */ + /* + * General 32-bit SGET handler. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op 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_OBJECT_VOLATILE_resolve @ yes, do resolve +.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 + ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + SET_VREG(r1, r2) @ fp[AA]<- r1 + GET_INST_OPCODE(ip) @ extract opcode from rINST + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FE: /* 0xfe */ -/* File: armv5te/OP_UNUSED_FE.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ +/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_SPUT.S */ + /* + * General 32-bit SPUT handler. + * + * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op 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_SPUT_OBJECT_VOLATILE_resolve @ yes, do resolve +.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_VREG(r1, r2) @ r1<- fp[AA] + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r1, [r0, #offStaticField_value] @ field<- vAA + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ @@ -8073,6 +8260,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8093,6 +8281,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8113,6 +8302,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8133,6 +8323,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8153,6 +8344,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8215,6 +8407,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8235,6 +8428,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8255,6 +8449,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8275,6 +8470,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8295,6 +8491,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8789,6 +8986,99 @@ d2l_doconv: stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 GOTO_OPCODE(ip) @ jump to next instruction +/* continuation for OP_IGET_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IGET_VOLATILE_finish: + @bl common_squeak0 + cmp r9, #0 @ check object for null + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + beq common_errNullObject @ object was null + ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- A+ + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + and r2, r2, #15 @ r2<- A + GET_INST_OPCODE(ip) @ extract opcode from rINST + SET_VREG(r0, r2) @ fp[A]<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_IPUT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IPUT_VOLATILE_finish: + @bl common_squeak0 + mov r1, rINST, lsr #8 @ r1<- A+ + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + and r1, r1, #15 @ r1<- A + cmp r9, #0 @ check object for null + GET_VREG(r0, r1) @ r0<- fp[A] + beq common_errNullObject @ object was null + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_SGET_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SGET_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_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_SPUT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SPUT_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_SPUT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_IGET_OBJECT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IGET_OBJECT_VOLATILE_finish: + @bl common_squeak0 + cmp r9, #0 @ check object for null + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + beq common_errNullObject @ object was null + ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- A+ + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + and r2, r2, #15 @ r2<- A + GET_INST_OPCODE(ip) @ extract opcode from rINST + SET_VREG(r0, r2) @ fp[A]<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + /* continuation for OP_IGET_WIDE_VOLATILE */ /* @@ -8800,7 +9090,7 @@ d2l_doconv: 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 + .if 1 add r0, r9, r3 @ r0<- address of field bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field .else @@ -8831,7 +9121,7 @@ d2l_doconv: 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 + .if 1 add r2, r9, r3 @ r2<- target address bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 .else @@ -8939,6 +9229,57 @@ d2l_doconv: .LOP_EXECUTE_INLINE_RANGE_table: .word gDvmInlineOpsTable +/* continuation for OP_IPUT_OBJECT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IPUT_OBJECT_VOLATILE_finish: + @bl common_squeak0 + mov r1, rINST, lsr #8 @ r1<- A+ + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + and r1, r1, #15 @ r1<- A + cmp r9, #0 @ check object for null + GET_VREG(r0, r1) @ r0<- fp[A] + beq common_errNullObject @ object was null + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_SGET_OBJECT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SGET_OBJECT_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_OBJECT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_SPUT_OBJECT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SPUT_OBJECT_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_SPUT_OBJECT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + .size dvmAsmSisterStart, .-dvmAsmSisterStart .global dvmAsmSisterEnd dvmAsmSisterEnd: diff --git a/vm/mterp/out/InterpAsm-armv7-a.S b/vm/mterp/out/InterpAsm-armv7-a.S index db8403107..8e0cac9dd 100644 --- a/vm/mterp/out/InterpAsm-armv7-a.S +++ b/vm/mterp/out/InterpAsm-armv7-a.S @@ -20,6 +20,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + /* * ARMv5 definitions and declarations. */ @@ -205,7 +206,7 @@ unspecified registers or condition codes. #include "../common/jit-config.h" #endif -/* File: armv5te/platform.S */ +/* File: armv7-a/platform.S */ /* * =========================================================================== * CPU-version-specific defines @@ -242,6 +243,24 @@ unspecified registers or condition codes. ldmfd sp!, {\regs,pc} .endm +#if !defined(ANDROID_SMP) +# error "Must define ANDROID_SMP" +#endif + +/* + * Macro for data memory barrier; not meaningful pre-ARMv6K. + * If the argument is nonzero, emit barrier; otherwise, emit nothing. + */ +.macro SMP_DMB gen +#if ANDROID_SMP != 0 + .if \gen + dmb + .endif +#else + /* not SMP */ +#endif +.endm + /* File: armv5te/entry.S */ /* * Copyright (C) 2008 The Android Open Source Project @@ -2777,6 +2796,7 @@ dalvik_inst: beq .LOP_SGET_resolve @ yes, do resolve .LOP_SGET_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2830,6 +2850,7 @@ dalvik_inst: beq .LOP_SGET_OBJECT_resolve @ yes, do resolve .LOP_SGET_OBJECT_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2856,6 +2877,7 @@ dalvik_inst: beq .LOP_SGET_BOOLEAN_resolve @ yes, do resolve .LOP_SGET_BOOLEAN_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2882,6 +2904,7 @@ dalvik_inst: beq .LOP_SGET_BYTE_resolve @ yes, do resolve .LOP_SGET_BYTE_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2908,6 +2931,7 @@ dalvik_inst: beq .LOP_SGET_CHAR_resolve @ yes, do resolve .LOP_SGET_CHAR_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2934,6 +2958,7 @@ dalvik_inst: beq .LOP_SGET_SHORT_resolve @ yes, do resolve .LOP_SGET_SHORT_finish: @ field ptr in r0 ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- AA FETCH_ADVANCE_INST(2) @ advance rPC, load rINST SET_VREG(r1, r2) @ fp[AA]<- r1 @@ -2962,6 +2987,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3015,6 +3041,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3041,6 +3068,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3067,6 +3095,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3093,6 +3122,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -3119,6 +3149,7 @@ dalvik_inst: FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_VREG(r1, r2) @ r1<- fp[AA] GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r1, [r0, #offStaticField_value] @ field<- vAA GOTO_OPCODE(ip) @ jump to next instruction @@ -7026,42 +7057,140 @@ dalvik_inst: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E3: /* 0xe3 */ -/* File: armv5te/OP_UNUSED_E3.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IGET_VOLATILE: /* 0xe3 */ +/* File: armv5te/OP_IGET_VOLATILE.S */ +/* File: armv5te/OP_IGET.S */ + /* + * General 32-bit instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + /* op 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<- pDvmDex->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_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_VOLATILE_finish + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E4: /* 0xe4 */ -/* File: armv5te/OP_UNUSED_E4.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IPUT_VOLATILE: /* 0xe4 */ +/* File: armv5te/OP_IPUT_VOLATILE.S */ +/* File: armv5te/OP_IPUT.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op 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<- pDvmDex->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_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_VOLATILE_finish @ yes, finish up + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E5: /* 0xe5 */ -/* File: armv5te/OP_UNUSED_E5.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SGET_VOLATILE: /* 0xe5 */ +/* File: armv5te/OP_SGET_VOLATILE.S */ +/* File: armv5te/OP_SGET.S */ + /* + * General 32-bit SGET handler. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op 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_VOLATILE_resolve @ yes, do resolve +.LOP_SGET_VOLATILE_finish: @ field ptr in r0 + ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + SET_VREG(r1, r2) @ fp[AA]<- r1 + GET_INST_OPCODE(ip) @ extract opcode from rINST + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E6: /* 0xe6 */ -/* File: armv5te/OP_UNUSED_E6.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SPUT_VOLATILE: /* 0xe6 */ +/* File: armv5te/OP_SPUT_VOLATILE.S */ +/* File: armv5te/OP_SPUT.S */ + /* + * General 32-bit SPUT handler. + * + * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op 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_SPUT_VOLATILE_resolve @ yes, do resolve +.LOP_SPUT_VOLATILE_finish: @ field ptr in r0 + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_VREG(r1, r2) @ r1<- fp[AA] + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r1, [r0, #offStaticField_value] @ field<- vAA + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E7: /* 0xe7 */ -/* File: armv5te/OP_UNUSED_E7.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ +/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_IGET.S */ + /* + * General 32-bit instance field get. + * + * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short + */ + /* op 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<- pDvmDex->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_OBJECT_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_OBJECT_VOLATILE_finish + b common_exceptionThrown /* ------------------------------ */ @@ -7500,26 +7629,84 @@ dalvik_inst: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FC: /* 0xfc */ -/* File: armv5te/OP_UNUSED_FC.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ +/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_IPUT.S */ + /* + * General 32-bit instance field put. + * + * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short + */ + /* op 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<- pDvmDex->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_OBJECT_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_OBJECT_VOLATILE_finish @ yes, finish up + b common_exceptionThrown /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FD: /* 0xfd */ -/* File: armv5te/OP_UNUSED_FD.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ +/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_SGET.S */ + /* + * General 32-bit SGET handler. + * + * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short + */ + /* op 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_OBJECT_VOLATILE_resolve @ yes, do resolve +.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0 + ldr r1, [r0, #offStaticField_value] @ r1<- field value + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + SET_VREG(r1, r2) @ fp[AA]<- r1 + GET_INST_OPCODE(ip) @ extract opcode from rINST + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FE: /* 0xfe */ -/* File: armv5te/OP_UNUSED_FE.S */ -/* File: armv5te/unused.S */ - bl common_abort +.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ +/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */ +/* File: armv5te/OP_SPUT.S */ + /* + * General 32-bit SPUT handler. + * + * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short + */ + /* op 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_SPUT_OBJECT_VOLATILE_resolve @ yes, do resolve +.LOP_SPUT_OBJECT_VOLATILE_finish: @ field ptr in r0 + mov r2, rINST, lsr #8 @ r2<- AA + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_VREG(r1, r2) @ r1<- fp[AA] + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r1, [r0, #offStaticField_value] @ field<- vAA + GOTO_OPCODE(ip) @ jump to next instruction /* ------------------------------ */ @@ -8073,6 +8260,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8093,6 +8281,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8113,6 +8302,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8133,6 +8323,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8153,6 +8344,7 @@ dvmAsmSisterStart: ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field beq common_errNullObject @ object was null ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 0 @ acquiring load mov r2, rINST, lsr #8 @ r2<- A+ FETCH_ADVANCE_INST(2) @ advance rPC, load rINST and r2, r2, #15 @ r2<- A @@ -8215,6 +8407,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8235,6 +8428,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8255,6 +8449,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8275,6 +8470,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8295,6 +8491,7 @@ dvmAsmSisterStart: beq common_errNullObject @ object was null FETCH_ADVANCE_INST(2) @ advance rPC, load rINST GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 0 @ releasing store str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 GOTO_OPCODE(ip) @ jump to next instruction @@ -8789,6 +8986,99 @@ d2l_doconv: stmia r9, {r0-r1} @ vAA/vAA+1<- r0/r1 GOTO_OPCODE(ip) @ jump to next instruction +/* continuation for OP_IGET_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IGET_VOLATILE_finish: + @bl common_squeak0 + cmp r9, #0 @ check object for null + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + beq common_errNullObject @ object was null + ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- A+ + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + and r2, r2, #15 @ r2<- A + GET_INST_OPCODE(ip) @ extract opcode from rINST + SET_VREG(r0, r2) @ fp[A]<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_IPUT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IPUT_VOLATILE_finish: + @bl common_squeak0 + mov r1, rINST, lsr #8 @ r1<- A+ + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + and r1, r1, #15 @ r1<- A + cmp r9, #0 @ check object for null + GET_VREG(r0, r1) @ r0<- fp[A] + beq common_errNullObject @ object was null + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_SGET_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SGET_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_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_SPUT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SPUT_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_SPUT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_IGET_OBJECT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IGET_OBJECT_VOLATILE_finish: + @bl common_squeak0 + cmp r9, #0 @ check object for null + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + beq common_errNullObject @ object was null + ldr r0, [r9, r3] @ r0<- obj.field (8/16/32 bits) + SMP_DMB 1 @ acquiring load + mov r2, rINST, lsr #8 @ r2<- A+ + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + and r2, r2, #15 @ r2<- A + GET_INST_OPCODE(ip) @ extract opcode from rINST + SET_VREG(r0, r2) @ fp[A]<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + /* continuation for OP_IGET_WIDE_VOLATILE */ /* @@ -8800,7 +9090,7 @@ d2l_doconv: 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 + .if 1 add r0, r9, r3 @ r0<- address of field bl dvmQuasiAtomicRead64 @ r0/r1<- contents of field .else @@ -8831,7 +9121,7 @@ d2l_doconv: 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 + .if 1 add r2, r9, r3 @ r2<- target address bl dvmQuasiAtomicSwap64 @ stores r0/r1 into addr r2 .else @@ -8939,6 +9229,57 @@ d2l_doconv: .LOP_EXECUTE_INLINE_RANGE_table: .word gDvmInlineOpsTable +/* continuation for OP_IPUT_OBJECT_VOLATILE */ + + /* + * Currently: + * r0 holds resolved field + * r9 holds object + */ +.LOP_IPUT_OBJECT_VOLATILE_finish: + @bl common_squeak0 + mov r1, rINST, lsr #8 @ r1<- A+ + ldr r3, [r0, #offInstField_byteOffset] @ r3<- byte offset of field + and r1, r1, #15 @ r1<- A + cmp r9, #0 @ check object for null + GET_VREG(r0, r1) @ r0<- fp[A] + beq common_errNullObject @ object was null + FETCH_ADVANCE_INST(2) @ advance rPC, load rINST + GET_INST_OPCODE(ip) @ extract opcode from rINST + SMP_DMB 1 @ releasing store + str r0, [r9, r3] @ obj.field (8/16/32 bits)<- r0 + GOTO_OPCODE(ip) @ jump to next instruction + +/* continuation for OP_SGET_OBJECT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SGET_OBJECT_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_OBJECT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + +/* continuation for OP_SPUT_OBJECT_VOLATILE */ + + /* + * Continuation if the field has not yet been resolved. + * r1: BBBB field ref + */ +.LOP_SPUT_OBJECT_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_SPUT_OBJECT_VOLATILE_finish @ yes, finish + b common_exceptionThrown @ no, handle exception + .size dvmAsmSisterStart, .-dvmAsmSisterStart .global dvmAsmSisterEnd dvmAsmSisterEnd: diff --git a/vm/mterp/out/InterpAsm-x86-atom.S b/vm/mterp/out/InterpAsm-x86-atom.S index 8f8cb0fa5..d259f6e6e 100644 --- a/vm/mterp/out/InterpAsm-x86-atom.S +++ b/vm/mterp/out/InterpAsm-x86-atom.S @@ -14281,8 +14281,7 @@ OP_IF_LEZ_2f: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E3: /* 0xe3 */ -/* File: x86-atom/OP_UNUSED_E3.S */ +.L_OP_IGET_VOLATILE: /* 0xe3 */ /* Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14299,46 +14298,18 @@ OP_IF_LEZ_2f: */ /* - * File: OP_UNUSED_E3.S - */ - -/* File: x86-atom/unused.S */ - /* Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* - * File: unused.S - * - * Code: Common code for unused bytecodes. Uses no subtitutions. - * - * For: all unused bytecodes - * - * Description: aborts if executed. - * - * Format: ØØ|op (10x) - * - * Syntax: op + * File: stub.S */ - call common_abort - - + SAVE_PC_FP_TO_GLUE %edx # save program counter and frame pointer + pushl rGLUE # push parameter glue + call dvmMterp_OP_IGET_VOLATILE # call c-based implementation + lea 4(%esp), %esp + LOAD_PC_FP_FROM_GLUE # restore program counter and frame pointer + FINISH_A # jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E4: /* 0xe4 */ -/* File: x86-atom/OP_UNUSED_E4.S */ +.L_OP_IPUT_VOLATILE: /* 0xe4 */ /* Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14355,46 +14326,18 @@ OP_IF_LEZ_2f: */ /* - * File: OP_UNUSED_E4.S - */ - -/* File: x86-atom/unused.S */ - /* Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* - * File: unused.S - * - * Code: Common code for unused bytecodes. Uses no subtitutions. - * - * For: all unused bytecodes - * - * Description: aborts if executed. - * - * Format: ØØ|op (10x) - * - * Syntax: op + * File: stub.S */ - call common_abort - - + SAVE_PC_FP_TO_GLUE %edx # save program counter and frame pointer + pushl rGLUE # push parameter glue + call dvmMterp_OP_IPUT_VOLATILE # call c-based implementation + lea 4(%esp), %esp + LOAD_PC_FP_FROM_GLUE # restore program counter and frame pointer + FINISH_A # jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E5: /* 0xe5 */ -/* File: x86-atom/OP_UNUSED_E5.S */ +.L_OP_SGET_VOLATILE: /* 0xe5 */ /* Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14411,46 +14354,18 @@ OP_IF_LEZ_2f: */ /* - * File: OP_UNUSED_E5.S - */ - -/* File: x86-atom/unused.S */ - /* Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* - * File: unused.S - * - * Code: Common code for unused bytecodes. Uses no subtitutions. - * - * For: all unused bytecodes - * - * Description: aborts if executed. - * - * Format: ØØ|op (10x) - * - * Syntax: op + * File: stub.S */ - call common_abort - - + SAVE_PC_FP_TO_GLUE %edx # save program counter and frame pointer + pushl rGLUE # push parameter glue + call dvmMterp_OP_SGET_VOLATILE # call c-based implementation + lea 4(%esp), %esp + LOAD_PC_FP_FROM_GLUE # restore program counter and frame pointer + FINISH_A # jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E6: /* 0xe6 */ -/* File: x86-atom/OP_UNUSED_E6.S */ +.L_OP_SPUT_VOLATILE: /* 0xe6 */ /* Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14467,46 +14382,18 @@ OP_IF_LEZ_2f: */ /* - * File: OP_UNUSED_E6.S - */ - -/* File: x86-atom/unused.S */ - /* Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* - * File: unused.S - * - * Code: Common code for unused bytecodes. Uses no subtitutions. - * - * For: all unused bytecodes - * - * Description: aborts if executed. - * - * Format: ØØ|op (10x) - * - * Syntax: op + * File: stub.S */ - call common_abort - - + SAVE_PC_FP_TO_GLUE %edx # save program counter and frame pointer + pushl rGLUE # push parameter glue + call dvmMterp_OP_SPUT_VOLATILE # call c-based implementation + lea 4(%esp), %esp + LOAD_PC_FP_FROM_GLUE # restore program counter and frame pointer + FINISH_A # jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E7: /* 0xe7 */ -/* File: x86-atom/OP_UNUSED_E7.S */ +.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ /* Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14523,42 +14410,15 @@ OP_IF_LEZ_2f: */ /* - * File: OP_UNUSED_E7.S - */ - -/* File: x86-atom/unused.S */ - /* Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* - * File: unused.S - * - * Code: Common code for unused bytecodes. Uses no subtitutions. - * - * For: all unused bytecodes - * - * Description: aborts if executed. - * - * Format: ØØ|op (10x) - * - * Syntax: op + * File: stub.S */ - call common_abort - - + SAVE_PC_FP_TO_GLUE %edx # save program counter and frame pointer + pushl rGLUE # push parameter glue + call dvmMterp_OP_IGET_OBJECT_VOLATILE # call c-based implementation + lea 4(%esp), %esp + LOAD_PC_FP_FROM_GLUE # restore program counter and frame pointer + FINISH_A # jump to next instruction /* ------------------------------ */ .balign 64 .L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ @@ -15415,8 +15275,7 @@ OP_IF_LEZ_2f: /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FC: /* 0xfc */ -/* File: x86-atom/OP_UNUSED_FC.S */ +.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ /* Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15433,46 +15292,18 @@ OP_IF_LEZ_2f: */ /* - * File: OP_UNUSED_FC.S - */ - -/* File: x86-atom/unused.S */ - /* Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* - * File: unused.S - * - * Code: Common code for unused bytecodes. Uses no subtitutions. - * - * For: all unused bytecodes - * - * Description: aborts if executed. - * - * Format: ØØ|op (10x) - * - * Syntax: op + * File: stub.S */ - call common_abort - - + SAVE_PC_FP_TO_GLUE %edx # save program counter and frame pointer + pushl rGLUE # push parameter glue + call dvmMterp_OP_IPUT_OBJECT_VOLATILE # call c-based implementation + lea 4(%esp), %esp + LOAD_PC_FP_FROM_GLUE # restore program counter and frame pointer + FINISH_A # jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FD: /* 0xfd */ -/* File: x86-atom/OP_UNUSED_FD.S */ +.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ /* Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15489,46 +15320,18 @@ OP_IF_LEZ_2f: */ /* - * File: OP_UNUSED_FD.S - */ - -/* File: x86-atom/unused.S */ - /* Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* - * File: unused.S - * - * Code: Common code for unused bytecodes. Uses no subtitutions. - * - * For: all unused bytecodes - * - * Description: aborts if executed. - * - * Format: ØØ|op (10x) - * - * Syntax: op + * File: stub.S */ - call common_abort - - + SAVE_PC_FP_TO_GLUE %edx # save program counter and frame pointer + pushl rGLUE # push parameter glue + call dvmMterp_OP_SGET_OBJECT_VOLATILE # call c-based implementation + lea 4(%esp), %esp + LOAD_PC_FP_FROM_GLUE # restore program counter and frame pointer + FINISH_A # jump to next instruction /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FE: /* 0xfe */ -/* File: x86-atom/OP_UNUSED_FE.S */ +.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ /* Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15545,42 +15348,15 @@ OP_IF_LEZ_2f: */ /* - * File: OP_UNUSED_FE.S - */ - -/* File: x86-atom/unused.S */ - /* Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - /* - * File: unused.S - * - * Code: Common code for unused bytecodes. Uses no subtitutions. - * - * For: all unused bytecodes - * - * Description: aborts if executed. - * - * Format: ØØ|op (10x) - * - * Syntax: op + * File: stub.S */ - call common_abort - - + SAVE_PC_FP_TO_GLUE %edx # save program counter and frame pointer + pushl rGLUE # push parameter glue + call dvmMterp_OP_SPUT_OBJECT_VOLATILE # call c-based implementation + lea 4(%esp), %esp + LOAD_PC_FP_FROM_GLUE # restore program counter and frame pointer + FINISH_A # jump to next instruction /* ------------------------------ */ .balign 64 .L_OP_UNUSED_FF: /* 0xff */ diff --git a/vm/mterp/out/InterpAsm-x86.S b/vm/mterp/out/InterpAsm-x86.S index 8168c598a..914b1d170 100644 --- a/vm/mterp/out/InterpAsm-x86.S +++ b/vm/mterp/out/InterpAsm-x86.S @@ -5683,44 +5683,74 @@ dvmAsmInstructionStart = .L_OP_NOP /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E3: /* 0xe3 */ -/* File: x86/OP_UNUSED_E3.S */ -/* File: x86/unused.S */ - jmp common_abort - - +.L_OP_IGET_VOLATILE: /* 0xe3 */ + /* (stub) */ + GET_GLUE(%ecx) + SAVE_PC_TO_GLUE(%ecx) # only need to export these two + SAVE_FP_TO_GLUE(%ecx) # only need to export these two + movl %ecx,OUT_ARG0(%esp) # glue is first arg to function + call dvmMterp_OP_IGET_VOLATILE # do the real work + GET_GLUE(%ecx) + LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values + LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values + FETCH_INST() + GOTO_NEXT /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E4: /* 0xe4 */ -/* File: x86/OP_UNUSED_E4.S */ -/* File: x86/unused.S */ - jmp common_abort - - +.L_OP_IPUT_VOLATILE: /* 0xe4 */ + /* (stub) */ + GET_GLUE(%ecx) + SAVE_PC_TO_GLUE(%ecx) # only need to export these two + SAVE_FP_TO_GLUE(%ecx) # only need to export these two + movl %ecx,OUT_ARG0(%esp) # glue is first arg to function + call dvmMterp_OP_IPUT_VOLATILE # do the real work + GET_GLUE(%ecx) + LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values + LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values + FETCH_INST() + GOTO_NEXT /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E5: /* 0xe5 */ -/* File: x86/OP_UNUSED_E5.S */ -/* File: x86/unused.S */ - jmp common_abort - - +.L_OP_SGET_VOLATILE: /* 0xe5 */ + /* (stub) */ + GET_GLUE(%ecx) + SAVE_PC_TO_GLUE(%ecx) # only need to export these two + SAVE_FP_TO_GLUE(%ecx) # only need to export these two + movl %ecx,OUT_ARG0(%esp) # glue is first arg to function + call dvmMterp_OP_SGET_VOLATILE # do the real work + GET_GLUE(%ecx) + LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values + LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values + FETCH_INST() + GOTO_NEXT /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E6: /* 0xe6 */ -/* File: x86/OP_UNUSED_E6.S */ -/* File: x86/unused.S */ - jmp common_abort - - +.L_OP_SPUT_VOLATILE: /* 0xe6 */ + /* (stub) */ + GET_GLUE(%ecx) + SAVE_PC_TO_GLUE(%ecx) # only need to export these two + SAVE_FP_TO_GLUE(%ecx) # only need to export these two + movl %ecx,OUT_ARG0(%esp) # glue is first arg to function + call dvmMterp_OP_SPUT_VOLATILE # do the real work + GET_GLUE(%ecx) + LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values + LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values + FETCH_INST() + GOTO_NEXT /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_E7: /* 0xe7 */ -/* File: x86/OP_UNUSED_E7.S */ -/* File: x86/unused.S */ - jmp common_abort - - +.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */ + /* (stub) */ + GET_GLUE(%ecx) + SAVE_PC_TO_GLUE(%ecx) # only need to export these two + SAVE_FP_TO_GLUE(%ecx) # only need to export these two + movl %ecx,OUT_ARG0(%esp) # glue is first arg to function + call dvmMterp_OP_IGET_OBJECT_VOLATILE # do the real work + GET_GLUE(%ecx) + LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values + LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values + FETCH_INST() + GOTO_NEXT /* ------------------------------ */ .balign 64 .L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */ @@ -6111,28 +6141,46 @@ dvmAsmInstructionStart = .L_OP_NOP /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FC: /* 0xfc */ -/* File: x86/OP_UNUSED_FC.S */ -/* File: x86/unused.S */ - jmp common_abort - - +.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */ + /* (stub) */ + GET_GLUE(%ecx) + SAVE_PC_TO_GLUE(%ecx) # only need to export these two + SAVE_FP_TO_GLUE(%ecx) # only need to export these two + movl %ecx,OUT_ARG0(%esp) # glue is first arg to function + call dvmMterp_OP_IPUT_OBJECT_VOLATILE # do the real work + GET_GLUE(%ecx) + LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values + LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values + FETCH_INST() + GOTO_NEXT /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FD: /* 0xfd */ -/* File: x86/OP_UNUSED_FD.S */ -/* File: x86/unused.S */ - jmp common_abort - - +.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */ + /* (stub) */ + GET_GLUE(%ecx) + SAVE_PC_TO_GLUE(%ecx) # only need to export these two + SAVE_FP_TO_GLUE(%ecx) # only need to export these two + movl %ecx,OUT_ARG0(%esp) # glue is first arg to function + call dvmMterp_OP_SGET_OBJECT_VOLATILE # do the real work + GET_GLUE(%ecx) + LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values + LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values + FETCH_INST() + GOTO_NEXT /* ------------------------------ */ .balign 64 -.L_OP_UNUSED_FE: /* 0xfe */ -/* File: x86/OP_UNUSED_FE.S */ -/* File: x86/unused.S */ - jmp common_abort - - +.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */ + /* (stub) */ + GET_GLUE(%ecx) + SAVE_PC_TO_GLUE(%ecx) # only need to export these two + SAVE_FP_TO_GLUE(%ecx) # only need to export these two + movl %ecx,OUT_ARG0(%esp) # glue is first arg to function + call dvmMterp_OP_SPUT_OBJECT_VOLATILE # do the real work + GET_GLUE(%ecx) + LOAD_PC_FROM_GLUE(%ecx) # retrieve updated values + LOAD_FP_FROM_GLUE(%ecx) # retrieve updated values + FETCH_INST() + GOTO_NEXT /* ------------------------------ */ .balign 64 .L_OP_UNUSED_FF: /* 0xff */ diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c index 2a366f690..6a50b6477 100644 --- a/vm/mterp/out/InterpC-allstubs.c +++ b/vm/mterp/out/InterpC-allstubs.c @@ -2779,24 +2779,24 @@ OP_END HANDLE_OP_SHX_INT_LIT8(OP_USHR_INT_LIT8, "ushr", (u4), >>) OP_END -/* File: c/OP_UNUSED_E3.c */ -HANDLE_OPCODE(OP_UNUSED_E3) +/* File: c/OP_IGET_VOLATILE.c */ +HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, ) OP_END -/* File: c/OP_UNUSED_E4.c */ -HANDLE_OPCODE(OP_UNUSED_E4) +/* File: c/OP_IPUT_VOLATILE.c */ +HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, ) OP_END -/* File: c/OP_UNUSED_E5.c */ -HANDLE_OPCODE(OP_UNUSED_E5) +/* File: c/OP_SGET_VOLATILE.c */ +HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, ) OP_END -/* File: c/OP_UNUSED_E6.c */ -HANDLE_OPCODE(OP_UNUSED_E6) +/* File: c/OP_SPUT_VOLATILE.c */ +HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, ) OP_END -/* File: c/OP_UNUSED_E7.c */ -HANDLE_OPCODE(OP_UNUSED_E7) +/* File: c/OP_IGET_OBJECT_VOLATILE.c */ +HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) OP_END /* File: c/OP_IGET_WIDE_VOLATILE.c */ @@ -3026,16 +3026,16 @@ HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) GOTO_invoke(invokeSuperQuick, true); OP_END -/* File: c/OP_UNUSED_FC.c */ -HANDLE_OPCODE(OP_UNUSED_FC) +/* File: c/OP_IPUT_OBJECT_VOLATILE.c */ +HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) OP_END -/* File: c/OP_UNUSED_FD.c */ -HANDLE_OPCODE(OP_UNUSED_FD) +/* File: c/OP_SGET_OBJECT_VOLATILE.c */ +HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) OP_END -/* File: c/OP_UNUSED_FE.c */ -HANDLE_OPCODE(OP_UNUSED_FE) +/* File: c/OP_SPUT_OBJECT_VOLATILE.c */ +HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) OP_END /* File: c/OP_UNUSED_FF.c */ diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c index 2b7f33356..18433f8eb 100644 --- a/vm/mterp/out/InterpC-portdbg.c +++ b/vm/mterp/out/InterpC-portdbg.c @@ -3145,24 +3145,24 @@ OP_END HANDLE_OP_SHX_INT_LIT8(OP_USHR_INT_LIT8, "ushr", (u4), >>) OP_END -/* File: c/OP_UNUSED_E3.c */ -HANDLE_OPCODE(OP_UNUSED_E3) +/* File: c/OP_IGET_VOLATILE.c */ +HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, ) OP_END -/* File: c/OP_UNUSED_E4.c */ -HANDLE_OPCODE(OP_UNUSED_E4) +/* File: c/OP_IPUT_VOLATILE.c */ +HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, ) OP_END -/* File: c/OP_UNUSED_E5.c */ -HANDLE_OPCODE(OP_UNUSED_E5) +/* File: c/OP_SGET_VOLATILE.c */ +HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, ) OP_END -/* File: c/OP_UNUSED_E6.c */ -HANDLE_OPCODE(OP_UNUSED_E6) +/* File: c/OP_SPUT_VOLATILE.c */ +HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, ) OP_END -/* File: c/OP_UNUSED_E7.c */ -HANDLE_OPCODE(OP_UNUSED_E7) +/* File: c/OP_IGET_OBJECT_VOLATILE.c */ +HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) OP_END /* File: c/OP_IGET_WIDE_VOLATILE.c */ @@ -3392,16 +3392,16 @@ HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) GOTO_invoke(invokeSuperQuick, true); OP_END -/* File: c/OP_UNUSED_FC.c */ -HANDLE_OPCODE(OP_UNUSED_FC) +/* File: c/OP_IPUT_OBJECT_VOLATILE.c */ +HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) OP_END -/* File: c/OP_UNUSED_FD.c */ -HANDLE_OPCODE(OP_UNUSED_FD) +/* File: c/OP_SGET_OBJECT_VOLATILE.c */ +HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) OP_END -/* File: c/OP_UNUSED_FE.c */ -HANDLE_OPCODE(OP_UNUSED_FE) +/* File: c/OP_SPUT_OBJECT_VOLATILE.c */ +HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) OP_END /* File: c/OP_UNUSED_FF.c */ diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c index d75dead6a..a4c4b54ae 100644 --- a/vm/mterp/out/InterpC-portstd.c +++ b/vm/mterp/out/InterpC-portstd.c @@ -2884,24 +2884,24 @@ OP_END HANDLE_OP_SHX_INT_LIT8(OP_USHR_INT_LIT8, "ushr", (u4), >>) OP_END -/* File: c/OP_UNUSED_E3.c */ -HANDLE_OPCODE(OP_UNUSED_E3) +/* File: c/OP_IGET_VOLATILE.c */ +HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, ) OP_END -/* File: c/OP_UNUSED_E4.c */ -HANDLE_OPCODE(OP_UNUSED_E4) +/* File: c/OP_IPUT_VOLATILE.c */ +HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, ) OP_END -/* File: c/OP_UNUSED_E5.c */ -HANDLE_OPCODE(OP_UNUSED_E5) +/* File: c/OP_SGET_VOLATILE.c */ +HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, ) OP_END -/* File: c/OP_UNUSED_E6.c */ -HANDLE_OPCODE(OP_UNUSED_E6) +/* File: c/OP_SPUT_VOLATILE.c */ +HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, ) OP_END -/* File: c/OP_UNUSED_E7.c */ -HANDLE_OPCODE(OP_UNUSED_E7) +/* File: c/OP_IGET_OBJECT_VOLATILE.c */ +HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) OP_END /* File: c/OP_IGET_WIDE_VOLATILE.c */ @@ -3131,16 +3131,16 @@ HANDLE_OPCODE(OP_INVOKE_SUPER_QUICK_RANGE /*{vCCCC..v(CCCC+AA-1)}, meth@BBBB*/) GOTO_invoke(invokeSuperQuick, true); OP_END -/* File: c/OP_UNUSED_FC.c */ -HANDLE_OPCODE(OP_UNUSED_FC) +/* File: c/OP_IPUT_OBJECT_VOLATILE.c */ +HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) OP_END -/* File: c/OP_UNUSED_FD.c */ -HANDLE_OPCODE(OP_UNUSED_FD) +/* File: c/OP_SGET_OBJECT_VOLATILE.c */ +HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) OP_END -/* File: c/OP_UNUSED_FE.c */ -HANDLE_OPCODE(OP_UNUSED_FE) +/* File: c/OP_SPUT_OBJECT_VOLATILE.c */ +HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) OP_END /* File: c/OP_UNUSED_FF.c */ diff --git a/vm/mterp/out/InterpC-x86-atom.c b/vm/mterp/out/InterpC-x86-atom.c index 0061a61ec..9d208a350 100644 --- a/vm/mterp/out/InterpC-x86-atom.c +++ b/vm/mterp/out/InterpC-x86-atom.c @@ -1201,6 +1201,26 @@ GOTO_TARGET_DECL(exceptionThrown); } \ FINISH(2); +/* File: c/OP_IGET_VOLATILE.c */ +HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, ) +OP_END + +/* File: c/OP_IPUT_VOLATILE.c */ +HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, ) +OP_END + +/* File: c/OP_SGET_VOLATILE.c */ +HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, ) +OP_END + +/* File: c/OP_SPUT_VOLATILE.c */ +HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, ) +OP_END + +/* File: c/OP_IGET_OBJECT_VOLATILE.c */ +HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) +OP_END + /* File: c/OP_IGET_WIDE_VOLATILE.c */ HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE) OP_END @@ -1293,6 +1313,18 @@ HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/) FINISH(3); OP_END +/* File: c/OP_IPUT_OBJECT_VOLATILE.c */ +HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) +OP_END + +/* File: c/OP_SGET_OBJECT_VOLATILE.c */ +HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) +OP_END + +/* File: c/OP_SPUT_OBJECT_VOLATILE.c */ +HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) +OP_END + /* File: c/gotoTargets.c */ /* * C footer. This has some common code shared by the various targets. diff --git a/vm/mterp/out/InterpC-x86.c b/vm/mterp/out/InterpC-x86.c index c95ef905e..d9e599e6a 100644 --- a/vm/mterp/out/InterpC-x86.c +++ b/vm/mterp/out/InterpC-x86.c @@ -1201,6 +1201,26 @@ GOTO_TARGET_DECL(exceptionThrown); } \ FINISH(2); +/* File: c/OP_IGET_VOLATILE.c */ +HANDLE_IGET_X(OP_IGET_VOLATILE, "-volatile", IntVolatile, ) +OP_END + +/* File: c/OP_IPUT_VOLATILE.c */ +HANDLE_IPUT_X(OP_IPUT_VOLATILE, "-volatile", IntVolatile, ) +OP_END + +/* File: c/OP_SGET_VOLATILE.c */ +HANDLE_SGET_X(OP_SGET_VOLATILE, "-volatile", IntVolatile, ) +OP_END + +/* File: c/OP_SPUT_VOLATILE.c */ +HANDLE_SPUT_X(OP_SPUT_VOLATILE, "-volatile", IntVolatile, ) +OP_END + +/* File: c/OP_IGET_OBJECT_VOLATILE.c */ +HANDLE_IGET_X(OP_IGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) +OP_END + /* File: c/OP_IGET_WIDE_VOLATILE.c */ HANDLE_IGET_X(OP_IGET_WIDE_VOLATILE, "-wide-volatile", LongVolatile, _WIDE) OP_END @@ -1262,6 +1282,18 @@ HANDLE_OPCODE(OP_EXECUTE_INLINE_RANGE /*{vCCCC..v(CCCC+AA-1)}, inline@BBBB*/) FINISH(3); OP_END +/* File: c/OP_IPUT_OBJECT_VOLATILE.c */ +HANDLE_IPUT_X(OP_IPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) +OP_END + +/* File: c/OP_SGET_OBJECT_VOLATILE.c */ +HANDLE_SGET_X(OP_SGET_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) +OP_END + +/* File: c/OP_SPUT_OBJECT_VOLATILE.c */ +HANDLE_SPUT_X(OP_SPUT_OBJECT_VOLATILE, "-object-volatile", ObjectVolatile, _AS_OBJECT) +OP_END + /* File: c/gotoTargets.c */ /* * C footer. This has some common code shared by the various targets. diff --git a/vm/mterp/x86-atom/TODO.txt b/vm/mterp/x86-atom/TODO.txt index c49532ebb..5b89db95d 100644 --- a/vm/mterp/x86-atom/TODO.txt +++ b/vm/mterp/x86-atom/TODO.txt @@ -7,8 +7,8 @@ Items requiring attention: skip a memory load when debugger support is completely disabled) (md) Correct OP_MONITOR_EXIT (need to adjust PC before throw) +(md) OP_THROW needs to export the PC (lo) Implement OP_BREAKPOINT (lo) Implement OP_EXECUTE_INLINE_RANGE -(lo) Implement OP_*_WIDE_VOLATILE -(lo) OP_THROW needs to export the PC +(lo) Implement OP_*_VOLATILE (12 instructions) diff --git a/vm/oo/Object.h b/vm/oo/Object.h index 92ec1d64f..041e1e8ef 100644 --- a/vm/oo/Object.h +++ b/vm/oo/Object.h @@ -714,9 +714,19 @@ INLINE double dvmGetFieldDouble(const Object* obj, int offset) { INLINE Object* dvmGetFieldObject(const Object* obj, int offset) { return ((JValue*)BYTE_OFFSET(obj, offset))->l; } +INLINE s4 dvmGetFieldIntVolatile(const Object* obj, int offset) { + s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i; + return android_atomic_acquire_load(ptr); +} +INLINE Object* dvmGetFieldObjectVolatile(const Object* obj, int offset) { + void** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l; + return (Object*) android_atomic_acquire_load((int32_t*)ptr); +} INLINE s8 dvmGetFieldLongVolatile(const Object* obj, int offset) { const s8* addr = BYTE_OFFSET(obj, offset); - return dvmQuasiAtomicRead64((s8*)addr); + s8 val = dvmQuasiAtomicRead64(addr); + ANDROID_MEMBAR_FULL(); + return val; } INLINE void dvmSetFieldBoolean(Object* obj, int offset, bool val) { @@ -746,8 +756,17 @@ INLINE void dvmSetFieldDouble(Object* obj, int offset, double val) { INLINE void dvmSetFieldObject(Object* obj, int offset, Object* val) { ((JValue*)BYTE_OFFSET(obj, offset))->l = val; } +INLINE void dvmSetFieldIntVolatile(Object* obj, int offset, s4 val) { + s4* ptr = &((JValue*)BYTE_OFFSET(obj, offset))->i; + android_atomic_release_store(val, ptr); +} +INLINE void dvmSetFieldObjectVolatile(Object* obj, int offset, Object* val) { + void** ptr = &((JValue*)BYTE_OFFSET(obj, offset))->l; + android_atomic_release_store((int32_t)val, (int32_t*)ptr); +} INLINE void dvmSetFieldLongVolatile(Object* obj, int offset, s8 val) { s8* addr = BYTE_OFFSET(obj, offset); + ANDROID_MEMBAR_FULL(); dvmQuasiAtomicSwap64(val, addr); } @@ -785,9 +804,19 @@ INLINE double dvmGetStaticFieldDouble(const StaticField* sfield) { INLINE Object* dvmGetStaticFieldObject(const StaticField* sfield) { return sfield->value.l; } +INLINE s4 dvmGetStaticFieldIntVolatile(const StaticField* sfield) { + const s4* ptr = &(sfield->value.i); + return android_atomic_acquire_load((s4*)ptr); +} +INLINE Object* dvmGetStaticFieldObjectVolatile(const StaticField* sfield) { + void* const* ptr = &(sfield->value.l); + return (Object*) android_atomic_acquire_load((int32_t*)ptr); +} INLINE s8 dvmGetStaticFieldLongVolatile(const StaticField* sfield) { const s8* addr = &sfield->value.j; - return dvmQuasiAtomicRead64((s8*)addr); + s8 val = dvmQuasiAtomicRead64(addr); + ANDROID_MEMBAR_FULL(); + return val; } INLINE void dvmSetStaticFieldBoolean(StaticField* sfield, bool val) { @@ -817,8 +846,17 @@ INLINE void dvmSetStaticFieldDouble(StaticField* sfield, double val) { INLINE void dvmSetStaticFieldObject(StaticField* sfield, Object* val) { sfield->value.l = val; } +INLINE void dvmSetStaticFieldIntVolatile(StaticField* sfield, s4 val) { + s4* ptr = &(sfield->value.i); + android_atomic_release_store(val, ptr); +} +INLINE void dvmSetStaticFieldObjectVolatile(StaticField* sfield, Object* val) { + void** ptr = &(sfield->value.l); + android_atomic_release_store((int32_t)val, (int32_t*)ptr); +} INLINE void dvmSetStaticFieldLongVolatile(StaticField* sfield, s8 val) { s8* addr = &sfield->value.j; + ANDROID_MEMBAR_FULL(); dvmQuasiAtomicSwap64(val, addr); } |