ART: Fix mips64 jni bugs.
For mips64, 32-bits loads can be zero extended or sign extended to
64-bits. The extension type must match the data type to be loaded.
Also re-enable mips64 generic jni testing.
Change-Id: I9cabaf80b4fde63d9868fccd74593b36d1c324e8
diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc
index 282ab96..5e9653d 100644
--- a/compiler/utils/mips64/assembler_mips64.cc
+++ b/compiler/utils/mips64/assembler_mips64.cc
@@ -272,6 +272,10 @@
EmitI(0x25, rs, rt, imm16);
}
+void Mips64Assembler::Lwu(GpuRegister rt, GpuRegister rs, uint16_t imm16) {
+ EmitI(0x27, rs, rt, imm16);
+}
+
void Mips64Assembler::Lui(GpuRegister rt, uint16_t imm16) {
EmitI(0xf, static_cast<GpuRegister>(0), rt, imm16);
}
@@ -480,6 +484,9 @@
case kLoadWord:
Lw(reg, base, offset);
break;
+ case kLoadUnsignedWord:
+ Lwu(reg, base, offset);
+ break;
case kLoadDoubleword:
// TODO: alignment issues ???
Ld(reg, base, offset);
@@ -512,7 +519,6 @@
CHECK_EQ(0u, size) << dst;
} else if (dst.IsGpuRegister()) {
if (size == 4) {
- CHECK_EQ(4u, size) << dst;
LoadFromOffset(kLoadWord, dst.AsGpuRegister(), src_register, src_offset);
} else if (size == 8) {
CHECK_EQ(8u, size) << dst;
@@ -740,14 +746,13 @@
void Mips64Assembler::LoadRef(ManagedRegister mdest, FrameOffset src) {
Mips64ManagedRegister dest = mdest.AsMips64();
CHECK(dest.IsGpuRegister());
- LoadFromOffset(kLoadWord, dest.AsGpuRegister(), SP, src.Int32Value());
+ LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(), SP, src.Int32Value());
}
-void Mips64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base,
- MemberOffset offs) {
+void Mips64Assembler::LoadRef(ManagedRegister mdest, ManagedRegister base, MemberOffset offs) {
Mips64ManagedRegister dest = mdest.AsMips64();
- CHECK(dest.IsGpuRegister() && dest.IsGpuRegister());
- LoadFromOffset(kLoadWord, dest.AsGpuRegister(),
+ CHECK(dest.IsGpuRegister() && base.AsMips64().IsGpuRegister());
+ LoadFromOffset(kLoadUnsignedWord, dest.AsGpuRegister(),
base.AsMips64().AsGpuRegister(), offs.Int32Value());
if (kPoisonHeapReferences) {
Subu(dest.AsGpuRegister(), ZERO, dest.AsGpuRegister());
@@ -921,7 +926,7 @@
// the address in the handle scope holding the reference.
// e.g. out_reg = (handle == 0) ? 0 : (SP+handle_offset)
if (in_reg.IsNoRegister()) {
- LoadFromOffset(kLoadWord, out_reg.AsGpuRegister(),
+ LoadFromOffset(kLoadUnsignedWord, out_reg.AsGpuRegister(),
SP, handle_scope_offset.Int32Value());
in_reg = out_reg;
}
@@ -944,7 +949,7 @@
CHECK(scratch.IsGpuRegister()) << scratch;
if (null_allowed) {
Label null_arg;
- LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP,
+ LoadFromOffset(kLoadUnsignedWord, scratch.AsGpuRegister(), SP,
handle_scope_offset.Int32Value());
// Null values get a handle scope entry value of 0. Otherwise, the handle scope entry is
// the address in the handle scope holding the reference.
@@ -998,7 +1003,7 @@
Mips64ManagedRegister scratch = mscratch.AsMips64();
CHECK(scratch.IsGpuRegister()) << scratch;
// Call *(*(SP + base) + offset)
- LoadFromOffset(kLoadWord, scratch.AsGpuRegister(),
+ LoadFromOffset(kLoadUnsignedWord, scratch.AsGpuRegister(),
SP, base.Int32Value());
LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(),
scratch.AsGpuRegister(), offset.Int32Value());
diff --git a/compiler/utils/mips64/assembler_mips64.h b/compiler/utils/mips64/assembler_mips64.h
index b7f6a9e..2d7c661 100644
--- a/compiler/utils/mips64/assembler_mips64.h
+++ b/compiler/utils/mips64/assembler_mips64.h
@@ -36,6 +36,7 @@
kLoadSignedHalfword,
kLoadUnsignedHalfword,
kLoadWord,
+ kLoadUnsignedWord,
kLoadDoubleword
};
@@ -85,6 +86,7 @@
void Ld(GpuRegister rt, GpuRegister rs, uint16_t imm16);
void Lbu(GpuRegister rt, GpuRegister rs, uint16_t imm16);
void Lhu(GpuRegister rt, GpuRegister rs, uint16_t imm16);
+ void Lwu(GpuRegister rt, GpuRegister rs, uint16_t imm16);
void Lui(GpuRegister rt, uint16_t imm16);
void Mfhi(GpuRegister rd);
void Mflo(GpuRegister rd);