Merge "ARM64: Improve String.getCharsNoCheck intrinsic."
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 5560ae2..a37ea1e 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -2951,75 +2951,48 @@
/* false_target */ nullptr);
}
-enum SelectVariant {
- kCsel,
- kCselFalseConst,
- kCselTrueConst,
- kFcsel,
-};
-
static inline bool IsConditionOnFloatingPointValues(HInstruction* condition) {
return condition->IsCondition() &&
Primitive::IsFloatingPointType(condition->InputAt(0)->GetType());
}
-static inline bool IsRecognizedCselConstant(HInstruction* constant) {
- if (constant->IsConstant()) {
- int64_t value = Int64FromConstant(constant->AsConstant());
- if ((value == -1) || (value == 0) || (value == 1)) {
- return true;
- }
- }
- return false;
-}
-
-static inline SelectVariant GetSelectVariant(HSelect* select) {
- if (Primitive::IsFloatingPointType(select->GetType())) {
- return kFcsel;
- } else if (IsRecognizedCselConstant(select->GetFalseValue())) {
- return kCselFalseConst;
- } else if (IsRecognizedCselConstant(select->GetTrueValue())) {
- return kCselTrueConst;
- } else {
- return kCsel;
- }
-}
-
-static inline bool HasSwappedInputs(SelectVariant variant) {
- return variant == kCselTrueConst;
-}
-
-static inline Condition GetConditionForSelect(HCondition* condition, SelectVariant variant) {
- IfCondition cond = HasSwappedInputs(variant) ? condition->GetOppositeCondition()
- : condition->GetCondition();
+static inline Condition GetConditionForSelect(HCondition* condition) {
+ IfCondition cond = condition->AsCondition()->GetCondition();
return IsConditionOnFloatingPointValues(condition) ? ARM64FPCondition(cond, condition->IsGtBias())
: ARM64Condition(cond);
}
void LocationsBuilderARM64::VisitSelect(HSelect* select) {
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(select);
- switch (GetSelectVariant(select)) {
- case kCsel:
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::RequiresRegister());
- locations->SetOut(Location::RequiresRegister());
- break;
- case kCselFalseConst:
- locations->SetInAt(0, Location::ConstantLocation(select->InputAt(0)->AsConstant()));
- locations->SetInAt(1, Location::RequiresRegister());
- locations->SetOut(Location::RequiresRegister());
- break;
- case kCselTrueConst:
- locations->SetInAt(0, Location::RequiresRegister());
- locations->SetInAt(1, Location::ConstantLocation(select->InputAt(1)->AsConstant()));
- locations->SetOut(Location::RequiresRegister());
- break;
- case kFcsel:
- locations->SetInAt(0, Location::RequiresFpuRegister());
- locations->SetInAt(1, Location::RequiresFpuRegister());
- locations->SetOut(Location::RequiresFpuRegister());
- break;
+ if (Primitive::IsFloatingPointType(select->GetType())) {
+ locations->SetInAt(0, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetOut(Location::RequiresFpuRegister());
+ } else {
+ HConstant* cst_true_value = select->GetTrueValue()->AsConstant();
+ HConstant* cst_false_value = select->GetFalseValue()->AsConstant();
+ bool is_true_value_constant = cst_true_value != nullptr;
+ bool is_false_value_constant = cst_false_value != nullptr;
+ // Ask VIXL whether we should synthesize constants in registers.
+ // We give an arbitrary register to VIXL when dealing with non-constant inputs.
+ Operand true_op = is_true_value_constant ?
+ Operand(Int64FromConstant(cst_true_value)) : Operand(x1);
+ Operand false_op = is_false_value_constant ?
+ Operand(Int64FromConstant(cst_false_value)) : Operand(x2);
+ bool true_value_in_register = false;
+ bool false_value_in_register = false;
+ MacroAssembler::GetCselSynthesisInformation(
+ x0, true_op, false_op, &true_value_in_register, &false_value_in_register);
+ true_value_in_register |= !is_true_value_constant;
+ false_value_in_register |= !is_false_value_constant;
+
+ locations->SetInAt(1, true_value_in_register ? Location::RequiresRegister()
+ : Location::ConstantLocation(cst_true_value));
+ locations->SetInAt(0, false_value_in_register ? Location::RequiresRegister()
+ : Location::ConstantLocation(cst_false_value));
+ locations->SetOut(Location::RequiresRegister());
}
+
if (IsBooleanValueOrMaterializedCondition(select->GetCondition())) {
locations->SetInAt(2, Location::RequiresRegister());
}
@@ -3027,45 +3000,34 @@
void InstructionCodeGeneratorARM64::VisitSelect(HSelect* select) {
HInstruction* cond = select->GetCondition();
- SelectVariant variant = GetSelectVariant(select);
Condition csel_cond;
if (IsBooleanValueOrMaterializedCondition(cond)) {
if (cond->IsCondition() && cond->GetNext() == select) {
- // Condition codes set from previous instruction.
- csel_cond = GetConditionForSelect(cond->AsCondition(), variant);
+ // Use the condition flags set by the previous instruction.
+ csel_cond = GetConditionForSelect(cond->AsCondition());
} else {
__ Cmp(InputRegisterAt(select, 2), 0);
- csel_cond = HasSwappedInputs(variant) ? eq : ne;
+ csel_cond = ne;
}
} else if (IsConditionOnFloatingPointValues(cond)) {
GenerateFcmp(cond);
- csel_cond = GetConditionForSelect(cond->AsCondition(), variant);
+ csel_cond = GetConditionForSelect(cond->AsCondition());
} else {
__ Cmp(InputRegisterAt(cond, 0), InputOperandAt(cond, 1));
- csel_cond = GetConditionForSelect(cond->AsCondition(), variant);
+ csel_cond = GetConditionForSelect(cond->AsCondition());
}
- switch (variant) {
- case kCsel:
- case kCselFalseConst:
- __ Csel(OutputRegister(select),
- InputRegisterAt(select, 1),
- InputOperandAt(select, 0),
- csel_cond);
- break;
- case kCselTrueConst:
- __ Csel(OutputRegister(select),
- InputRegisterAt(select, 0),
- InputOperandAt(select, 1),
- csel_cond);
- break;
- case kFcsel:
- __ Fcsel(OutputFPRegister(select),
- InputFPRegisterAt(select, 1),
- InputFPRegisterAt(select, 0),
- csel_cond);
- break;
+ if (Primitive::IsFloatingPointType(select->GetType())) {
+ __ Fcsel(OutputFPRegister(select),
+ InputFPRegisterAt(select, 1),
+ InputFPRegisterAt(select, 0),
+ csel_cond);
+ } else {
+ __ Csel(OutputRegister(select),
+ InputOperandAt(select, 1),
+ InputOperandAt(select, 0),
+ csel_cond);
}
}
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index ae3c4b0..4b4e549 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2283,8 +2283,6 @@
if (kIsDebugBuild) {
ScopedObjectAccess soa(Thread::Current());
DCHECK(IsValidHandle(type_handle));
- DCHECK(!type_handle->IsErroneous());
- DCHECK(!type_handle->IsArrayClass() || !type_handle->GetComponentType()->IsErroneous());
if (!is_exact) {
DCHECK(!type_handle->CannotBeAssignedFromOtherTypes())
<< "Callers of ReferenceTypeInfo::Create should ensure is_exact is properly computed";
diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc
index 2a281dd..3e6adcb 100644
--- a/compiler/optimizing/reference_type_propagation.cc
+++ b/compiler/optimizing/reference_type_propagation.cc
@@ -46,10 +46,10 @@
return *cache;
}
-// Returns true if klass is admissible to the propagation: non-null and non-erroneous.
+// Returns true if klass is admissible to the propagation: non-null and resolved.
// For an array type, we also check if the component type is admissible.
static bool IsAdmissible(mirror::Class* klass) SHARED_REQUIRES(Locks::mutator_lock_) {
- return klass != nullptr && !klass->IsErroneous() &&
+ return klass != nullptr && klass->IsResolved() &&
(!klass->IsArrayClass() || IsAdmissible(klass->GetComponentType()));
}
diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc
index 9368301..ac93083 100644
--- a/compiler/utils/mips/assembler_mips.cc
+++ b/compiler/utils/mips/assembler_mips.cc
@@ -448,6 +448,11 @@
EmitI(0xf, static_cast<Register>(0), rt, imm16);
}
+void MipsAssembler::Aui(Register rt, Register rs, uint16_t imm16) {
+ CHECK(IsR6());
+ EmitI(0xf, rs, rt, imm16);
+}
+
void MipsAssembler::Sync(uint32_t stype) {
EmitR(0, static_cast<Register>(0), static_cast<Register>(0), static_cast<Register>(0),
stype & 0x1f, 0xf);
@@ -1385,13 +1390,8 @@
Register base,
int32_t offset,
Register temp) {
- if (!IsInt<16>(offset)) {
- CHECK_NE(temp, AT); // Must not use AT as temp, as not to overwrite the loaded value.
- LoadConst32(AT, offset);
- Addu(AT, AT, base);
- base = AT;
- offset = 0;
- }
+ CHECK_NE(temp, AT); // Must not use AT as temp, so as not to overwrite the adjusted base.
+ AdjustBaseAndOffset(base, offset, /* is_doubleword */ false);
if (value == 0) {
temp = ZERO;
} else {
@@ -1404,14 +1404,8 @@
Register base,
int32_t offset,
Register temp) {
- // IsInt<16> must be passed a signed value.
- if (!IsInt<16>(offset) || !IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize))) {
- CHECK_NE(temp, AT); // Must not use AT as temp, as not to overwrite the loaded value.
- LoadConst32(AT, offset);
- Addu(AT, AT, base);
- base = AT;
- offset = 0;
- }
+ CHECK_NE(temp, AT); // Must not use AT as temp, so as not to overwrite the adjusted base.
+ AdjustBaseAndOffset(base, offset, /* is_doubleword */ true);
uint32_t low = Low32Bits(value);
uint32_t high = High32Bits(value);
if (low == 0) {
@@ -1457,11 +1451,35 @@
}
void MipsAssembler::Addiu32(Register rt, Register rs, int32_t value, Register temp) {
+ CHECK_NE(rs, temp); // Must not overwrite the register `rs` while loading `value`.
if (IsInt<16>(value)) {
Addiu(rt, rs, value);
+ } else if (IsR6()) {
+ int16_t high = High16Bits(value);
+ int16_t low = Low16Bits(value);
+ high += (low < 0) ? 1 : 0; // Account for sign extension in addiu.
+ if (low != 0) {
+ Aui(temp, rs, high);
+ Addiu(rt, temp, low);
+ } else {
+ Aui(rt, rs, high);
+ }
} else {
- LoadConst32(temp, value);
- Addu(rt, rs, temp);
+ // Do not load the whole 32-bit `value` if it can be represented as
+ // a sum of two 16-bit signed values. This can save an instruction.
+ constexpr int32_t kMinValueForSimpleAdjustment = std::numeric_limits<int16_t>::min() * 2;
+ constexpr int32_t kMaxValueForSimpleAdjustment = std::numeric_limits<int16_t>::max() * 2;
+ if (0 <= value && value <= kMaxValueForSimpleAdjustment) {
+ Addiu(temp, rs, kMaxValueForSimpleAdjustment / 2);
+ Addiu(rt, temp, value - kMaxValueForSimpleAdjustment / 2);
+ } else if (kMinValueForSimpleAdjustment <= value && value < 0) {
+ Addiu(temp, rs, kMinValueForSimpleAdjustment / 2);
+ Addiu(rt, temp, value - kMinValueForSimpleAdjustment / 2);
+ } else {
+ // Now that all shorter options have been exhausted, load the full 32-bit value.
+ LoadConst32(temp, value);
+ Addu(rt, rs, temp);
+ }
}
}
@@ -2262,17 +2280,103 @@
Bcond(label, kCondT, static_cast<Register>(ft), ZERO);
}
-void MipsAssembler::LoadFromOffset(LoadOperandType type, Register reg, Register base,
- int32_t offset) {
- // IsInt<16> must be passed a signed value.
- if (!IsInt<16>(offset) ||
- (type == kLoadDoubleword && !IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) {
- LoadConst32(AT, offset);
- Addu(AT, AT, base);
- base = AT;
- offset = 0;
+void MipsAssembler::AdjustBaseAndOffset(Register& base,
+ int32_t& offset,
+ bool is_doubleword,
+ bool is_float) {
+ // This method is used to adjust the base register and offset pair
+ // for a load/store when the offset doesn't fit into int16_t.
+ // It is assumed that `base + offset` is sufficiently aligned for memory
+ // operands that are machine word in size or smaller. For doubleword-sized
+ // operands it's assumed that `base` is a multiple of 8, while `offset`
+ // may be a multiple of 4 (e.g. 4-byte-aligned long and double arguments
+ // and spilled variables on the stack accessed relative to the stack
+ // pointer register).
+ // We preserve the "alignment" of `offset` by adjusting it by a multiple of 8.
+ CHECK_NE(base, AT); // Must not overwrite the register `base` while loading `offset`.
+
+ bool doubleword_aligned = IsAligned<kMipsDoublewordSize>(offset);
+ bool two_accesses = is_doubleword && (!is_float || !doubleword_aligned);
+
+ // IsInt<16> must be passed a signed value, hence the static cast below.
+ if (IsInt<16>(offset) &&
+ (!two_accesses || IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) {
+ // Nothing to do: `offset` (and, if needed, `offset + 4`) fits into int16_t.
+ return;
}
+ // Remember the "(mis)alignment" of `offset`, it will be checked at the end.
+ uint32_t misalignment = offset & (kMipsDoublewordSize - 1);
+
+ // Do not load the whole 32-bit `offset` if it can be represented as
+ // a sum of two 16-bit signed offsets. This can save an instruction or two.
+ // To simplify matters, only do this for a symmetric range of offsets from
+ // about -64KB to about +64KB, allowing further addition of 4 when accessing
+ // 64-bit variables with two 32-bit accesses.
+ constexpr int32_t kMinOffsetForSimpleAdjustment = 0x7ff8; // Max int16_t that's a multiple of 8.
+ constexpr int32_t kMaxOffsetForSimpleAdjustment = 2 * kMinOffsetForSimpleAdjustment;
+ if (0 <= offset && offset <= kMaxOffsetForSimpleAdjustment) {
+ Addiu(AT, base, kMinOffsetForSimpleAdjustment);
+ offset -= kMinOffsetForSimpleAdjustment;
+ } else if (-kMaxOffsetForSimpleAdjustment <= offset && offset < 0) {
+ Addiu(AT, base, -kMinOffsetForSimpleAdjustment);
+ offset += kMinOffsetForSimpleAdjustment;
+ } else if (IsR6()) {
+ // On R6 take advantage of the aui instruction, e.g.:
+ // aui AT, base, offset_high
+ // lw reg_lo, offset_low(AT)
+ // lw reg_hi, (offset_low+4)(AT)
+ // or when offset_low+4 overflows int16_t:
+ // aui AT, base, offset_high
+ // addiu AT, AT, 8
+ // lw reg_lo, (offset_low-8)(AT)
+ // lw reg_hi, (offset_low-4)(AT)
+ int16_t offset_high = High16Bits(offset);
+ int16_t offset_low = Low16Bits(offset);
+ offset_high += (offset_low < 0) ? 1 : 0; // Account for offset sign extension in load/store.
+ Aui(AT, base, offset_high);
+ if (two_accesses && !IsInt<16>(static_cast<int32_t>(offset_low + kMipsWordSize))) {
+ // Avoid overflow in the 16-bit offset of the load/store instruction when adding 4.
+ Addiu(AT, AT, kMipsDoublewordSize);
+ offset_low -= kMipsDoublewordSize;
+ }
+ offset = offset_low;
+ } else {
+ // Do not load the whole 32-bit `offset` if it can be represented as
+ // a sum of three 16-bit signed offsets. This can save an instruction.
+ // To simplify matters, only do this for a symmetric range of offsets from
+ // about -96KB to about +96KB, allowing further addition of 4 when accessing
+ // 64-bit variables with two 32-bit accesses.
+ constexpr int32_t kMinOffsetForMediumAdjustment = 2 * kMinOffsetForSimpleAdjustment;
+ constexpr int32_t kMaxOffsetForMediumAdjustment = 3 * kMinOffsetForSimpleAdjustment;
+ if (0 <= offset && offset <= kMaxOffsetForMediumAdjustment) {
+ Addiu(AT, base, kMinOffsetForMediumAdjustment / 2);
+ Addiu(AT, AT, kMinOffsetForMediumAdjustment / 2);
+ offset -= kMinOffsetForMediumAdjustment;
+ } else if (-kMaxOffsetForMediumAdjustment <= offset && offset < 0) {
+ Addiu(AT, base, -kMinOffsetForMediumAdjustment / 2);
+ Addiu(AT, AT, -kMinOffsetForMediumAdjustment / 2);
+ offset += kMinOffsetForMediumAdjustment;
+ } else {
+ // Now that all shorter options have been exhausted, load the full 32-bit offset.
+ int32_t loaded_offset = RoundDown(offset, kMipsDoublewordSize);
+ LoadConst32(AT, loaded_offset);
+ Addu(AT, AT, base);
+ offset -= loaded_offset;
+ }
+ }
+ base = AT;
+
+ CHECK(IsInt<16>(offset));
+ if (two_accesses) {
+ CHECK(IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)));
+ }
+ CHECK_EQ(misalignment, offset & (kMipsDoublewordSize - 1));
+}
+
+void MipsAssembler::LoadFromOffset(LoadOperandType type, Register reg, Register base,
+ int32_t offset) {
+ AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kLoadDoubleword));
switch (type) {
case kLoadSignedByte:
Lb(reg, base, offset);
@@ -2306,27 +2410,12 @@
}
void MipsAssembler::LoadSFromOffset(FRegister reg, Register base, int32_t offset) {
- if (!IsInt<16>(offset)) {
- LoadConst32(AT, offset);
- Addu(AT, AT, base);
- base = AT;
- offset = 0;
- }
-
+ AdjustBaseAndOffset(base, offset, /* is_doubleword */ false, /* is_float */ true);
Lwc1(reg, base, offset);
}
void MipsAssembler::LoadDFromOffset(FRegister reg, Register base, int32_t offset) {
- // IsInt<16> must be passed a signed value.
- if (!IsInt<16>(offset) ||
- (!IsAligned<kMipsDoublewordSize>(offset) &&
- !IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) {
- LoadConst32(AT, offset);
- Addu(AT, AT, base);
- base = AT;
- offset = 0;
- }
-
+ AdjustBaseAndOffset(base, offset, /* is_doubleword */ true, /* is_float */ true);
if (offset & 0x7) {
if (Is32BitFPU()) {
Lwc1(reg, base, offset);
@@ -2365,15 +2454,10 @@
void MipsAssembler::StoreToOffset(StoreOperandType type, Register reg, Register base,
int32_t offset) {
- // IsInt<16> must be passed a signed value.
- if (!IsInt<16>(offset) ||
- (type == kStoreDoubleword && !IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) {
- LoadConst32(AT, offset);
- Addu(AT, AT, base);
- base = AT;
- offset = 0;
- }
-
+ // Must not use AT as `reg`, so as not to overwrite the value being stored
+ // with the adjusted `base`.
+ CHECK_NE(reg, AT);
+ AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kStoreDoubleword));
switch (type) {
case kStoreByte:
Sb(reg, base, offset);
@@ -2396,27 +2480,12 @@
}
void MipsAssembler::StoreSToOffset(FRegister reg, Register base, int32_t offset) {
- if (!IsInt<16>(offset)) {
- LoadConst32(AT, offset);
- Addu(AT, AT, base);
- base = AT;
- offset = 0;
- }
-
+ AdjustBaseAndOffset(base, offset, /* is_doubleword */ false, /* is_float */ true);
Swc1(reg, base, offset);
}
void MipsAssembler::StoreDToOffset(FRegister reg, Register base, int32_t offset) {
- // IsInt<16> must be passed a signed value.
- if (!IsInt<16>(offset) ||
- (!IsAligned<kMipsDoublewordSize>(offset) &&
- !IsInt<16>(static_cast<int32_t>(offset + kMipsWordSize)))) {
- LoadConst32(AT, offset);
- Addu(AT, AT, base);
- base = AT;
- offset = 0;
- }
-
+ AdjustBaseAndOffset(base, offset, /* is_doubleword */ true, /* is_float */ true);
if (offset & 0x7) {
if (Is32BitFPU()) {
Swc1(reg, base, offset);
diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h
index d5e6285..31b3b31 100644
--- a/compiler/utils/mips/assembler_mips.h
+++ b/compiler/utils/mips/assembler_mips.h
@@ -183,6 +183,7 @@
void Lbu(Register rt, Register rs, uint16_t imm16);
void Lhu(Register rt, Register rs, uint16_t imm16);
void Lui(Register rt, uint16_t imm16);
+ void Aui(Register rt, Register rs, uint16_t imm16); // R6
void Sync(uint32_t stype);
void Mfhi(Register rd); // R2
void Mflo(Register rd); // R2
@@ -385,6 +386,10 @@
void Bc1nez(FRegister ft, MipsLabel* label); // R6
void EmitLoad(ManagedRegister m_dst, Register src_register, int32_t src_offset, size_t size);
+ void AdjustBaseAndOffset(Register& base,
+ int32_t& offset,
+ bool is_doubleword,
+ bool is_float = false);
void LoadFromOffset(LoadOperandType type, Register reg, Register base, int32_t offset);
void LoadSFromOffset(FRegister reg, Register base, int32_t offset);
void LoadDFromOffset(FRegister reg, Register base, int32_t offset);
diff --git a/compiler/utils/mips/assembler_mips_test.cc b/compiler/utils/mips/assembler_mips_test.cc
index 56e5884..57d5183 100644
--- a/compiler/utils/mips/assembler_mips_test.cc
+++ b/compiler/utils/mips/assembler_mips_test.cc
@@ -731,212 +731,538 @@
DriverStr(RepeatRR(&mips::MipsAssembler::Not, "nor ${reg1}, ${reg2}, $zero"), "Not");
}
-TEST_F(AssemblerMIPSTest, LoadFromOffset) {
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A0, mips::A0, 0);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A0, mips::A1, 0);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A0, mips::A1, 256);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A0, mips::A1, 1000);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A0, mips::A1, 0x8000);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A0, mips::A1, 0x10000);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A0, mips::A1, 0x12345678);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A0, mips::A1, -256);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A0, mips::A1, 0xFFFF8000);
- __ LoadFromOffset(mips::kLoadSignedByte, mips::A0, mips::A1, 0xABCDEF00);
-
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A0, mips::A0, 0);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A0, mips::A1, 0);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A0, mips::A1, 256);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A0, mips::A1, 1000);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A0, mips::A1, 0x8000);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A0, mips::A1, 0x10000);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A0, mips::A1, 0x12345678);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A0, mips::A1, -256);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A0, mips::A1, 0xFFFF8000);
- __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A0, mips::A1, 0xABCDEF00);
-
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A0, mips::A0, 0);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A0, mips::A1, 0);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A0, mips::A1, 256);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A0, mips::A1, 1000);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A0, mips::A1, 0x8000);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A0, mips::A1, 0x10000);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A0, mips::A1, 0x12345678);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A0, mips::A1, -256);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A0, mips::A1, 0xFFFF8000);
- __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A0, mips::A1, 0xABCDEF00);
-
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A0, mips::A0, 0);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A0, mips::A1, 0);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A0, mips::A1, 256);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A0, mips::A1, 1000);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A0, mips::A1, 0x8000);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A0, mips::A1, 0x10000);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A0, mips::A1, 0x12345678);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A0, mips::A1, -256);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A0, mips::A1, 0xFFFF8000);
- __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A0, mips::A1, 0xABCDEF00);
-
- __ LoadFromOffset(mips::kLoadWord, mips::A0, mips::A0, 0);
- __ LoadFromOffset(mips::kLoadWord, mips::A0, mips::A1, 0);
- __ LoadFromOffset(mips::kLoadWord, mips::A0, mips::A1, 256);
- __ LoadFromOffset(mips::kLoadWord, mips::A0, mips::A1, 1000);
- __ LoadFromOffset(mips::kLoadWord, mips::A0, mips::A1, 0x8000);
- __ LoadFromOffset(mips::kLoadWord, mips::A0, mips::A1, 0x10000);
- __ LoadFromOffset(mips::kLoadWord, mips::A0, mips::A1, 0x12345678);
- __ LoadFromOffset(mips::kLoadWord, mips::A0, mips::A1, -256);
- __ LoadFromOffset(mips::kLoadWord, mips::A0, mips::A1, 0xFFFF8000);
- __ LoadFromOffset(mips::kLoadWord, mips::A0, mips::A1, 0xABCDEF00);
-
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A0, 0);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A1, 0);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A1, mips::A0, 0);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, 0);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, 256);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, 1000);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, 0x8000);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, 0x10000);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, 0x12345678);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -256);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, 0xFFFF8000);
- __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, 0xABCDEF00);
+TEST_F(AssemblerMIPSTest, Addiu32) {
+ __ Addiu32(mips::A1, mips::A2, -0x8000);
+ __ Addiu32(mips::A1, mips::A2, +0);
+ __ Addiu32(mips::A1, mips::A2, +0x7FFF);
+ __ Addiu32(mips::A1, mips::A2, -0x10000);
+ __ Addiu32(mips::A1, mips::A2, -0x8001);
+ __ Addiu32(mips::A1, mips::A2, +0x8000);
+ __ Addiu32(mips::A1, mips::A2, +0xFFFE);
+ __ Addiu32(mips::A1, mips::A2, -0x10001);
+ __ Addiu32(mips::A1, mips::A2, +0xFFFF);
+ __ Addiu32(mips::A1, mips::A2, +0x10000);
+ __ Addiu32(mips::A1, mips::A2, +0x10001);
+ __ Addiu32(mips::A1, mips::A2, +0x12345678);
const char* expected =
- "lb $a0, 0($a0)\n"
- "lb $a0, 0($a1)\n"
- "lb $a0, 256($a1)\n"
- "lb $a0, 1000($a1)\n"
- "ori $at, $zero, 0x8000\n"
- "addu $at, $at, $a1\n"
- "lb $a0, 0($at)\n"
+ "addiu $a1, $a2, -0x8000\n"
+ "addiu $a1, $a2, 0\n"
+ "addiu $a1, $a2, 0x7FFF\n"
+ "addiu $at, $a2, -0x8000\n"
+ "addiu $a1, $at, -0x8000\n"
+ "addiu $at, $a2, -0x8000\n"
+ "addiu $a1, $at, -1\n"
+ "addiu $at, $a2, 0x7FFF\n"
+ "addiu $a1, $at, 1\n"
+ "addiu $at, $a2, 0x7FFF\n"
+ "addiu $a1, $at, 0x7FFF\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0xFFFF\n"
+ "addu $a1, $a2, $at\n"
+ "ori $at, $zero, 0xFFFF\n"
+ "addu $a1, $a2, $at\n"
"lui $at, 1\n"
- "addu $at, $at, $a1\n"
- "lb $a0, 0($at)\n"
- "lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
- "addu $at, $at, $a1\n"
- "lb $a0, 0($at)\n"
- "lb $a0, -256($a1)\n"
- "lb $a0, 0xFFFF8000($a1)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
- "addu $at, $at, $a1\n"
- "lb $a0, 0($at)\n"
-
- "lbu $a0, 0($a0)\n"
- "lbu $a0, 0($a1)\n"
- "lbu $a0, 256($a1)\n"
- "lbu $a0, 1000($a1)\n"
- "ori $at, $zero, 0x8000\n"
- "addu $at, $at, $a1\n"
- "lbu $a0, 0($at)\n"
+ "addu $a1, $a2, $at\n"
"lui $at, 1\n"
- "addu $at, $at, $a1\n"
- "lbu $a0, 0($at)\n"
+ "ori $at, $at, 1\n"
+ "addu $a1, $a2, $at\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
- "addu $at, $at, $a1\n"
- "lbu $a0, 0($at)\n"
- "lbu $a0, -256($a1)\n"
- "lbu $a0, 0xFFFF8000($a1)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
- "addu $at, $at, $a1\n"
- "lbu $a0, 0($at)\n"
+ "ori $at, $at, 0x5678\n"
+ "addu $a1, $a2, $at\n";
+ DriverStr(expected, "Addiu32");
+}
- "lh $a0, 0($a0)\n"
- "lh $a0, 0($a1)\n"
- "lh $a0, 256($a1)\n"
- "lh $a0, 1000($a1)\n"
- "ori $at, $zero, 0x8000\n"
+TEST_F(AssemblerMIPSTest, LoadFromOffset) {
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x8000);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x7FF8);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x7FFB);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x7FFC);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x7FFF);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0xFFF0);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x8008);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x8001);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x8000);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0xFFF0);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x17FE8);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x0FFF8);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x0FFF1);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x0FFF1);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x0FFF8);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x17FE8);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x17FF0);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, -0x17FE9);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x17FE9);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x17FF0);
+ __ LoadFromOffset(mips::kLoadSignedByte, mips::A3, mips::A1, +0x12345678);
+
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x8000);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x7FF8);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x7FFB);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x7FFC);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x7FFF);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0xFFF0);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x8008);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x8001);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x8000);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0xFFF0);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x17FE8);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x0FFF8);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x0FFF1);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x0FFF1);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x0FFF8);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x17FE8);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x17FF0);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, -0x17FE9);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x17FE9);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x17FF0);
+ __ LoadFromOffset(mips::kLoadUnsignedByte, mips::A3, mips::A1, +0x12345678);
+
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x8000);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x7FF8);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x7FFB);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x7FFC);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x7FFF);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0xFFF0);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x8008);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x8001);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x8000);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0xFFF0);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x17FE8);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x0FFF8);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x0FFF1);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x0FFF1);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x0FFF8);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x17FE8);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x17FF0);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, -0x17FE9);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x17FE9);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x17FF0);
+ __ LoadFromOffset(mips::kLoadSignedHalfword, mips::A3, mips::A1, +0x12345678);
+
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x8000);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x7FF8);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x7FFB);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x7FFC);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x7FFF);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0xFFF0);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x8008);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x8001);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x8000);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0xFFF0);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x17FE8);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x0FFF8);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x0FFF1);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x0FFF1);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x0FFF8);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x17FE8);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x17FF0);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, -0x17FE9);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x17FE9);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x17FF0);
+ __ LoadFromOffset(mips::kLoadUnsignedHalfword, mips::A3, mips::A1, +0x12345678);
+
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x8000);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x7FF8);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x7FFB);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x7FFC);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x7FFF);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0xFFF0);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x8008);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x8001);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x8000);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0xFFF0);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x17FE8);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x0FFF8);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x0FFF1);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x0FFF1);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x0FFF8);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x17FE8);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x17FF0);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, -0x17FE9);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x17FE9);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x17FF0);
+ __ LoadFromOffset(mips::kLoadWord, mips::A3, mips::A1, +0x12345678);
+
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x8000);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x7FF8);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x7FFB);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x7FFC);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x7FFF);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0xFFF0);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x8008);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x8001);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x8000);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0xFFF0);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x17FE8);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x0FFF8);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x0FFF1);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x0FFF1);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x0FFF8);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x17FE8);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x17FF0);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, -0x17FE9);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x17FE9);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x17FF0);
+ __ LoadFromOffset(mips::kLoadDoubleword, mips::A0, mips::A2, +0x12345678);
+
+ const char* expected =
+ "lb $a3, -0x8000($a1)\n"
+ "lb $a3, 0($a1)\n"
+ "lb $a3, 0x7FF8($a1)\n"
+ "lb $a3, 0x7FFB($a1)\n"
+ "lb $a3, 0x7FFC($a1)\n"
+ "lb $a3, 0x7FFF($a1)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lb $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lb $a3, -0x10($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lb $a3, -9($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "lb $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "lb $a3, 0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lb $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lb $a3, -8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lb $a3, -1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lb $a3, 1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lb $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lb $a3, 0x7FF8($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
- "lh $a0, 0($at)\n"
- "lui $at, 1\n"
+ "lb $a3, 0($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
- "lh $a0, 0($at)\n"
+ "lb $a3, 7($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a1\n"
+ "lb $a3, 1($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
+ "addu $at, $at, $a1\n"
+ "lb $a3, 0($at)\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
+ "ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
- "lh $a0, 0($at)\n"
- "lh $a0, -256($a1)\n"
- "lh $a0, 0xFFFF8000($a1)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
- "addu $at, $at, $a1\n"
- "lh $a0, 0($at)\n"
+ "lb $a3, 0($at)\n"
- "lhu $a0, 0($a0)\n"
- "lhu $a0, 0($a1)\n"
- "lhu $a0, 256($a1)\n"
- "lhu $a0, 1000($a1)\n"
- "ori $at, $zero, 0x8000\n"
+ "lbu $a3, -0x8000($a1)\n"
+ "lbu $a3, 0($a1)\n"
+ "lbu $a3, 0x7FF8($a1)\n"
+ "lbu $a3, 0x7FFB($a1)\n"
+ "lbu $a3, 0x7FFC($a1)\n"
+ "lbu $a3, 0x7FFF($a1)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lbu $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lbu $a3, -0x10($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lbu $a3, -9($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "lbu $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "lbu $a3, 0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lbu $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lbu $a3, -8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lbu $a3, -1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lbu $a3, 1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lbu $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lbu $a3, 0x7FF8($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
- "lhu $a0, 0($at)\n"
- "lui $at, 1\n"
+ "lbu $a3, 0($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
- "lhu $a0, 0($at)\n"
+ "lbu $a3, 7($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a1\n"
+ "lbu $a3, 1($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
+ "addu $at, $at, $a1\n"
+ "lbu $a3, 0($at)\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
+ "ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
- "lhu $a0, 0($at)\n"
- "lhu $a0, -256($a1)\n"
- "lhu $a0, 0xFFFF8000($a1)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
- "addu $at, $at, $a1\n"
- "lhu $a0, 0($at)\n"
+ "lbu $a3, 0($at)\n"
- "lw $a0, 0($a0)\n"
- "lw $a0, 0($a1)\n"
- "lw $a0, 256($a1)\n"
- "lw $a0, 1000($a1)\n"
- "ori $at, $zero, 0x8000\n"
+ "lh $a3, -0x8000($a1)\n"
+ "lh $a3, 0($a1)\n"
+ "lh $a3, 0x7FF8($a1)\n"
+ "lh $a3, 0x7FFB($a1)\n"
+ "lh $a3, 0x7FFC($a1)\n"
+ "lh $a3, 0x7FFF($a1)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lh $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lh $a3, -0x10($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lh $a3, -9($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "lh $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "lh $a3, 0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lh $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lh $a3, -8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lh $a3, -1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lh $a3, 1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lh $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lh $a3, 0x7FF8($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
- "lw $a0, 0($at)\n"
- "lui $at, 1\n"
+ "lh $a3, 0($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
- "lw $a0, 0($at)\n"
+ "lh $a3, 7($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a1\n"
+ "lh $a3, 1($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
+ "addu $at, $at, $a1\n"
+ "lh $a3, 0($at)\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
+ "ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
- "lw $a0, 0($at)\n"
- "lw $a0, -256($a1)\n"
- "lw $a0, 0xFFFF8000($a1)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
- "addu $at, $at, $a1\n"
- "lw $a0, 0($at)\n"
+ "lh $a3, 0($at)\n"
- "lw $a1, 4($a0)\n"
- "lw $a0, 0($a0)\n"
- "lw $a0, 0($a1)\n"
- "lw $a1, 4($a1)\n"
- "lw $a1, 0($a0)\n"
- "lw $a2, 4($a0)\n"
+ "lhu $a3, -0x8000($a1)\n"
+ "lhu $a3, 0($a1)\n"
+ "lhu $a3, 0x7FF8($a1)\n"
+ "lhu $a3, 0x7FFB($a1)\n"
+ "lhu $a3, 0x7FFC($a1)\n"
+ "lhu $a3, 0x7FFF($a1)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lhu $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lhu $a3, -0x10($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lhu $a3, -9($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "lhu $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "lhu $a3, 0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lhu $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lhu $a3, -8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lhu $a3, -1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lhu $a3, 1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lhu $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lhu $a3, 0x7FF8($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
+ "addu $at, $at, $a1\n"
+ "lhu $a3, 0($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
+ "addu $at, $at, $a1\n"
+ "lhu $a3, 7($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a1\n"
+ "lhu $a3, 1($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
+ "addu $at, $at, $a1\n"
+ "lhu $a3, 0($at)\n"
+ "lui $at, 0x1234\n"
+ "ori $at, $at, 0x5678\n"
+ "addu $at, $at, $a1\n"
+ "lhu $a3, 0($at)\n"
+
+ "lw $a3, -0x8000($a1)\n"
+ "lw $a3, 0($a1)\n"
+ "lw $a3, 0x7FF8($a1)\n"
+ "lw $a3, 0x7FFB($a1)\n"
+ "lw $a3, 0x7FFC($a1)\n"
+ "lw $a3, 0x7FFF($a1)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lw $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lw $a3, -0x10($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "lw $a3, -9($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "lw $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "lw $a3, 0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lw $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lw $a3, -8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lw $a3, -1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lw $a3, 1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lw $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lw $a3, 0x7FF8($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
+ "addu $at, $at, $a1\n"
+ "lw $a3, 0($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
+ "addu $at, $at, $a1\n"
+ "lw $a3, 7($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a1\n"
+ "lw $a3, 1($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
+ "addu $at, $at, $a1\n"
+ "lw $a3, 0($at)\n"
+ "lui $at, 0x1234\n"
+ "ori $at, $at, 0x5678\n"
+ "addu $at, $at, $a1\n"
+ "lw $a3, 0($at)\n"
+
+ "lw $a0, -0x8000($a2)\n"
+ "lw $a1, -0x7FFC($a2)\n"
"lw $a0, 0($a2)\n"
"lw $a1, 4($a2)\n"
- "lw $a0, 256($a2)\n"
- "lw $a1, 260($a2)\n"
- "lw $a0, 1000($a2)\n"
- "lw $a1, 1004($a2)\n"
- "ori $at, $zero, 0x8000\n"
+ "lw $a0, 0x7FF8($a2)\n"
+ "lw $a1, 0x7FFC($a2)\n"
+ "lw $a0, 0x7FFB($a2)\n"
+ "lw $a1, 0x7FFF($a2)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "lw $a0, 4($at)\n"
+ "lw $a1, 8($at)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "lw $a0, 7($at)\n"
+ "lw $a1, 11($at)\n"
+ "addiu $at, $a2, -0x7FF8\n"
+ "lw $a0, -0x7FF8($at)\n"
+ "lw $a1, -0x7FF4($at)\n"
+ "addiu $at, $a2, -0x7FF8\n"
+ "lw $a0, -0x10($at)\n"
+ "lw $a1, -0xC($at)\n"
+ "addiu $at, $a2, -0x7FF8\n"
+ "lw $a0, -9($at)\n"
+ "lw $a1, -5($at)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "lw $a0, 8($at)\n"
+ "lw $a1, 12($at)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "lw $a0, 0x7FF8($at)\n"
+ "lw $a1, 0x7FFC($at)\n"
+ "addiu $at, $a2, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lw $a0, -0x7FF8($at)\n"
+ "lw $a1, -0x7FF4($at)\n"
+ "addiu $at, $a2, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lw $a0, -8($at)\n"
+ "lw $a1, -4($at)\n"
+ "addiu $at, $a2, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lw $a0, -1($at)\n"
+ "lw $a1, 3($at)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lw $a0, 1($at)\n"
+ "lw $a1, 5($at)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lw $a0, 8($at)\n"
+ "lw $a1, 12($at)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lw $a0, 0x7FF8($at)\n"
+ "lw $a1, 0x7FFC($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a2\n"
"lw $a0, 0($at)\n"
"lw $a1, 4($at)\n"
- "lui $at, 1\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
+ "addu $at, $at, $a2\n"
+ "lw $a0, 7($at)\n"
+ "lw $a1, 11($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a2\n"
+ "lw $a0, 1($at)\n"
+ "lw $a1, 5($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a2\n"
"lw $a0, 0($at)\n"
"lw $a1, 4($at)\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
- "addu $at, $at, $a2\n"
- "lw $a0, 0($at)\n"
- "lw $a1, 4($at)\n"
- "lw $a0, -256($a2)\n"
- "lw $a1, -252($a2)\n"
- "lw $a0, 0xFFFF8000($a2)\n"
- "lw $a1, 0xFFFF8004($a2)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
+ "ori $at, $at, 0x5678\n"
"addu $at, $at, $a2\n"
"lw $a0, 0($at)\n"
"lw $a1, 4($at)\n";
@@ -944,208 +1270,513 @@
}
TEST_F(AssemblerMIPSTest, LoadSFromOffset) {
- __ LoadSFromOffset(mips::F0, mips::A0, 0);
- __ LoadSFromOffset(mips::F0, mips::A0, 4);
- __ LoadSFromOffset(mips::F0, mips::A0, 256);
- __ LoadSFromOffset(mips::F0, mips::A0, 0x8000);
- __ LoadSFromOffset(mips::F0, mips::A0, 0x10000);
- __ LoadSFromOffset(mips::F0, mips::A0, 0x12345678);
- __ LoadSFromOffset(mips::F0, mips::A0, -256);
- __ LoadSFromOffset(mips::F0, mips::A0, 0xFFFF8000);
- __ LoadSFromOffset(mips::F0, mips::A0, 0xABCDEF00);
+ __ LoadSFromOffset(mips::F2, mips::A0, -0x8000);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0x7FF8);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0x7FFB);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0x7FFC);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0x7FFF);
+ __ LoadSFromOffset(mips::F2, mips::A0, -0xFFF0);
+ __ LoadSFromOffset(mips::F2, mips::A0, -0x8008);
+ __ LoadSFromOffset(mips::F2, mips::A0, -0x8001);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0x8000);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0xFFF0);
+ __ LoadSFromOffset(mips::F2, mips::A0, -0x17FE8);
+ __ LoadSFromOffset(mips::F2, mips::A0, -0x0FFF8);
+ __ LoadSFromOffset(mips::F2, mips::A0, -0x0FFF1);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0x0FFF1);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0x0FFF8);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0x17FE8);
+ __ LoadSFromOffset(mips::F2, mips::A0, -0x17FF0);
+ __ LoadSFromOffset(mips::F2, mips::A0, -0x17FE9);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0x17FE9);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0x17FF0);
+ __ LoadSFromOffset(mips::F2, mips::A0, +0x12345678);
const char* expected =
- "lwc1 $f0, 0($a0)\n"
- "lwc1 $f0, 4($a0)\n"
- "lwc1 $f0, 256($a0)\n"
- "ori $at, $zero, 0x8000\n"
+ "lwc1 $f2, -0x8000($a0)\n"
+ "lwc1 $f2, 0($a0)\n"
+ "lwc1 $f2, 0x7FF8($a0)\n"
+ "lwc1 $f2, 0x7FFB($a0)\n"
+ "lwc1 $f2, 0x7FFC($a0)\n"
+ "lwc1 $f2, 0x7FFF($a0)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "lwc1 $f2, -0x7FF8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "lwc1 $f2, -0x10($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "lwc1 $f2, -9($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "lwc1 $f2, 8($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "lwc1 $f2, 0x7FF8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lwc1 $f2, -0x7FF8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lwc1 $f2, -8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lwc1 $f2, -1($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lwc1 $f2, 1($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lwc1 $f2, 8($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lwc1 $f2, 0x7FF8($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
- "lwc1 $f0, 0($at)\n"
- "lui $at, 1\n"
+ "lwc1 $f2, 0($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
- "lwc1 $f0, 0($at)\n"
+ "lwc1 $f2, 7($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a0\n"
+ "lwc1 $f2, 1($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
+ "addu $at, $at, $a0\n"
+ "lwc1 $f2, 0($at)\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
+ "ori $at, $at, 0x5678\n"
"addu $at, $at, $a0\n"
- "lwc1 $f0, 0($at)\n"
- "lwc1 $f0, -256($a0)\n"
- "lwc1 $f0, 0xFFFF8000($a0)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
- "addu $at, $at, $a0\n"
- "lwc1 $f0, 0($at)\n";
+ "lwc1 $f2, 0($at)\n";
DriverStr(expected, "LoadSFromOffset");
}
-
TEST_F(AssemblerMIPSTest, LoadDFromOffset) {
- __ LoadDFromOffset(mips::F0, mips::A0, 0);
- __ LoadDFromOffset(mips::F0, mips::A0, 4);
- __ LoadDFromOffset(mips::F0, mips::A0, 256);
- __ LoadDFromOffset(mips::F0, mips::A0, 0x8000);
- __ LoadDFromOffset(mips::F0, mips::A0, 0x10000);
- __ LoadDFromOffset(mips::F0, mips::A0, 0x12345678);
- __ LoadDFromOffset(mips::F0, mips::A0, -256);
- __ LoadDFromOffset(mips::F0, mips::A0, 0xFFFF8000);
- __ LoadDFromOffset(mips::F0, mips::A0, 0xABCDEF00);
+ __ LoadDFromOffset(mips::F0, mips::A0, -0x8000);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0x7FF8);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0x7FFB);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0x7FFC);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0x7FFF);
+ __ LoadDFromOffset(mips::F0, mips::A0, -0xFFF0);
+ __ LoadDFromOffset(mips::F0, mips::A0, -0x8008);
+ __ LoadDFromOffset(mips::F0, mips::A0, -0x8001);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0x8000);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0xFFF0);
+ __ LoadDFromOffset(mips::F0, mips::A0, -0x17FE8);
+ __ LoadDFromOffset(mips::F0, mips::A0, -0x0FFF8);
+ __ LoadDFromOffset(mips::F0, mips::A0, -0x0FFF1);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0x0FFF1);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0x0FFF8);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0x17FE8);
+ __ LoadDFromOffset(mips::F0, mips::A0, -0x17FF0);
+ __ LoadDFromOffset(mips::F0, mips::A0, -0x17FE9);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0x17FE9);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0x17FF0);
+ __ LoadDFromOffset(mips::F0, mips::A0, +0x12345678);
const char* expected =
+ "ldc1 $f0, -0x8000($a0)\n"
"ldc1 $f0, 0($a0)\n"
- "lwc1 $f0, 4($a0)\n"
- "lwc1 $f1, 8($a0)\n"
- "ldc1 $f0, 256($a0)\n"
- "ori $at, $zero, 0x8000\n"
+ "ldc1 $f0, 0x7FF8($a0)\n"
+ "lwc1 $f0, 0x7FFB($a0)\n"
+ "lwc1 $f1, 0x7FFF($a0)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "lwc1 $f0, 4($at)\n"
+ "lwc1 $f1, 8($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "lwc1 $f0, 7($at)\n"
+ "lwc1 $f1, 11($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "ldc1 $f0, -0x7FF8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "ldc1 $f0, -0x10($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "lwc1 $f0, -9($at)\n"
+ "lwc1 $f1, -5($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "ldc1 $f0, 8($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "ldc1 $f0, 0x7FF8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "ldc1 $f0, -0x7FF8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "ldc1 $f0, -8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "lwc1 $f0, -1($at)\n"
+ "lwc1 $f1, 3($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "lwc1 $f0, 1($at)\n"
+ "lwc1 $f1, 5($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "ldc1 $f0, 8($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "ldc1 $f0, 0x7FF8($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
"ldc1 $f0, 0($at)\n"
- "lui $at, 1\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
+ "addu $at, $at, $a0\n"
+ "lwc1 $f0, 7($at)\n"
+ "lwc1 $f1, 11($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a0\n"
+ "lwc1 $f0, 1($at)\n"
+ "lwc1 $f1, 5($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a0\n"
"ldc1 $f0, 0($at)\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
- "addu $at, $at, $a0\n"
- "ldc1 $f0, 0($at)\n"
- "ldc1 $f0, -256($a0)\n"
- "ldc1 $f0, 0xFFFF8000($a0)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
+ "ori $at, $at, 0x5678\n"
"addu $at, $at, $a0\n"
"ldc1 $f0, 0($at)\n";
DriverStr(expected, "LoadDFromOffset");
}
TEST_F(AssemblerMIPSTest, StoreToOffset) {
- __ StoreToOffset(mips::kStoreByte, mips::A0, mips::A0, 0);
- __ StoreToOffset(mips::kStoreByte, mips::A0, mips::A1, 0);
- __ StoreToOffset(mips::kStoreByte, mips::A0, mips::A1, 256);
- __ StoreToOffset(mips::kStoreByte, mips::A0, mips::A1, 1000);
- __ StoreToOffset(mips::kStoreByte, mips::A0, mips::A1, 0x8000);
- __ StoreToOffset(mips::kStoreByte, mips::A0, mips::A1, 0x10000);
- __ StoreToOffset(mips::kStoreByte, mips::A0, mips::A1, 0x12345678);
- __ StoreToOffset(mips::kStoreByte, mips::A0, mips::A1, -256);
- __ StoreToOffset(mips::kStoreByte, mips::A0, mips::A1, 0xFFFF8000);
- __ StoreToOffset(mips::kStoreByte, mips::A0, mips::A1, 0xABCDEF00);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x8000);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x7FF8);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x7FFB);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x7FFC);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x7FFF);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0xFFF0);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x8008);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x8001);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x8000);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0xFFF0);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x17FE8);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x0FFF8);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x0FFF1);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x0FFF1);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x0FFF8);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x17FE8);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x17FF0);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, -0x17FE9);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x17FE9);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x17FF0);
+ __ StoreToOffset(mips::kStoreByte, mips::A3, mips::A1, +0x12345678);
- __ StoreToOffset(mips::kStoreHalfword, mips::A0, mips::A0, 0);
- __ StoreToOffset(mips::kStoreHalfword, mips::A0, mips::A1, 0);
- __ StoreToOffset(mips::kStoreHalfword, mips::A0, mips::A1, 256);
- __ StoreToOffset(mips::kStoreHalfword, mips::A0, mips::A1, 1000);
- __ StoreToOffset(mips::kStoreHalfword, mips::A0, mips::A1, 0x8000);
- __ StoreToOffset(mips::kStoreHalfword, mips::A0, mips::A1, 0x10000);
- __ StoreToOffset(mips::kStoreHalfword, mips::A0, mips::A1, 0x12345678);
- __ StoreToOffset(mips::kStoreHalfword, mips::A0, mips::A1, -256);
- __ StoreToOffset(mips::kStoreHalfword, mips::A0, mips::A1, 0xFFFF8000);
- __ StoreToOffset(mips::kStoreHalfword, mips::A0, mips::A1, 0xABCDEF00);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x8000);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x7FF8);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x7FFB);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x7FFC);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x7FFF);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0xFFF0);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x8008);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x8001);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x8000);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0xFFF0);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x17FE8);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x0FFF8);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x0FFF1);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x0FFF1);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x0FFF8);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x17FE8);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x17FF0);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, -0x17FE9);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x17FE9);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x17FF0);
+ __ StoreToOffset(mips::kStoreHalfword, mips::A3, mips::A1, +0x12345678);
- __ StoreToOffset(mips::kStoreWord, mips::A0, mips::A0, 0);
- __ StoreToOffset(mips::kStoreWord, mips::A0, mips::A1, 0);
- __ StoreToOffset(mips::kStoreWord, mips::A0, mips::A1, 256);
- __ StoreToOffset(mips::kStoreWord, mips::A0, mips::A1, 1000);
- __ StoreToOffset(mips::kStoreWord, mips::A0, mips::A1, 0x8000);
- __ StoreToOffset(mips::kStoreWord, mips::A0, mips::A1, 0x10000);
- __ StoreToOffset(mips::kStoreWord, mips::A0, mips::A1, 0x12345678);
- __ StoreToOffset(mips::kStoreWord, mips::A0, mips::A1, -256);
- __ StoreToOffset(mips::kStoreWord, mips::A0, mips::A1, 0xFFFF8000);
- __ StoreToOffset(mips::kStoreWord, mips::A0, mips::A1, 0xABCDEF00);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x8000);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x7FF8);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x7FFB);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x7FFC);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x7FFF);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0xFFF0);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x8008);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x8001);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x8000);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0xFFF0);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x17FE8);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x0FFF8);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x0FFF1);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x0FFF1);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x0FFF8);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x17FE8);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x17FF0);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, -0x17FE9);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x17FE9);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x17FF0);
+ __ StoreToOffset(mips::kStoreWord, mips::A3, mips::A1, +0x12345678);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, 0);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, 256);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, 1000);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, 0x8000);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, 0x10000);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, 0x12345678);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -256);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, 0xFFFF8000);
- __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, 0xABCDEF00);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x8000);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x7FF8);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x7FFB);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x7FFC);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x7FFF);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0xFFF0);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x8008);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x8001);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x8000);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0xFFF0);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x17FE8);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x0FFF8);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x0FFF1);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x0FFF1);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x0FFF8);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x17FE8);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x17FF0);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, -0x17FE9);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x17FE9);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x17FF0);
+ __ StoreToOffset(mips::kStoreDoubleword, mips::A0, mips::A2, +0x12345678);
const char* expected =
- "sb $a0, 0($a0)\n"
- "sb $a0, 0($a1)\n"
- "sb $a0, 256($a1)\n"
- "sb $a0, 1000($a1)\n"
- "ori $at, $zero, 0x8000\n"
+ "sb $a3, -0x8000($a1)\n"
+ "sb $a3, 0($a1)\n"
+ "sb $a3, 0x7FF8($a1)\n"
+ "sb $a3, 0x7FFB($a1)\n"
+ "sb $a3, 0x7FFC($a1)\n"
+ "sb $a3, 0x7FFF($a1)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "sb $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "sb $a3, -0x10($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "sb $a3, -9($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "sb $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "sb $a3, 0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sb $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sb $a3, -8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sb $a3, -1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sb $a3, 1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sb $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sb $a3, 0x7FF8($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
- "sb $a0, 0($at)\n"
- "lui $at, 1\n"
+ "sb $a3, 0($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
- "sb $a0, 0($at)\n"
+ "sb $a3, 7($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a1\n"
+ "sb $a3, 1($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
+ "addu $at, $at, $a1\n"
+ "sb $a3, 0($at)\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
+ "ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
- "sb $a0, 0($at)\n"
- "sb $a0, -256($a1)\n"
- "sb $a0, 0xFFFF8000($a1)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
- "addu $at, $at, $a1\n"
- "sb $a0, 0($at)\n"
+ "sb $a3, 0($at)\n"
- "sh $a0, 0($a0)\n"
- "sh $a0, 0($a1)\n"
- "sh $a0, 256($a1)\n"
- "sh $a0, 1000($a1)\n"
- "ori $at, $zero, 0x8000\n"
+ "sh $a3, -0x8000($a1)\n"
+ "sh $a3, 0($a1)\n"
+ "sh $a3, 0x7FF8($a1)\n"
+ "sh $a3, 0x7FFB($a1)\n"
+ "sh $a3, 0x7FFC($a1)\n"
+ "sh $a3, 0x7FFF($a1)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "sh $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "sh $a3, -0x10($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "sh $a3, -9($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "sh $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "sh $a3, 0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sh $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sh $a3, -8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sh $a3, -1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sh $a3, 1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sh $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sh $a3, 0x7FF8($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
- "sh $a0, 0($at)\n"
- "lui $at, 1\n"
+ "sh $a3, 0($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
- "sh $a0, 0($at)\n"
+ "sh $a3, 7($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a1\n"
+ "sh $a3, 1($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
+ "addu $at, $at, $a1\n"
+ "sh $a3, 0($at)\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
+ "ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
- "sh $a0, 0($at)\n"
- "sh $a0, -256($a1)\n"
- "sh $a0, 0xFFFF8000($a1)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
- "addu $at, $at, $a1\n"
- "sh $a0, 0($at)\n"
+ "sh $a3, 0($at)\n"
- "sw $a0, 0($a0)\n"
- "sw $a0, 0($a1)\n"
- "sw $a0, 256($a1)\n"
- "sw $a0, 1000($a1)\n"
- "ori $at, $zero, 0x8000\n"
+ "sw $a3, -0x8000($a1)\n"
+ "sw $a3, 0($a1)\n"
+ "sw $a3, 0x7FF8($a1)\n"
+ "sw $a3, 0x7FFB($a1)\n"
+ "sw $a3, 0x7FFC($a1)\n"
+ "sw $a3, 0x7FFF($a1)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "sw $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "sw $a3, -0x10($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "sw $a3, -9($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "sw $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "sw $a3, 0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sw $a3, -0x7FF8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sw $a3, -8($at)\n"
+ "addiu $at, $a1, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sw $a3, -1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sw $a3, 1($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sw $a3, 8($at)\n"
+ "addiu $at, $a1, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sw $a3, 0x7FF8($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
- "sw $a0, 0($at)\n"
- "lui $at, 1\n"
+ "sw $a3, 0($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a1\n"
- "sw $a0, 0($at)\n"
+ "sw $a3, 7($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a1\n"
+ "sw $a3, 1($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
+ "addu $at, $at, $a1\n"
+ "sw $a3, 0($at)\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
+ "ori $at, $at, 0x5678\n"
"addu $at, $at, $a1\n"
- "sw $a0, 0($at)\n"
- "sw $a0, -256($a1)\n"
- "sw $a0, 0xFFFF8000($a1)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
- "addu $at, $at, $a1\n"
- "sw $a0, 0($at)\n"
+ "sw $a3, 0($at)\n"
+ "sw $a0, -0x8000($a2)\n"
+ "sw $a1, -0x7FFC($a2)\n"
"sw $a0, 0($a2)\n"
"sw $a1, 4($a2)\n"
- "sw $a0, 256($a2)\n"
- "sw $a1, 260($a2)\n"
- "sw $a0, 1000($a2)\n"
- "sw $a1, 1004($a2)\n"
- "ori $at, $zero, 0x8000\n"
+ "sw $a0, 0x7FF8($a2)\n"
+ "sw $a1, 0x7FFC($a2)\n"
+ "sw $a0, 0x7FFB($a2)\n"
+ "sw $a1, 0x7FFF($a2)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "sw $a0, 4($at)\n"
+ "sw $a1, 8($at)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "sw $a0, 7($at)\n"
+ "sw $a1, 11($at)\n"
+ "addiu $at, $a2, -0x7FF8\n"
+ "sw $a0, -0x7FF8($at)\n"
+ "sw $a1, -0x7FF4($at)\n"
+ "addiu $at, $a2, -0x7FF8\n"
+ "sw $a0, -0x10($at)\n"
+ "sw $a1, -0xC($at)\n"
+ "addiu $at, $a2, -0x7FF8\n"
+ "sw $a0, -9($at)\n"
+ "sw $a1, -5($at)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "sw $a0, 8($at)\n"
+ "sw $a1, 12($at)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "sw $a0, 0x7FF8($at)\n"
+ "sw $a1, 0x7FFC($at)\n"
+ "addiu $at, $a2, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sw $a0, -0x7FF8($at)\n"
+ "sw $a1, -0x7FF4($at)\n"
+ "addiu $at, $a2, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sw $a0, -8($at)\n"
+ "sw $a1, -4($at)\n"
+ "addiu $at, $a2, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sw $a0, -1($at)\n"
+ "sw $a1, 3($at)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sw $a0, 1($at)\n"
+ "sw $a1, 5($at)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sw $a0, 8($at)\n"
+ "sw $a1, 12($at)\n"
+ "addiu $at, $a2, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sw $a0, 0x7FF8($at)\n"
+ "sw $a1, 0x7FFC($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a2\n"
"sw $a0, 0($at)\n"
"sw $a1, 4($at)\n"
- "lui $at, 1\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
+ "addu $at, $at, $a2\n"
+ "sw $a0, 7($at)\n"
+ "sw $a1, 11($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a2\n"
+ "sw $a0, 1($at)\n"
+ "sw $a1, 5($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a2\n"
"sw $a0, 0($at)\n"
"sw $a1, 4($at)\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
- "addu $at, $at, $a2\n"
- "sw $a0, 0($at)\n"
- "sw $a1, 4($at)\n"
- "sw $a0, -256($a2)\n"
- "sw $a1, -252($a2)\n"
- "sw $a0, 0xFFFF8000($a2)\n"
- "sw $a1, 0xFFFF8004($a2)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
+ "ori $at, $at, 0x5678\n"
"addu $at, $at, $a2\n"
"sw $a0, 0($at)\n"
"sw $a1, 4($at)\n";
@@ -1153,69 +1784,174 @@
}
TEST_F(AssemblerMIPSTest, StoreSToOffset) {
- __ StoreSToOffset(mips::F0, mips::A0, 0);
- __ StoreSToOffset(mips::F0, mips::A0, 4);
- __ StoreSToOffset(mips::F0, mips::A0, 256);
- __ StoreSToOffset(mips::F0, mips::A0, 0x8000);
- __ StoreSToOffset(mips::F0, mips::A0, 0x10000);
- __ StoreSToOffset(mips::F0, mips::A0, 0x12345678);
- __ StoreSToOffset(mips::F0, mips::A0, -256);
- __ StoreSToOffset(mips::F0, mips::A0, 0xFFFF8000);
- __ StoreSToOffset(mips::F0, mips::A0, 0xABCDEF00);
+ __ StoreSToOffset(mips::F2, mips::A0, -0x8000);
+ __ StoreSToOffset(mips::F2, mips::A0, +0);
+ __ StoreSToOffset(mips::F2, mips::A0, +0x7FF8);
+ __ StoreSToOffset(mips::F2, mips::A0, +0x7FFB);
+ __ StoreSToOffset(mips::F2, mips::A0, +0x7FFC);
+ __ StoreSToOffset(mips::F2, mips::A0, +0x7FFF);
+ __ StoreSToOffset(mips::F2, mips::A0, -0xFFF0);
+ __ StoreSToOffset(mips::F2, mips::A0, -0x8008);
+ __ StoreSToOffset(mips::F2, mips::A0, -0x8001);
+ __ StoreSToOffset(mips::F2, mips::A0, +0x8000);
+ __ StoreSToOffset(mips::F2, mips::A0, +0xFFF0);
+ __ StoreSToOffset(mips::F2, mips::A0, -0x17FE8);
+ __ StoreSToOffset(mips::F2, mips::A0, -0x0FFF8);
+ __ StoreSToOffset(mips::F2, mips::A0, -0x0FFF1);
+ __ StoreSToOffset(mips::F2, mips::A0, +0x0FFF1);
+ __ StoreSToOffset(mips::F2, mips::A0, +0x0FFF8);
+ __ StoreSToOffset(mips::F2, mips::A0, +0x17FE8);
+ __ StoreSToOffset(mips::F2, mips::A0, -0x17FF0);
+ __ StoreSToOffset(mips::F2, mips::A0, -0x17FE9);
+ __ StoreSToOffset(mips::F2, mips::A0, +0x17FE9);
+ __ StoreSToOffset(mips::F2, mips::A0, +0x17FF0);
+ __ StoreSToOffset(mips::F2, mips::A0, +0x12345678);
const char* expected =
- "swc1 $f0, 0($a0)\n"
- "swc1 $f0, 4($a0)\n"
- "swc1 $f0, 256($a0)\n"
- "ori $at, $zero, 0x8000\n"
+ "swc1 $f2, -0x8000($a0)\n"
+ "swc1 $f2, 0($a0)\n"
+ "swc1 $f2, 0x7FF8($a0)\n"
+ "swc1 $f2, 0x7FFB($a0)\n"
+ "swc1 $f2, 0x7FFC($a0)\n"
+ "swc1 $f2, 0x7FFF($a0)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "swc1 $f2, -0x7FF8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "swc1 $f2, -0x10($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "swc1 $f2, -9($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "swc1 $f2, 8($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "swc1 $f2, 0x7FF8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "swc1 $f2, -0x7FF8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "swc1 $f2, -8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "swc1 $f2, -1($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "swc1 $f2, 1($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "swc1 $f2, 8($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "swc1 $f2, 0x7FF8($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
- "swc1 $f0, 0($at)\n"
- "lui $at, 1\n"
+ "swc1 $f2, 0($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
- "swc1 $f0, 0($at)\n"
+ "swc1 $f2, 7($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a0\n"
+ "swc1 $f2, 1($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
+ "addu $at, $at, $a0\n"
+ "swc1 $f2, 0($at)\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
+ "ori $at, $at, 0x5678\n"
"addu $at, $at, $a0\n"
- "swc1 $f0, 0($at)\n"
- "swc1 $f0, -256($a0)\n"
- "swc1 $f0, 0xFFFF8000($a0)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
- "addu $at, $at, $a0\n"
- "swc1 $f0, 0($at)\n";
+ "swc1 $f2, 0($at)\n";
DriverStr(expected, "StoreSToOffset");
}
TEST_F(AssemblerMIPSTest, StoreDToOffset) {
- __ StoreDToOffset(mips::F0, mips::A0, 0);
- __ StoreDToOffset(mips::F0, mips::A0, 4);
- __ StoreDToOffset(mips::F0, mips::A0, 256);
- __ StoreDToOffset(mips::F0, mips::A0, 0x8000);
- __ StoreDToOffset(mips::F0, mips::A0, 0x10000);
- __ StoreDToOffset(mips::F0, mips::A0, 0x12345678);
- __ StoreDToOffset(mips::F0, mips::A0, -256);
- __ StoreDToOffset(mips::F0, mips::A0, 0xFFFF8000);
- __ StoreDToOffset(mips::F0, mips::A0, 0xABCDEF00);
+ __ StoreDToOffset(mips::F0, mips::A0, -0x8000);
+ __ StoreDToOffset(mips::F0, mips::A0, +0);
+ __ StoreDToOffset(mips::F0, mips::A0, +0x7FF8);
+ __ StoreDToOffset(mips::F0, mips::A0, +0x7FFB);
+ __ StoreDToOffset(mips::F0, mips::A0, +0x7FFC);
+ __ StoreDToOffset(mips::F0, mips::A0, +0x7FFF);
+ __ StoreDToOffset(mips::F0, mips::A0, -0xFFF0);
+ __ StoreDToOffset(mips::F0, mips::A0, -0x8008);
+ __ StoreDToOffset(mips::F0, mips::A0, -0x8001);
+ __ StoreDToOffset(mips::F0, mips::A0, +0x8000);
+ __ StoreDToOffset(mips::F0, mips::A0, +0xFFF0);
+ __ StoreDToOffset(mips::F0, mips::A0, -0x17FE8);
+ __ StoreDToOffset(mips::F0, mips::A0, -0x0FFF8);
+ __ StoreDToOffset(mips::F0, mips::A0, -0x0FFF1);
+ __ StoreDToOffset(mips::F0, mips::A0, +0x0FFF1);
+ __ StoreDToOffset(mips::F0, mips::A0, +0x0FFF8);
+ __ StoreDToOffset(mips::F0, mips::A0, +0x17FE8);
+ __ StoreDToOffset(mips::F0, mips::A0, -0x17FF0);
+ __ StoreDToOffset(mips::F0, mips::A0, -0x17FE9);
+ __ StoreDToOffset(mips::F0, mips::A0, +0x17FE9);
+ __ StoreDToOffset(mips::F0, mips::A0, +0x17FF0);
+ __ StoreDToOffset(mips::F0, mips::A0, +0x12345678);
const char* expected =
+ "sdc1 $f0, -0x8000($a0)\n"
"sdc1 $f0, 0($a0)\n"
- "swc1 $f0, 4($a0)\n"
- "swc1 $f1, 8($a0)\n"
- "sdc1 $f0, 256($a0)\n"
- "ori $at, $zero, 0x8000\n"
+ "sdc1 $f0, 0x7FF8($a0)\n"
+ "swc1 $f0, 0x7FFB($a0)\n"
+ "swc1 $f1, 0x7FFF($a0)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "swc1 $f0, 4($at)\n"
+ "swc1 $f1, 8($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "swc1 $f0, 7($at)\n"
+ "swc1 $f1, 11($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "sdc1 $f0, -0x7FF8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "sdc1 $f0, -0x10($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "swc1 $f0, -9($at)\n"
+ "swc1 $f1, -5($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "sdc1 $f0, 8($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "sdc1 $f0, 0x7FF8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sdc1 $f0, -0x7FF8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "sdc1 $f0, -8($at)\n"
+ "addiu $at, $a0, -0x7FF8\n"
+ "addiu $at, $at, -0x7FF8\n"
+ "swc1 $f0, -1($at)\n"
+ "swc1 $f1, 3($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "swc1 $f0, 1($at)\n"
+ "swc1 $f1, 5($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sdc1 $f0, 8($at)\n"
+ "addiu $at, $a0, 0x7FF8\n"
+ "addiu $at, $at, 0x7FF8\n"
+ "sdc1 $f0, 0x7FF8($at)\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
"addu $at, $at, $a0\n"
"sdc1 $f0, 0($at)\n"
- "lui $at, 1\n"
+ "lui $at, 0xFFFE\n"
+ "ori $at, $at, 0x8010\n"
+ "addu $at, $at, $a0\n"
+ "swc1 $f0, 7($at)\n"
+ "swc1 $f1, 11($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FE8\n"
+ "addu $at, $at, $a0\n"
+ "swc1 $f0, 1($at)\n"
+ "swc1 $f1, 5($at)\n"
+ "lui $at, 0x1\n"
+ "ori $at, $at, 0x7FF0\n"
"addu $at, $at, $a0\n"
"sdc1 $f0, 0($at)\n"
"lui $at, 0x1234\n"
- "ori $at, 0x5678\n"
- "addu $at, $at, $a0\n"
- "sdc1 $f0, 0($at)\n"
- "sdc1 $f0, -256($a0)\n"
- "sdc1 $f0, 0xFFFF8000($a0)\n"
- "lui $at, 0xABCD\n"
- "ori $at, 0xEF00\n"
+ "ori $at, $at, 0x5678\n"
"addu $at, $at, $a0\n"
"sdc1 $f0, 0($at)\n";
DriverStr(expected, "StoreDToOffset");
diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h
index 98d3345..a102858 100644
--- a/runtime/art_field-inl.h
+++ b/runtime/art_field-inl.h
@@ -33,9 +33,10 @@
namespace art {
+template<ReadBarrierOption kReadBarrierOption>
inline mirror::Class* ArtField::GetDeclaringClass() {
GcRootSource gc_root_source(this);
- mirror::Class* result = declaring_class_.Read(&gc_root_source);
+ mirror::Class* result = declaring_class_.Read<kReadBarrierOption>(&gc_root_source);
DCHECK(result != nullptr);
DCHECK(result->IsLoaded() || result->IsErroneous()) << result->GetStatus();
return result;
diff --git a/runtime/art_field.h b/runtime/art_field.h
index b64b70f..aaccbf3 100644
--- a/runtime/art_field.h
+++ b/runtime/art_field.h
@@ -41,6 +41,7 @@
public:
ArtField();
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
mirror::Class* GetDeclaringClass() SHARED_REQUIRES(Locks::mutator_lock_);
void SetDeclaringClass(mirror::Class *new_declaring_class)
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 7647ad6..26450c4 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -395,8 +395,9 @@
return GetDeclaringClass()->GetDexCache();
}
+template<ReadBarrierOption kReadBarrierOption>
inline bool ArtMethod::IsProxyMethod() {
- return GetDeclaringClass()->IsProxyClass();
+ return GetDeclaringClass<kReadBarrierOption>()->IsProxyClass();
}
inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy(size_t pointer_size) {
@@ -438,24 +439,24 @@
return type;
}
-template<typename RootVisitorType>
+template<ReadBarrierOption kReadBarrierOption, typename RootVisitorType>
void ArtMethod::VisitRoots(RootVisitorType& visitor, size_t pointer_size) {
- ArtMethod* interface_method = nullptr;
- mirror::Class* klass = declaring_class_.Read();
- if (LIKELY(klass != nullptr)) {
+ if (LIKELY(!declaring_class_.IsNull())) {
+ visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
+ mirror::Class* klass = declaring_class_.Read<kReadBarrierOption>();
if (UNLIKELY(klass->IsProxyClass())) {
// For normal methods, dex cache shortcuts will be visited through the declaring class.
// However, for proxies we need to keep the interface method alive, so we visit its roots.
- interface_method = mirror::DexCache::GetElementPtrSize(
+ ArtMethod* interface_method = mirror::DexCache::GetElementPtrSize(
GetDexCacheResolvedMethods(pointer_size),
GetDexMethodIndex(),
pointer_size);
DCHECK(interface_method != nullptr);
DCHECK_EQ(interface_method,
- Runtime::Current()->GetClassLinker()->FindMethodForProxy(klass, this));
+ Runtime::Current()->GetClassLinker()->FindMethodForProxy<kReadBarrierOption>(
+ klass, this));
interface_method->VisitRoots(visitor, pointer_size);
}
- visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
// We know we don't have profiling information if the class hasn't been verified. Note
// that this check also ensures the IsNative call can be made, as IsNative expects a fully
// created class (and not a retired one).
@@ -463,7 +464,7 @@
// Runtime methods and native methods use the same field as the profiling info for
// storing their own data (jni entrypoint for native methods, and ImtConflictTable for
// some runtime methods).
- if (!IsNative() && !IsRuntimeMethod()) {
+ if (!IsNative<kReadBarrierOption>() && !IsRuntimeMethod()) {
ProfilingInfo* profiling_info = GetProfilingInfo(pointer_size);
if (profiling_info != nullptr) {
profiling_info->VisitRoots(visitor);
diff --git a/runtime/art_method.h b/runtime/art_method.h
index a012a5a..2b025f8 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -340,6 +340,7 @@
return (GetAccessFlags() & kAccSynthetic) != 0;
}
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
bool IsProxyMethod() SHARED_REQUIRES(Locks::mutator_lock_);
bool SkipAccessChecks() {
@@ -564,7 +565,7 @@
SHARED_REQUIRES(Locks::mutator_lock_);
// NO_THREAD_SAFETY_ANALYSIS since we don't know what the callback requires.
- template<typename RootVisitorType>
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier, typename RootVisitorType>
void VisitRoots(RootVisitorType& visitor, size_t pointer_size) NO_THREAD_SAFETY_ANALYSIS;
const DexFile* GetDexFile() SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index 8eb3742..480644a 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -128,7 +128,7 @@
art::Thread::SelfOffset<__SIZEOF_POINTER__>().Int32Value())
// Offset of field Thread::tlsPtr_.thread_local_objects.
-#define THREAD_LOCAL_OBJECTS_OFFSET (THREAD_CARD_TABLE_OFFSET + 168 * __SIZEOF_POINTER__)
+#define THREAD_LOCAL_OBJECTS_OFFSET (THREAD_CARD_TABLE_OFFSET + 166 * __SIZEOF_POINTER__)
ADD_TEST_EQ(THREAD_LOCAL_OBJECTS_OFFSET,
art::Thread::ThreadLocalObjectsOffset<__SIZEOF_POINTER__>().Int32Value())
// Offset of field Thread::tlsPtr_.thread_local_pos.
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index f3e260b..f2575f7 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -225,6 +225,34 @@
return klass;
}
+template<ReadBarrierOption kReadBarrierOption>
+ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class, ArtMethod* proxy_method) {
+ DCHECK(proxy_class->IsProxyClass());
+ DCHECK(proxy_method->IsProxyMethod<kReadBarrierOption>());
+ {
+ Thread* const self = Thread::Current();
+ ReaderMutexLock mu(self, dex_lock_);
+ // Locate the dex cache of the original interface/Object
+ for (const DexCacheData& data : dex_caches_) {
+ if (!self->IsJWeakCleared(data.weak_root) &&
+ proxy_method->HasSameDexCacheResolvedTypes(data.resolved_types,
+ image_pointer_size_)) {
+ mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(
+ self->DecodeJObject(data.weak_root));
+ if (dex_cache != nullptr) {
+ ArtMethod* resolved_method = dex_cache->GetResolvedMethod(
+ proxy_method->GetDexMethodIndex(), image_pointer_size_);
+ CHECK(resolved_method != nullptr);
+ return resolved_method;
+ }
+ }
+ }
+ }
+ LOG(FATAL) << "Didn't find dex cache for " << PrettyClass(proxy_class) << " "
+ << PrettyMethod(proxy_method);
+ UNREACHABLE();
+}
+
} // namespace art
#endif // ART_RUNTIME_CLASS_LINKER_INL_H_
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index db0e9ac..fe7448f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4280,33 +4280,6 @@
return DotToDescriptor(name->ToModifiedUtf8().c_str());
}
-ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class, ArtMethod* proxy_method) {
- DCHECK(proxy_class->IsProxyClass());
- DCHECK(proxy_method->IsProxyMethod());
- {
- Thread* const self = Thread::Current();
- ReaderMutexLock mu(self, dex_lock_);
- // Locate the dex cache of the original interface/Object
- for (const DexCacheData& data : dex_caches_) {
- if (!self->IsJWeakCleared(data.weak_root) &&
- proxy_method->HasSameDexCacheResolvedTypes(data.resolved_types,
- image_pointer_size_)) {
- mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(
- self->DecodeJObject(data.weak_root));
- if (dex_cache != nullptr) {
- ArtMethod* resolved_method = dex_cache->GetResolvedMethod(
- proxy_method->GetDexMethodIndex(), image_pointer_size_);
- CHECK(resolved_method != nullptr);
- return resolved_method;
- }
- }
- }
- }
- LOG(FATAL) << "Didn't find dex cache for " << PrettyClass(proxy_class) << " "
- << PrettyMethod(proxy_method);
- UNREACHABLE();
-}
-
void ClassLinker::CreateProxyConstructor(Handle<mirror::Class> klass, ArtMethod* out) {
// Create constructor for Proxy that must initialize the method.
CHECK_EQ(GetClassRoot(kJavaLangReflectProxy)->NumDirectMethods(), 18u);
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index cd1ca7f..ca5af19 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -483,6 +483,7 @@
SHARED_REQUIRES(Locks::mutator_lock_);
std::string GetDescriptorForProxy(mirror::Class* proxy_class)
SHARED_REQUIRES(Locks::mutator_lock_);
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
ArtMethod* FindMethodForProxy(mirror::Class* proxy_class, ArtMethod* proxy_method)
REQUIRES(!dex_lock_)
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc
index c621672..91deea0 100644
--- a/runtime/entrypoints_order_test.cc
+++ b/runtime/entrypoints_order_test.cc
@@ -112,10 +112,12 @@
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, name, pthread_self, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, pthread_self, last_no_thread_suspension_cause,
sizeof(void*));
- EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, last_no_thread_suspension_cause, checkpoint_functions,
+ EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, last_no_thread_suspension_cause, checkpoint_function,
sizeof(void*));
- EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, checkpoint_functions, jni_entrypoints,
- sizeof(void*) * 6);
+ EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, checkpoint_function, active_suspend_barriers,
+ sizeof(void*));
+ EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, active_suspend_barriers, jni_entrypoints,
+ sizeof(Thread::tls_ptr_sized_values::active_suspend_barriers));
// Skip across the entrypoints structures.
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index fcdfc88..cefd9f0 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -532,7 +532,7 @@
inline MemberOffset Class::GetFirstReferenceInstanceFieldOffset() {
Class* super_class = GetSuperClass<kVerifyFlags, kReadBarrierOption>();
return (super_class != nullptr)
- ? MemberOffset(RoundUp(super_class->GetObjectSize(),
+ ? MemberOffset(RoundUp(super_class->GetObjectSize<kVerifyFlags, kReadBarrierOption>(),
sizeof(mirror::HeapReference<mirror::Object>)))
: ClassOffset();
}
@@ -778,7 +778,8 @@
}
if (kVisitNativeRoots) {
// Since this class is reachable, we must also visit the associated roots when we scan it.
- VisitNativeRoots(visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
+ VisitNativeRoots<kReadBarrierOption>(
+ visitor, Runtime::Current()->GetClassLinker()->GetImagePointerSize());
}
}
@@ -917,24 +918,24 @@
return GetFieldPtr<GcRoot<String>*>(DexCacheStringsOffset());
}
-template<class Visitor>
+template<ReadBarrierOption kReadBarrierOption, class Visitor>
void mirror::Class::VisitNativeRoots(Visitor& visitor, size_t pointer_size) {
for (ArtField& field : GetSFieldsUnchecked()) {
// Visit roots first in case the declaring class gets moved.
field.VisitRoots(visitor);
if (kIsDebugBuild && IsResolved()) {
- CHECK_EQ(field.GetDeclaringClass(), this) << GetStatus();
+ CHECK_EQ(field.GetDeclaringClass<kReadBarrierOption>(), this) << GetStatus();
}
}
for (ArtField& field : GetIFieldsUnchecked()) {
// Visit roots first in case the declaring class gets moved.
field.VisitRoots(visitor);
if (kIsDebugBuild && IsResolved()) {
- CHECK_EQ(field.GetDeclaringClass(), this) << GetStatus();
+ CHECK_EQ(field.GetDeclaringClass<kReadBarrierOption>(), this) << GetStatus();
}
}
for (ArtMethod& method : GetMethods(pointer_size)) {
- method.VisitRoots(visitor, pointer_size);
+ method.VisitRoots<kReadBarrierOption>(visitor, pointer_size);
}
}
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 8c20fa6..5235a3e 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1156,7 +1156,7 @@
// Visit native roots visits roots which are keyed off the native pointers such as ArtFields and
// ArtMethods.
- template<class Visitor>
+ template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier, class Visitor>
void VisitNativeRoots(Visitor& visitor, size_t pointer_size)
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h
index 2894b68..0b3461f 100644
--- a/runtime/mirror/dex_cache-inl.h
+++ b/runtime/mirror/dex_cache-inl.h
@@ -55,7 +55,6 @@
inline void DexCache::SetResolvedType(uint32_t type_idx, Class* resolved) {
DCHECK_LT(type_idx, NumResolvedTypes()); // NOTE: Unchecked, i.e. not throwing AIOOB.
// TODO default transaction support.
- DCHECK(resolved == nullptr || !resolved->IsErroneous());
GetResolvedTypes()[type_idx] = GcRoot<Class>(resolved);
// TODO: Fine-grained marking, so that we don't need to go through all arrays in full.
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(this);
diff --git a/runtime/oat.h b/runtime/oat.h
index 57675dc..286394e 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,7 +32,7 @@
class PACKED(4) OatHeader {
public:
static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
- static constexpr uint8_t kOatVersion[] = { '0', '7', '9', '\0' };
+ static constexpr uint8_t kOatVersion[] = { '0', '8', '0', '\0' };
static constexpr const char* kImageLocationKey = "image-location";
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/thread.cc b/runtime/thread.cc
index f1f4a12..28f863e 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1122,32 +1122,36 @@
}
void Thread::RunCheckpointFunction() {
- Closure *checkpoints[kMaxCheckpoints];
-
- // Grab the suspend_count lock and copy the current set of
- // checkpoints. Then clear the list and the flag. The RequestCheckpoint
- // function will also grab this lock so we prevent a race between setting
- // the kCheckpointRequest flag and clearing it.
- {
- MutexLock mu(this, *Locks::thread_suspend_count_lock_);
- for (uint32_t i = 0; i < kMaxCheckpoints; ++i) {
- checkpoints[i] = tlsPtr_.checkpoint_functions[i];
- tlsPtr_.checkpoint_functions[i] = nullptr;
+ bool done = false;
+ do {
+ // Grab the suspend_count lock and copy the checkpoints one by one. When the last checkpoint is
+ // copied, clear the list and the flag. The RequestCheckpoint function will also grab this lock
+ // to prevent a race between setting the kCheckpointRequest flag and clearing it.
+ Closure* checkpoint = nullptr;
+ {
+ MutexLock mu(this, *Locks::thread_suspend_count_lock_);
+ if (tlsPtr_.checkpoint_function != nullptr) {
+ checkpoint = tlsPtr_.checkpoint_function;
+ if (!checkpoint_overflow_.empty()) {
+ // Overflow list not empty, copy the first one out and continue.
+ tlsPtr_.checkpoint_function = checkpoint_overflow_.front();
+ checkpoint_overflow_.pop_front();
+ } else {
+ // No overflow checkpoints, this means that we are on the last pending checkpoint.
+ tlsPtr_.checkpoint_function = nullptr;
+ AtomicClearFlag(kCheckpointRequest);
+ done = true;
+ }
+ } else {
+ LOG(FATAL) << "Checkpoint flag set without pending checkpoint";
+ }
}
- AtomicClearFlag(kCheckpointRequest);
- }
- // Outside the lock, run all the checkpoint functions that
- // we collected.
- bool found_checkpoint = false;
- for (uint32_t i = 0; i < kMaxCheckpoints; ++i) {
- if (checkpoints[i] != nullptr) {
- ScopedTrace trace("Run checkpoint function");
- checkpoints[i]->Run(this);
- found_checkpoint = true;
- }
- }
- CHECK(found_checkpoint);
+ // Outside the lock, run the checkpoint functions that we collected.
+ ScopedTrace trace("Run checkpoint function");
+ DCHECK(checkpoint != nullptr);
+ checkpoint->Run(this);
+ } while (!done);
}
bool Thread::RequestCheckpoint(Closure* function) {
@@ -1157,20 +1161,6 @@
return false; // Fail, thread is suspended and so can't run a checkpoint.
}
- uint32_t available_checkpoint = kMaxCheckpoints;
- for (uint32_t i = 0 ; i < kMaxCheckpoints; ++i) {
- if (tlsPtr_.checkpoint_functions[i] == nullptr) {
- available_checkpoint = i;
- break;
- }
- }
- if (available_checkpoint == kMaxCheckpoints) {
- // No checkpoint functions available, we can't run a checkpoint
- return false;
- }
- tlsPtr_.checkpoint_functions[available_checkpoint] = function;
-
- // Checkpoint function installed now install flag bit.
// We must be runnable to request a checkpoint.
DCHECK_EQ(old_state_and_flags.as_struct.state, kRunnable);
union StateAndFlags new_state_and_flags;
@@ -1178,11 +1168,13 @@
new_state_and_flags.as_struct.flags |= kCheckpointRequest;
bool success = tls32_.state_and_flags.as_atomic_int.CompareExchangeStrongSequentiallyConsistent(
old_state_and_flags.as_int, new_state_and_flags.as_int);
- if (UNLIKELY(!success)) {
- // The thread changed state before the checkpoint was installed.
- CHECK_EQ(tlsPtr_.checkpoint_functions[available_checkpoint], function);
- tlsPtr_.checkpoint_functions[available_checkpoint] = nullptr;
- } else {
+ if (success) {
+ // Succeeded setting checkpoint flag, now insert the actual checkpoint.
+ if (tlsPtr_.checkpoint_function == nullptr) {
+ tlsPtr_.checkpoint_function = function;
+ } else {
+ checkpoint_overflow_.push_back(function);
+ }
CHECK_EQ(ReadFlag(kCheckpointRequest), true);
TriggerSuspend();
}
@@ -1624,9 +1616,7 @@
std::fill(tlsPtr_.rosalloc_runs,
tlsPtr_.rosalloc_runs + kNumRosAllocThreadLocalSizeBracketsInThread,
gc::allocator::RosAlloc::GetDedicatedFullRun());
- for (uint32_t i = 0; i < kMaxCheckpoints; ++i) {
- tlsPtr_.checkpoint_functions[i] = nullptr;
- }
+ tlsPtr_.checkpoint_function = nullptr;
for (uint32_t i = 0; i < kMaxSuspendBarriers; ++i) {
tlsPtr_.active_suspend_barriers[i] = nullptr;
}
@@ -1767,9 +1757,8 @@
}
CHECK_NE(GetState(), kRunnable);
CHECK_NE(ReadFlag(kCheckpointRequest), true);
- CHECK(tlsPtr_.checkpoint_functions[0] == nullptr);
- CHECK(tlsPtr_.checkpoint_functions[1] == nullptr);
- CHECK(tlsPtr_.checkpoint_functions[2] == nullptr);
+ CHECK(tlsPtr_.checkpoint_function == nullptr);
+ CHECK_EQ(checkpoint_overflow_.size(), 0u);
CHECK(tlsPtr_.flip_function == nullptr);
CHECK_EQ(tls32_.suspended_at_suspend_check, false);
diff --git a/runtime/thread.h b/runtime/thread.h
index 3c367ee..7ae9be5 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -1220,9 +1220,6 @@
static void ThreadExitCallback(void* arg);
- // Maximum number of checkpoint functions.
- static constexpr uint32_t kMaxCheckpoints = 3;
-
// Maximum number of suspend barriers.
static constexpr uint32_t kMaxSuspendBarriers = 3;
@@ -1452,9 +1449,9 @@
// If no_thread_suspension_ is > 0, what is causing that assertion.
const char* last_no_thread_suspension_cause;
- // Pending checkpoint function or null if non-pending. Installation guarding by
- // Locks::thread_suspend_count_lock_.
- Closure* checkpoint_functions[kMaxCheckpoints];
+ // Pending checkpoint function or null if non-pending. If this checkpoint is set and someone\
+ // requests another checkpoint, it goes to the checkpoint overflow list.
+ Closure* checkpoint_function GUARDED_BY(Locks::thread_suspend_count_lock_);
// Pending barriers that require passing or NULL if non-pending. Installation guarding by
// Locks::thread_suspend_count_lock_.
@@ -1517,6 +1514,9 @@
// Debug disable read barrier count, only is checked for debug builds and only in the runtime.
uint8_t debug_disallow_read_barrier_ = 0;
+ // Pending extra checkpoints if checkpoint_function_ is already used.
+ std::list<Closure*> checkpoint_overflow_ GUARDED_BY(Locks::thread_suspend_count_lock_);
+
friend class Dbg; // For SetStateUnsafe.
friend class gc::collector::SemiSpace; // For getting stack traces.
friend class Runtime; // For CreatePeer.
diff --git a/test/149-suspend-all-stress/check b/test/149-suspend-all-stress/check
new file mode 100755
index 0000000..d30b888
--- /dev/null
+++ b/test/149-suspend-all-stress/check
@@ -0,0 +1,18 @@
+#!/bin/bash
+#
+# Copyright (C) 2016 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.
+
+# Only compare the last line.
+tail -n 1 "$2" | diff --strip-trailing-cr -q "$1" - >/dev/null
\ No newline at end of file
diff --git a/test/149-suspend-all-stress/expected.txt b/test/149-suspend-all-stress/expected.txt
index f993efc..134d8d0 100644
--- a/test/149-suspend-all-stress/expected.txt
+++ b/test/149-suspend-all-stress/expected.txt
@@ -1,2 +1 @@
-JNI_OnLoad called
Finishing
diff --git a/test/149-suspend-all-stress/src/Main.java b/test/149-suspend-all-stress/src/Main.java
index aa94fc9..6a27c4b 100644
--- a/test/149-suspend-all-stress/src/Main.java
+++ b/test/149-suspend-all-stress/src/Main.java
@@ -17,7 +17,7 @@
import java.util.Map;
public class Main implements Runnable {
- static final int numberOfThreads = 4;
+ static final int numberOfThreads = 8;
public static void main(String[] args) throws Exception {
System.loadLibrary(args[0]);
diff --git a/test/149-suspend-all-stress/suspend_all.cc b/test/149-suspend-all-stress/suspend_all.cc
index de479a5..5d2be08 100644
--- a/test/149-suspend-all-stress/suspend_all.cc
+++ b/test/149-suspend-all-stress/suspend_all.cc
@@ -22,7 +22,7 @@
extern "C" JNIEXPORT void JNICALL Java_Main_suspendAndResume(JNIEnv*, jclass) {
static constexpr size_t kInitialSleepUS = 100 * 1000; // 100ms.
- static constexpr size_t kIterations = 500;
+ static constexpr size_t kIterations = 250;
usleep(kInitialSleepUS); // Leave some time for threads to get in here before we start suspending.
enum Operation {
kOPSuspendAll,
diff --git a/test/570-checker-select/src/Main.java b/test/570-checker-select/src/Main.java
index 59741d6..e0a76ca 100644
--- a/test/570-checker-select/src/Main.java
+++ b/test/570-checker-select/src/Main.java
@@ -16,6 +16,8 @@
public class Main {
+ static boolean doThrow = false;
+
/// CHECK-START: int Main.BoolCond_IntVarVar(boolean, int, int) register (after)
/// CHECK: Select [{{i\d+}},{{i\d+}},{{z\d+}}]
@@ -35,6 +37,10 @@
/// CHECK: cmovnz/ne
public static int BoolCond_IntVarVar(boolean cond, int x, int y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return cond ? x : y;
}
@@ -57,6 +63,10 @@
/// CHECK: cmovnz/ne
public static int BoolCond_IntVarCst(boolean cond, int x) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return cond ? x : 1;
}
@@ -79,6 +89,10 @@
/// CHECK: cmovnz/ne
public static int BoolCond_IntCstVar(boolean cond, int y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return cond ? 1 : y;
}
@@ -102,6 +116,10 @@
/// CHECK-NEXT: cmovnz/ne
public static long BoolCond_LongVarVar(boolean cond, long x, long y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return cond ? x : y;
}
@@ -125,6 +143,10 @@
/// CHECK-NEXT: cmovnz/ne
public static long BoolCond_LongVarCst(boolean cond, long x) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return cond ? x : 1L;
}
@@ -148,6 +170,10 @@
/// CHECK-NEXT: cmovnz/ne
public static long BoolCond_LongCstVar(boolean cond, long y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return cond ? 1L : y;
}
@@ -160,6 +186,10 @@
/// CHECK-NEXT: fcsel ne
public static float BoolCond_FloatVarVar(boolean cond, float x, float y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return cond ? x : y;
}
@@ -172,6 +202,10 @@
/// CHECK-NEXT: fcsel ne
public static float BoolCond_FloatVarCst(boolean cond, float x) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return cond ? x : 1.0f;
}
@@ -184,6 +218,10 @@
/// CHECK-NEXT: fcsel ne
public static float BoolCond_FloatCstVar(boolean cond, float y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return cond ? 1.0f : y;
}
@@ -207,6 +245,10 @@
/// CHECK: cmovle/ng
public static int IntNonmatCond_IntVarVar(int a, int b, int x, int y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return a > b ? x : y;
}
@@ -233,6 +275,10 @@
/// CHECK: cmovle/ng
public static int IntMatCond_IntVarVar(int a, int b, int x, int y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
int result = (a > b ? x : y);
return result + (a > b ? 0 : 1);
}
@@ -258,6 +304,10 @@
/// CHECK-NEXT: cmovle/ng
public static long IntNonmatCond_LongVarVar(int a, int b, long x, long y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return a > b ? x : y;
}
@@ -291,6 +341,10 @@
/// CHECK-NEXT: cmovnz/ne
public static long IntMatCond_LongVarVar(int a, int b, long x, long y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
long result = (a > b ? x : y);
return result + (a > b ? 0L : 1L);
}
@@ -310,6 +364,10 @@
/// CHECK: cmovle/ngq
public static long LongNonmatCond_LongVarVar(long a, long b, long x, long y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return a > b ? x : y;
}
@@ -334,6 +392,10 @@
/// CHECK: cmovnz/neq
public static long LongMatCond_LongVarVar(long a, long b, long x, long y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
long result = (a > b ? x : y);
return result + (a > b ? 0L : 1L);
}
@@ -349,6 +411,10 @@
/// CHECK-NEXT: csel le
public static int FloatLtNonmatCond_IntVarVar(float a, float b, int x, int y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return a > b ? x : y;
}
@@ -363,6 +429,10 @@
/// CHECK-NEXT: csel hs
public static int FloatGtNonmatCond_IntVarVar(float a, float b, int x, int y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return a < b ? x : y;
}
@@ -377,6 +447,10 @@
/// CHECK-NEXT: fcsel hs
public static float FloatGtNonmatCond_FloatVarVar(float a, float b, float x, float y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
return a < b ? x : y;
}
@@ -393,6 +467,10 @@
/// CHECK-NEXT: csel le
public static int FloatLtMatCond_IntVarVar(float a, float b, int x, int y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
int result = (a > b ? x : y);
return result + (a > b ? 0 : 1);
}
@@ -410,6 +488,10 @@
/// CHECK-NEXT: csel hs
public static int FloatGtMatCond_IntVarVar(float a, float b, int x, int y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
int result = (a < b ? x : y);
return result + (a < b ? 0 : 1);
}
@@ -427,10 +509,70 @@
/// CHECK-NEXT: fcsel hs
public static float FloatGtMatCond_FloatVarVar(float a, float b, float x, float y) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
float result = (a < b ? x : y);
return result + (a < b ? 0 : 1);
}
+ /// CHECK-START: int Main.BoolCond_0_m1(boolean) register (after)
+ /// CHECK: <<Cond:z\d+>> ParameterValue
+ /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>]
+
+ /// CHECK-START-ARM64: int Main.BoolCond_0_m1(boolean) disassembly (after)
+ /// CHECK: <<Cond:z\d+>> ParameterValue
+ /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>]
+ /// CHECK-NEXT: cmp {{w\d+}}, #0x0 (0)
+ /// CHECK-NEXT: csetm {{w\d+}}, eq
+
+ /// CHECK-START-X86_64: int Main.BoolCond_0_m1(boolean) disassembly (after)
+ /// CHECK: <<Cond:z\d+>> ParameterValue
+ /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>]
+ /// CHECK: cmovnz/ne
+
+ /// CHECK-START-X86: int Main.BoolCond_0_m1(boolean) disassembly (after)
+ /// CHECK: <<Cond:z\d+>> ParameterValue
+ /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>]
+ /// CHECK: cmovnz/ne
+
+ public static int BoolCond_0_m1(boolean cond) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
+ return cond ? 0 : -1;
+ }
+
+ /// CHECK-START: int Main.BoolCond_m1_0(boolean) register (after)
+ /// CHECK: <<Cond:z\d+>> ParameterValue
+ /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>]
+
+ /// CHECK-START-ARM64: int Main.BoolCond_m1_0(boolean) disassembly (after)
+ /// CHECK: <<Cond:z\d+>> ParameterValue
+ /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>]
+ /// CHECK-NEXT: cmp {{w\d+}}, #0x0 (0)
+ /// CHECK-NEXT: csetm {{w\d+}}, ne
+
+ /// CHECK-START-X86_64: int Main.BoolCond_m1_0(boolean) disassembly (after)
+ /// CHECK: <<Cond:z\d+>> ParameterValue
+ /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>]
+ /// CHECK: cmovnz/ne
+
+ /// CHECK-START-X86: int Main.BoolCond_m1_0(boolean) disassembly (after)
+ /// CHECK: <<Cond:z\d+>> ParameterValue
+ /// CHECK: Select [{{i\d+}},{{i\d+}},<<Cond>>]
+ /// CHECK: cmovnz/ne
+
+ public static int BoolCond_m1_0(boolean cond) {
+ if (doThrow) {
+ // Try defeating inlining.
+ throw new Error();
+ }
+ return cond ? -1 : 0;
+ }
+
public static void assertEqual(int expected, int actual) {
if (expected != actual) {
throw new Error("Assertion failed: " + expected + " != " + actual);
@@ -499,5 +641,10 @@
assertEqual(8, FloatGtMatCond_FloatVarVar(3, 2, 5, 7));
assertEqual(8, FloatGtMatCond_FloatVarVar(Float.NaN, 2, 5, 7));
assertEqual(8, FloatGtMatCond_FloatVarVar(2, Float.NaN, 5, 7));
+
+ assertEqual(0, BoolCond_0_m1(true));
+ assertEqual(-1, BoolCond_0_m1(false));
+ assertEqual(-1, BoolCond_m1_0(true));
+ assertEqual(0, BoolCond_m1_0(false));
}
}
diff --git a/test/606-erroneous-class/expected.txt b/test/606-erroneous-class/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/606-erroneous-class/expected.txt
diff --git a/test/606-erroneous-class/info.txt b/test/606-erroneous-class/info.txt
new file mode 100644
index 0000000..42cbb7a
--- /dev/null
+++ b/test/606-erroneous-class/info.txt
@@ -0,0 +1,3 @@
+Regression test for a DCHECK in the DexCache which prevented erroneous classes
+from being stored into it. This was bogus because the status of a class can be
+changed by another thread.
\ No newline at end of file
diff --git a/test/606-erroneous-class/smali-multidex/ClassA.smali b/test/606-erroneous-class/smali-multidex/ClassA.smali
new file mode 100644
index 0000000..f87fcb2
--- /dev/null
+++ b/test/606-erroneous-class/smali-multidex/ClassA.smali
@@ -0,0 +1,27 @@
+# Copyright (C) 2016 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.
+
+.class public final LClassA;
+.super Ljava/lang/Object;
+
+.method public static foo()V
+ .registers 1
+ # Obtain the ErrClass type from Dex cache of the first Dex file. Note that
+ # because the first Dex file has already been verified, we know the class
+ # is erroneous at this point.
+ sget-object v0, LClassB;->g:LErrClass;
+ # Use the object in a way that will try to store the ErrClass type in
+ # the Dex cache of the second Dex file.
+ invoke-virtual {v0}, LErrClass;->foo()V
+.end method
diff --git a/test/606-erroneous-class/smali/ClassB.smali b/test/606-erroneous-class/smali/ClassB.smali
new file mode 100644
index 0000000..80754c8
--- /dev/null
+++ b/test/606-erroneous-class/smali/ClassB.smali
@@ -0,0 +1,18 @@
+# Copyright (C) 2016 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.
+
+.class public LClassB;
+.super Ljava/lang/Object;
+
+.field public static g:LErrClass;
diff --git a/test/606-erroneous-class/smali/ErrClass.smali b/test/606-erroneous-class/smali/ErrClass.smali
new file mode 100644
index 0000000..740f1e1
--- /dev/null
+++ b/test/606-erroneous-class/smali/ErrClass.smali
@@ -0,0 +1,26 @@
+# Copyright (C) 2016 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.
+
+.class public final LErrClass;
+.super Ljava/lang/Object;
+
+.field public g:Ljava/lang/Object;
+
+.method public foo()V
+ .registers 6
+ # Use a new instance before initializing it => hard verifier error.
+ new-instance v0, LSomeClass;
+ iput-object v0, p0, LErrClass;->g:Ljava/lang/Object;
+ return-void
+.end method
diff --git a/test/606-erroneous-class/src/Main.java b/test/606-erroneous-class/src/Main.java
new file mode 100644
index 0000000..7dbe567
--- /dev/null
+++ b/test/606-erroneous-class/src/Main.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+public class Main {
+ public static void main(String[] args) {
+ // Nothing to run.
+ }
+}
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index f118a76..ee651b5 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -209,10 +209,9 @@
$(IMAGE_TYPES), $(PICTEST_TYPES), $(DEBUGGABLE_TYPES), $(ART_TEST_RUN_TEST_SKIP), $(ALL_ADDRESS_SIZES))
-# Disable 149-suspend-all-stress, its output is flaky (b/28988206).
+# Disable 137-cfi (b/27391690).
# Disable 577-profile-foreign-dex (b/27454772).
TEST_ART_BROKEN_ALL_TARGET_TESTS := \
- 149-suspend-all-stress \
577-profile-foreign-dex \
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \