diff options
Diffstat (limited to 'compiler')
20 files changed, 2207 insertions, 577 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index a4b48892fb..131be37a33 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -2522,11 +2522,28 @@ class InitializeArrayClassesAndCreateConflictTablesVisitor : public ClassVisitor true); } // Create the conflict tables. - if (!klass->IsTemp() && klass->ShouldHaveEmbeddedImtAndVTable()) { + FillIMTAndConflictTables(klass); + return true; + } + + private: + void FillIMTAndConflictTables(mirror::Class* klass) SHARED_REQUIRES(Locks::mutator_lock_) { + if (!klass->ShouldHaveImt()) { + return; + } + if (visited_classes_.find(klass) != visited_classes_.end()) { + return; + } + if (klass->HasSuperClass()) { + FillIMTAndConflictTables(klass->GetSuperClass()); + } + if (!klass->IsTemp()) { Runtime::Current()->GetClassLinker()->FillIMTAndConflictTables(klass); } - return true; + visited_classes_.insert(klass); } + + std::set<mirror::Class*> visited_classes_; }; void CompilerDriver::InitializeClasses(jobject class_loader, diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index da10568475..063eb11718 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -1232,9 +1232,10 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { } // Assign offsets for all runtime methods in the IMT since these may hold conflict tables // live. - if (as_klass->ShouldHaveEmbeddedImtAndVTable()) { - for (size_t i = 0; i < mirror::Class::kImtSize; ++i) { - ArtMethod* imt_method = as_klass->GetEmbeddedImTableEntry(i, target_ptr_size_); + if (as_klass->ShouldHaveImt()) { + ImTable* imt = as_klass->GetImt(target_ptr_size_); + for (size_t i = 0; i < ImTable::kSize; ++i) { + ArtMethod* imt_method = imt->Get(i, target_ptr_size_); DCHECK(imt_method != nullptr); if (imt_method->IsRuntimeMethod() && !IsInBootImage(imt_method) && @@ -1243,6 +1244,11 @@ void ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { } } } + + if (as_klass->ShouldHaveImt()) { + ImTable* imt = as_klass->GetImt(target_ptr_size_); + TryAssignImTableOffset(imt, oat_index); + } } else if (h_obj->IsObjectArray()) { // Walk elements of an object array. int32_t length = h_obj->AsObjectArray<mirror::Object>()->GetLength(); @@ -1269,6 +1275,23 @@ bool ImageWriter::NativeRelocationAssigned(void* ptr) const { return native_object_relocations_.find(ptr) != native_object_relocations_.end(); } +void ImageWriter::TryAssignImTableOffset(ImTable* imt, size_t oat_index) { + // No offset, or already assigned. + if (imt == nullptr || IsInBootImage(imt) || NativeRelocationAssigned(imt)) { + return; + } + // If the method is a conflict method we also want to assign the conflict table offset. + ImageInfo& image_info = GetImageInfo(oat_index); + const size_t size = ImTable::SizeInBytes(target_ptr_size_); + native_object_relocations_.emplace( + imt, + NativeObjectRelocation { + oat_index, + image_info.bin_slot_sizes_[kBinImTable], + kNativeObjectRelocationTypeIMTable}); + image_info.bin_slot_sizes_[kBinImTable] += size; +} + void ImageWriter::TryAssignConflictTableOffset(ImtConflictTable* table, size_t oat_index) { // No offset, or already assigned. if (table == nullptr || NativeRelocationAssigned(table)) { @@ -1391,6 +1414,7 @@ void ImageWriter::CalculateNewObjectOffsets() { bin_offset = RoundUp(bin_offset, method_alignment); break; } + case kBinImTable: case kBinIMTConflictTable: { bin_offset = RoundUp(bin_offset, target_ptr_size_); break; @@ -1461,6 +1485,10 @@ size_t ImageWriter::ImageInfo::CreateImageSections(ImageSection* out_sections) c bin_slot_offsets_[kBinArtMethodClean], bin_slot_sizes_[kBinArtMethodClean] + bin_slot_sizes_[kBinArtMethodDirty]); + // IMT section. + ImageSection* imt_section = &out_sections[ImageHeader::kSectionImTables]; + *imt_section = ImageSection(bin_slot_offsets_[kBinImTable], bin_slot_sizes_[kBinImTable]); + // Conflict tables section. ImageSection* imt_conflict_tables_section = &out_sections[ImageHeader::kSectionIMTConflictTables]; *imt_conflict_tables_section = ImageSection(bin_slot_offsets_[kBinIMTConflictTable], @@ -1585,6 +1613,13 @@ class FixupRootVisitor : public RootVisitor { ImageWriter* const image_writer_; }; +void ImageWriter::CopyAndFixupImTable(ImTable* orig, ImTable* copy) { + for (size_t i = 0; i < ImTable::kSize; ++i) { + ArtMethod* method = orig->Get(i, target_ptr_size_); + copy->Set(i, NativeLocationInImage(method), target_ptr_size_); + } +} + void ImageWriter::CopyAndFixupImtConflictTable(ImtConflictTable* orig, ImtConflictTable* copy) { const size_t count = orig->NumEntries(target_ptr_size_); for (size_t i = 0; i < count; ++i) { @@ -1642,6 +1677,12 @@ void ImageWriter::CopyAndFixupNativeData(size_t oat_index) { case kNativeObjectRelocationTypeDexCacheArray: // Nothing to copy here, everything is done in FixupDexCache(). break; + case kNativeObjectRelocationTypeIMTable: { + ImTable* orig_imt = reinterpret_cast<ImTable*>(pair.first); + ImTable* dest_imt = reinterpret_cast<ImTable*>(dest); + CopyAndFixupImTable(orig_imt, dest_imt); + break; + } case kNativeObjectRelocationTypeIMTConflictTable: { auto* orig_table = reinterpret_cast<ImtConflictTable*>(pair.first); CopyAndFixupImtConflictTable( @@ -1850,13 +1891,25 @@ uintptr_t ImageWriter::NativeOffsetInImage(void* obj) { } template <typename T> +std::string PrettyPrint(T* ptr) SHARED_REQUIRES(Locks::mutator_lock_) { + std::ostringstream oss; + oss << ptr; + return oss.str(); +} + +template <> +std::string PrettyPrint(ArtMethod* method) SHARED_REQUIRES(Locks::mutator_lock_) { + return PrettyMethod(method); +} + +template <typename T> T* ImageWriter::NativeLocationInImage(T* obj) { if (obj == nullptr || IsInBootImage(obj)) { return obj; } else { auto it = native_object_relocations_.find(obj); - CHECK(it != native_object_relocations_.end()) << obj << " spaces " - << Runtime::Current()->GetHeap()->DumpSpaces(); + CHECK(it != native_object_relocations_.end()) << obj << " " << PrettyPrint(obj) + << " spaces " << Runtime::Current()->GetHeap()->DumpSpaces(); const NativeObjectRelocation& relocation = it->second; ImageInfo& image_info = GetImageInfo(relocation.oat_index); return reinterpret_cast<T*>(image_info.image_begin_ + relocation.offset); @@ -2210,6 +2263,8 @@ ImageWriter::Bin ImageWriter::BinTypeForNativeRelocationType(NativeObjectRelocat return kBinDexCacheArray; case kNativeObjectRelocationTypeRuntimeMethod: return kBinRuntimeMethod; + case kNativeObjectRelocationTypeIMTable: + return kBinImTable; case kNativeObjectRelocationTypeIMTConflictTable: return kBinIMTConflictTable; } diff --git a/compiler/image_writer.h b/compiler/image_writer.h index 51976c511f..1efdc22c0a 100644 --- a/compiler/image_writer.h +++ b/compiler/image_writer.h @@ -169,6 +169,8 @@ class ImageWriter FINAL { // ArtMethods may be dirty if the class has native methods or a declaring class that isn't // initialized. kBinArtMethodDirty, + // IMT (clean) + kBinImTable, // Conflict tables (clean). kBinIMTConflictTable, // Runtime methods (always clean, do not have a length prefix array). @@ -191,6 +193,7 @@ class ImageWriter FINAL { kNativeObjectRelocationTypeArtMethodDirty, kNativeObjectRelocationTypeArtMethodArrayDirty, kNativeObjectRelocationTypeRuntimeMethod, + kNativeObjectRelocationTypeIMTable, kNativeObjectRelocationTypeIMTConflictTable, kNativeObjectRelocationTypeDexCacheArray, }; @@ -401,6 +404,7 @@ class ImageWriter FINAL { void CopyAndFixupObject(mirror::Object* obj) SHARED_REQUIRES(Locks::mutator_lock_); void CopyAndFixupMethod(ArtMethod* orig, ArtMethod* copy, const ImageInfo& image_info) SHARED_REQUIRES(Locks::mutator_lock_); + void CopyAndFixupImTable(ImTable* orig, ImTable* copy) SHARED_REQUIRES(Locks::mutator_lock_); void CopyAndFixupImtConflictTable(ImtConflictTable* orig, ImtConflictTable* copy) SHARED_REQUIRES(Locks::mutator_lock_); void FixupClass(mirror::Class* orig, mirror::Class* copy) @@ -433,6 +437,8 @@ class ImageWriter FINAL { size_t oat_index) SHARED_REQUIRES(Locks::mutator_lock_); + void TryAssignImTableOffset(ImTable* imt, size_t oat_index) SHARED_REQUIRES(Locks::mutator_lock_); + // Assign the offset for an IMT conflict table. Does nothing if the table already has a native // relocation. void TryAssignConflictTableOffset(ImtConflictTable* table, size_t oat_index) diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 6e74d082e0..eca9e2c299 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -1873,8 +1873,6 @@ void InstructionCodeGeneratorARM::VisitInvokeInterface(HInvokeInterface* invoke) LocationSummary* locations = invoke->GetLocations(); Register temp = locations->GetTemp(0).AsRegister<Register>(); Register hidden_reg = locations->GetTemp(1).AsRegister<Register>(); - uint32_t method_offset = mirror::Class::EmbeddedImTableEntryOffset( - invoke->GetImtIndex() % mirror::Class::kImtSize, kArmPointerSize).Uint32Value(); Location receiver = locations->InAt(0); uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); @@ -1900,10 +1898,14 @@ void InstructionCodeGeneratorARM::VisitInvokeInterface(HInvokeInterface* invoke) // intact/accessible until the end of the marking phase (the // concurrent copying collector may not in the future). __ MaybeUnpoisonHeapReference(temp); + __ LoadFromOffset(kLoadWord, temp, temp, + mirror::Class::ImtPtrOffset(kArmPointerSize).Uint32Value()); + uint32_t method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement( + invoke->GetImtIndex(), kArmPointerSize)); // temp = temp->GetImtEntryAt(method_offset); + __ LoadFromOffset(kLoadWord, temp, temp, method_offset); uint32_t entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArmWordSize).Int32Value(); - __ LoadFromOffset(kLoadWord, temp, temp, method_offset); // LR = temp->GetEntryPoint(); __ LoadFromOffset(kLoadWord, LR, temp, entry_point); // LR(); @@ -6777,8 +6779,11 @@ void InstructionCodeGeneratorARM::VisitClassTableGet(HClassTableGet* instruction method_offset = mirror::Class::EmbeddedVTableEntryOffset( instruction->GetIndex(), kArmPointerSize).SizeValue(); } else { - method_offset = mirror::Class::EmbeddedImTableEntryOffset( - instruction->GetIndex() % mirror::Class::kImtSize, kArmPointerSize).Uint32Value(); + __ LoadFromOffset(kLoadWord, locations->Out().AsRegister<Register>(), + locations->InAt(0).AsRegister<Register>(), + mirror::Class::ImtPtrOffset(kArmPointerSize).Uint32Value()); + method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement( + instruction->GetIndex(), kArmPointerSize)); } __ LoadFromOffset(kLoadWord, locations->Out().AsRegister<Register>(), diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc index 5560ae2c74..5d3c8c5590 100644 --- a/compiler/optimizing/code_generator_arm64.cc +++ b/compiler/optimizing/code_generator_arm64.cc @@ -2951,75 +2951,48 @@ void InstructionCodeGeneratorARM64::VisitDeoptimize(HDeoptimize* deoptimize) { /* 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 LocationsBuilderARM64::VisitSelect(HSelect* select) { 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); } } @@ -3528,8 +3490,6 @@ void InstructionCodeGeneratorARM64::VisitInvokeInterface(HInvokeInterface* invok // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError. LocationSummary* locations = invoke->GetLocations(); Register temp = XRegisterFrom(locations->GetTemp(0)); - uint32_t method_offset = mirror::Class::EmbeddedImTableEntryOffset( - invoke->GetImtIndex() % mirror::Class::kImtSize, kArm64PointerSize).Uint32Value(); Location receiver = locations->InAt(0); Offset class_offset = mirror::Object::ClassOffset(); Offset entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize); @@ -3559,6 +3519,10 @@ void InstructionCodeGeneratorARM64::VisitInvokeInterface(HInvokeInterface* invok // intact/accessible until the end of the marking phase (the // concurrent copying collector may not in the future). GetAssembler()->MaybeUnpoisonHeapReference(temp.W()); + __ Ldr(temp, + MemOperand(temp, mirror::Class::ImtPtrOffset(kArm64PointerSize).Uint32Value())); + uint32_t method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement( + invoke->GetImtIndex(), kArm64PointerSize)); // temp = temp->GetImtEntryAt(method_offset); __ Ldr(temp, MemOperand(temp, method_offset)); // lr = temp->GetEntryPoint(); @@ -5186,8 +5150,10 @@ void InstructionCodeGeneratorARM64::VisitClassTableGet(HClassTableGet* instructi method_offset = mirror::Class::EmbeddedVTableEntryOffset( instruction->GetIndex(), kArm64PointerSize).SizeValue(); } else { - method_offset = mirror::Class::EmbeddedImTableEntryOffset( - instruction->GetIndex() % mirror::Class::kImtSize, kArm64PointerSize).Uint32Value(); + __ Ldr(XRegisterFrom(locations->Out()), MemOperand(XRegisterFrom(locations->InAt(0)), + mirror::Class::ImtPtrOffset(kArm64PointerSize).Uint32Value())); + method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement( + instruction->GetIndex(), kArm64PointerSize)); } __ Ldr(XRegisterFrom(locations->Out()), MemOperand(XRegisterFrom(locations->InAt(0)), method_offset)); diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index ed0767ed52..d5bad28dab 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -3701,8 +3701,6 @@ void LocationsBuilderMIPS::VisitInvokeInterface(HInvokeInterface* invoke) { void InstructionCodeGeneratorMIPS::VisitInvokeInterface(HInvokeInterface* invoke) { // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError. Register temp = invoke->GetLocations()->GetTemp(0).AsRegister<Register>(); - uint32_t method_offset = mirror::Class::EmbeddedImTableEntryOffset( - invoke->GetImtIndex() % mirror::Class::kImtSize, kMipsPointerSize).Uint32Value(); Location receiver = invoke->GetLocations()->InAt(0); uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); Offset entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kMipsWordSize); @@ -3719,6 +3717,10 @@ void InstructionCodeGeneratorMIPS::VisitInvokeInterface(HInvokeInterface* invoke __ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset); } codegen_->MaybeRecordImplicitNullCheck(invoke); + __ LoadFromOffset(kLoadWord, temp, temp, + mirror::Class::ImtPtrOffset(kMipsPointerSize).Uint32Value()); + uint32_t method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement( + invoke->GetImtIndex(), kMipsPointerSize)); // temp = temp->GetImtEntryAt(method_offset); __ LoadFromOffset(kLoadWord, temp, temp, method_offset); // T9 = temp->GetEntryPoint(); @@ -5162,8 +5164,12 @@ void InstructionCodeGeneratorMIPS::VisitClassTableGet(HClassTableGet* instructio method_offset = mirror::Class::EmbeddedVTableEntryOffset( instruction->GetIndex(), kMipsPointerSize).SizeValue(); } else { - method_offset = mirror::Class::EmbeddedImTableEntryOffset( - instruction->GetIndex() % mirror::Class::kImtSize, kMipsPointerSize).Uint32Value(); + __ LoadFromOffset(kLoadWord, + locations->Out().AsRegister<Register>(), + locations->InAt(0).AsRegister<Register>(), + mirror::Class::ImtPtrOffset(kMipsPointerSize).Uint32Value()); + method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement( + instruction->GetIndex(), kMipsPointerSize)); } __ LoadFromOffset(kLoadWord, locations->Out().AsRegister<Register>(), diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc index 8c73e350f6..539abf1de8 100644 --- a/compiler/optimizing/code_generator_mips64.cc +++ b/compiler/optimizing/code_generator_mips64.cc @@ -2935,8 +2935,6 @@ void LocationsBuilderMIPS64::VisitInvokeInterface(HInvokeInterface* invoke) { void InstructionCodeGeneratorMIPS64::VisitInvokeInterface(HInvokeInterface* invoke) { // TODO: b/18116999, our IMTs can miss an IncompatibleClassChangeError. GpuRegister temp = invoke->GetLocations()->GetTemp(0).AsRegister<GpuRegister>(); - uint32_t method_offset = mirror::Class::EmbeddedImTableEntryOffset( - invoke->GetImtIndex() % mirror::Class::kImtSize, kMips64PointerSize).Uint32Value(); Location receiver = invoke->GetLocations()->InAt(0); uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); Offset entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kMips64DoublewordSize); @@ -2953,6 +2951,10 @@ void InstructionCodeGeneratorMIPS64::VisitInvokeInterface(HInvokeInterface* invo __ LoadFromOffset(kLoadUnsignedWord, temp, receiver.AsRegister<GpuRegister>(), class_offset); } codegen_->MaybeRecordImplicitNullCheck(invoke); + __ LoadFromOffset(kLoadDoubleword, temp, temp, + mirror::Class::ImtPtrOffset(kMips64PointerSize).Uint32Value()); + uint32_t method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement( + invoke->GetImtIndex(), kMips64PointerSize)); // temp = temp->GetImtEntryAt(method_offset); __ LoadFromOffset(kLoadDoubleword, temp, temp, method_offset); // T9 = temp->GetEntryPoint(); diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 8c643a05c8..a21c295274 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -2012,8 +2012,6 @@ void InstructionCodeGeneratorX86::VisitInvokeInterface(HInvokeInterface* invoke) LocationSummary* locations = invoke->GetLocations(); Register temp = locations->GetTemp(0).AsRegister<Register>(); XmmRegister hidden_reg = locations->GetTemp(1).AsFpuRegister<XmmRegister>(); - uint32_t method_offset = mirror::Class::EmbeddedImTableEntryOffset( - invoke->GetImtIndex() % mirror::Class::kImtSize, kX86PointerSize).Uint32Value(); Location receiver = locations->InAt(0); uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); @@ -2040,7 +2038,12 @@ void InstructionCodeGeneratorX86::VisitInvokeInterface(HInvokeInterface* invoke) // intact/accessible until the end of the marking phase (the // concurrent copying collector may not in the future). __ MaybeUnpoisonHeapReference(temp); + // temp = temp->GetAddressOfIMT() + __ movl(temp, + Address(temp, mirror::Class::ImtPtrOffset(kX86PointerSize).Uint32Value())); // temp = temp->GetImtEntryAt(method_offset); + uint32_t method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement( + invoke->GetImtIndex(), kX86PointerSize)); __ movl(temp, Address(temp, method_offset)); // call temp->GetEntryPoint(); __ call(Address(temp, @@ -4060,8 +4063,12 @@ void InstructionCodeGeneratorX86::VisitClassTableGet(HClassTableGet* instruction method_offset = mirror::Class::EmbeddedVTableEntryOffset( instruction->GetIndex(), kX86PointerSize).SizeValue(); } else { - method_offset = mirror::Class::EmbeddedImTableEntryOffset( - instruction->GetIndex() % mirror::Class::kImtSize, kX86PointerSize).Uint32Value(); + __ movl(locations->InAt(0).AsRegister<Register>(), + Address(locations->InAt(0).AsRegister<Register>(), + mirror::Class::ImtPtrOffset(kX86PointerSize).Uint32Value())); + // temp = temp->GetImtEntryAt(method_offset); + method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement( + instruction->GetIndex(), kX86PointerSize)); } __ movl(locations->Out().AsRegister<Register>(), Address(locations->InAt(0).AsRegister<Register>(), method_offset)); diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 72de3e6e35..135f0c40d0 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -2228,8 +2228,6 @@ void InstructionCodeGeneratorX86_64::VisitInvokeInterface(HInvokeInterface* invo LocationSummary* locations = invoke->GetLocations(); CpuRegister temp = locations->GetTemp(0).AsRegister<CpuRegister>(); CpuRegister hidden_reg = locations->GetTemp(1).AsRegister<CpuRegister>(); - uint32_t method_offset = mirror::Class::EmbeddedImTableEntryOffset( - invoke->GetImtIndex() % mirror::Class::kImtSize, kX86_64PointerSize).Uint32Value(); Location receiver = locations->InAt(0); size_t class_offset = mirror::Object::ClassOffset().SizeValue(); @@ -2255,6 +2253,12 @@ void InstructionCodeGeneratorX86_64::VisitInvokeInterface(HInvokeInterface* invo // intact/accessible until the end of the marking phase (the // concurrent copying collector may not in the future). __ MaybeUnpoisonHeapReference(temp); + // temp = temp->GetAddressOfIMT() + __ movq(temp, + Address(temp, mirror::Class::ImtPtrOffset(kX86_64PointerSize).Uint32Value())); + // temp = temp->GetImtEntryAt(method_offset); + uint32_t method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement( + invoke->GetImtIndex(), kX86_64PointerSize)); // temp = temp->GetImtEntryAt(method_offset); __ movq(temp, Address(temp, method_offset)); // call temp->GetEntryPoint(); @@ -3978,8 +3982,11 @@ void InstructionCodeGeneratorX86_64::VisitClassTableGet(HClassTableGet* instruct method_offset = mirror::Class::EmbeddedVTableEntryOffset( instruction->GetIndex(), kX86_64PointerSize).SizeValue(); } else { - method_offset = mirror::Class::EmbeddedImTableEntryOffset( - instruction->GetIndex() % mirror::Class::kImtSize, kX86_64PointerSize).Uint32Value(); + __ movq(locations->Out().AsRegister<CpuRegister>(), + Address(locations->InAt(0).AsRegister<CpuRegister>(), + mirror::Class::ImtPtrOffset(kX86_64PointerSize).Uint32Value())); + method_offset = static_cast<uint32_t>(ImTable::OffsetOfElement( + instruction->GetIndex(), kX86_64PointerSize)); } __ movq(locations->Out().AsRegister<CpuRegister>(), Address(locations->InAt(0).AsRegister<CpuRegister>(), method_offset)); diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 59de895182..d5e80b4759 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -656,8 +656,8 @@ bool HInliner::TryInlinePolymorphicCallToSameTarget(HInvoke* invoke_instruction, } ArtMethod* new_method = nullptr; if (invoke_instruction->IsInvokeInterface()) { - new_method = ic.GetTypeAt(i)->GetEmbeddedImTableEntry( - method_index % mirror::Class::kImtSize, pointer_size); + new_method = ic.GetTypeAt(i)->GetImt(pointer_size)->Get( + method_index, pointer_size); if (new_method->IsRuntimeMethod()) { // Bail out as soon as we see a conflict trampoline in one of the target's // interface table. diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index f2286e46e6..1c67bcc878 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -16,6 +16,7 @@ #include "instruction_builder.h" +#include "art_method-inl.h" #include "bytecode_utils.h" #include "class_linker.h" #include "driver/compiler_options.h" @@ -890,7 +891,7 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction, return_type, dex_pc, method_idx, - resolved_method->GetDexMethodIndex()); + resolved_method->GetImtIndex()); } return HandleInvoke(invoke, diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc index 29f7672b0a..7d1c2ebe0b 100644 --- a/compiler/optimizing/intrinsics_arm.cc +++ b/compiler/optimizing/intrinsics_arm.cc @@ -2031,7 +2031,7 @@ void IntrinsicLocationsBuilderARM::VisitStringGetCharsNoCheck(HInvoke* invoke) { locations->SetInAt(3, Location::RequiresRegister()); locations->SetInAt(4, Location::RequiresRegister()); - locations->AddTemp(Location::RequiresRegister()); + // Temporary registers to store lengths of strings and for calculations. locations->AddTemp(Location::RequiresRegister()); locations->AddTemp(Location::RequiresRegister()); locations->AddTemp(Location::RequiresRegister()); @@ -2059,28 +2059,55 @@ void IntrinsicCodeGeneratorARM::VisitStringGetCharsNoCheck(HInvoke* invoke) { Register dstObj = locations->InAt(3).AsRegister<Register>(); Register dstBegin = locations->InAt(4).AsRegister<Register>(); - Register src_ptr = locations->GetTemp(0).AsRegister<Register>(); - Register src_ptr_end = locations->GetTemp(1).AsRegister<Register>(); + Register num_chr = locations->GetTemp(0).AsRegister<Register>(); + Register src_ptr = locations->GetTemp(1).AsRegister<Register>(); Register dst_ptr = locations->GetTemp(2).AsRegister<Register>(); - Register tmp = locations->GetTemp(3).AsRegister<Register>(); // src range to copy. __ add(src_ptr, srcObj, ShifterOperand(value_offset)); - __ add(src_ptr_end, src_ptr, ShifterOperand(srcEnd, LSL, 1)); __ add(src_ptr, src_ptr, ShifterOperand(srcBegin, LSL, 1)); // dst to be copied. __ add(dst_ptr, dstObj, ShifterOperand(data_offset)); __ add(dst_ptr, dst_ptr, ShifterOperand(dstBegin, LSL, 1)); + __ subs(num_chr, srcEnd, ShifterOperand(srcBegin)); + // Do the copy. - Label loop, done; + Label loop, remainder, done; + + // Early out for valid zero-length retrievals. + __ b(&done, EQ); + + // Save repairing the value of num_chr on the < 4 character path. + __ subs(IP, num_chr, ShifterOperand(4)); + __ b(&remainder, LT); + + // Keep the result of the earlier subs, we are going to fetch at least 4 characters. + __ mov(num_chr, ShifterOperand(IP)); + + // Main loop used for longer fetches loads and stores 4x16-bit characters at a time. + // (LDRD/STRD fault on unaligned addresses and it's not worth inlining extra code + // to rectify these everywhere this intrinsic applies.) __ Bind(&loop); - __ cmp(src_ptr, ShifterOperand(src_ptr_end)); + __ ldr(IP, Address(src_ptr, char_size * 2)); + __ subs(num_chr, num_chr, ShifterOperand(4)); + __ str(IP, Address(dst_ptr, char_size * 2)); + __ ldr(IP, Address(src_ptr, char_size * 4, Address::PostIndex)); + __ str(IP, Address(dst_ptr, char_size * 4, Address::PostIndex)); + __ b(&loop, GE); + + __ adds(num_chr, num_chr, ShifterOperand(4)); __ b(&done, EQ); - __ ldrh(tmp, Address(src_ptr, char_size, Address::PostIndex)); - __ strh(tmp, Address(dst_ptr, char_size, Address::PostIndex)); - __ b(&loop); + + // Main loop for < 4 character case and remainder handling. Loads and stores one + // 16-bit Java character at a time. + __ Bind(&remainder); + __ ldrh(IP, Address(src_ptr, char_size, Address::PostIndex)); + __ subs(num_chr, num_chr, ShifterOperand(1)); + __ strh(IP, Address(dst_ptr, char_size, Address::PostIndex)); + __ b(&remainder, GT); + __ Bind(&done); } diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index d776fb4406..c8d6ddc8f1 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -1745,6 +1745,7 @@ void IntrinsicLocationsBuilderARM64::VisitStringGetCharsNoCheck(HInvoke* invoke) locations->AddTemp(Location::RequiresRegister()); locations->AddTemp(Location::RequiresRegister()); + locations->AddTemp(Location::RequiresRegister()); } void IntrinsicCodeGeneratorARM64::VisitStringGetCharsNoCheck(HInvoke* invoke) { @@ -1770,29 +1771,57 @@ void IntrinsicCodeGeneratorARM64::VisitStringGetCharsNoCheck(HInvoke* invoke) { Register dstBegin = XRegisterFrom(locations->InAt(4)); Register src_ptr = XRegisterFrom(locations->GetTemp(0)); - Register src_ptr_end = XRegisterFrom(locations->GetTemp(1)); + Register num_chr = XRegisterFrom(locations->GetTemp(1)); + Register tmp1 = XRegisterFrom(locations->GetTemp(2)); UseScratchRegisterScope temps(masm); Register dst_ptr = temps.AcquireX(); - Register tmp = temps.AcquireW(); + Register tmp2 = temps.AcquireX(); - // src range to copy. + // src address to copy from. __ Add(src_ptr, srcObj, Operand(value_offset)); - __ Add(src_ptr_end, src_ptr, Operand(srcEnd, LSL, 1)); __ Add(src_ptr, src_ptr, Operand(srcBegin, LSL, 1)); - // dst to be copied. + // dst address start to copy to. __ Add(dst_ptr, dstObj, Operand(data_offset)); __ Add(dst_ptr, dst_ptr, Operand(dstBegin, LSL, 1)); + __ Sub(num_chr, srcEnd, srcBegin); + // Do the copy. - vixl::Label loop, done; + vixl::Label loop; + vixl::Label done; + vixl::Label remainder; + + // Early out for valid zero-length retrievals. + __ Cbz(num_chr, &done); + + // Save repairing the value of num_chr on the < 8 character path. + __ Subs(tmp1, num_chr, 8); + __ B(lt, &remainder); + + // Keep the result of the earlier subs, we are going to fetch at least 8 characters. + __ Mov(num_chr, tmp1); + + // Main loop used for longer fetches loads and stores 8x16-bit characters at a time. + // (Unaligned addresses are acceptable here and not worth inlining extra code to rectify.) __ Bind(&loop); - __ Cmp(src_ptr, src_ptr_end); - __ B(&done, eq); - __ Ldrh(tmp, MemOperand(src_ptr, char_size, vixl::PostIndex)); - __ Strh(tmp, MemOperand(dst_ptr, char_size, vixl::PostIndex)); - __ B(&loop); + __ Ldp(tmp1, tmp2, MemOperand(src_ptr, char_size * 8, vixl::PostIndex)); + __ Subs(num_chr, num_chr, 8); + __ Stp(tmp1, tmp2, MemOperand(dst_ptr, char_size * 8, vixl::PostIndex)); + __ B(ge, &loop); + + __ Adds(num_chr, num_chr, 8); + __ B(eq, &done); + + // Main loop for < 8 character case and remainder handling. Loads and stores one + // 16-bit Java character at a time. + __ Bind(&remainder); + __ Ldrh(tmp1, MemOperand(src_ptr, char_size, vixl::PostIndex)); + __ Subs(num_chr, num_chr, 1); + __ Strh(tmp1, MemOperand(dst_ptr, char_size, vixl::PostIndex)); + __ B(gt, &remainder); + __ Bind(&done); } diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index ae3c4b01e6..4b4e549e20 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -2283,8 +2283,6 @@ ReferenceTypeInfo ReferenceTypeInfo::Create(TypeHandle type_handle, bool is_exac 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 2a281dd46d..3e6adcb172 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -46,10 +46,10 @@ static inline ReferenceTypeInfo::TypeHandle GetRootHandle(StackHandleScopeCollec 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/assembler_test.h b/compiler/utils/assembler_test.h index 084e9011ba..afe0576906 100644 --- a/compiler/utils/assembler_test.h +++ b/compiler/utils/assembler_test.h @@ -461,7 +461,7 @@ class AssemblerTest : public testing::Test { void SetUp() OVERRIDE { arena_.reset(new ArenaAllocator(&pool_)); - assembler_.reset(new (arena_.get()) Ass(arena_.get())); + assembler_.reset(CreateAssembler(arena_.get())); test_helper_.reset( new AssemblerTestInfrastructure(GetArchitectureString(), GetAssemblerCmdName(), @@ -481,6 +481,11 @@ class AssemblerTest : public testing::Test { arena_.reset(); } + // Override this to set up any architecture-specific things, e.g., CPU revision. + virtual Ass* CreateAssembler(ArenaAllocator* arena) { + return new (arena) Ass(arena); + } + // Override this to set up any architecture-specific things, e.g., register vectors. virtual void SetUpHelpers() {} diff --git a/compiler/utils/mips/assembler_mips.cc b/compiler/utils/mips/assembler_mips.cc index 9368301d07..ac930833f2 100644 --- a/compiler/utils/mips/assembler_mips.cc +++ b/compiler/utils/mips/assembler_mips.cc @@ -448,6 +448,11 @@ void MipsAssembler::Lui(Register rt, uint16_t imm16) { 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 @@ void MipsAssembler::StoreConst32ToOffset(int32_t value, 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 @@ void MipsAssembler::StoreConst64ToOffset(int64_t value, 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::LoadDConst64(FRegister rd, int64_t value, Register temp) { } 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 @@ void MipsAssembler::Bc1nez(FRegister ft, MipsLabel* label) { 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::LoadFromOffset(LoadOperandType type, Register reg, Register } 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::EmitLoad(ManagedRegister m_dst, Register src_register, int32 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::StoreToOffset(StoreOperandType type, Register reg, Register } 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 d5e62853f4..31b3b311eb 100644 --- a/compiler/utils/mips/assembler_mips.h +++ b/compiler/utils/mips/assembler_mips.h @@ -183,6 +183,7 @@ class MipsAssembler FINAL : public Assembler { 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 @@ class MipsAssembler FINAL : public Assembler { 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_mips32r6_test.cc b/compiler/utils/mips/assembler_mips32r6_test.cc new file mode 100644 index 0000000000..ce92d602d0 --- /dev/null +++ b/compiler/utils/mips/assembler_mips32r6_test.cc @@ -0,0 +1,644 @@ +/* + * 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. + */ + +#include "assembler_mips.h" + +#include <map> + +#include "base/stl_util.h" +#include "utils/assembler_test.h" + +#define __ GetAssembler()-> + +namespace art { + +struct MIPSCpuRegisterCompare { + bool operator()(const mips::Register& a, const mips::Register& b) const { + return a < b; + } +}; + +class AssemblerMIPS32r6Test : public AssemblerTest<mips::MipsAssembler, + mips::Register, + mips::FRegister, + uint32_t> { + public: + typedef AssemblerTest<mips::MipsAssembler, mips::Register, mips::FRegister, uint32_t> Base; + + AssemblerMIPS32r6Test() : + instruction_set_features_(MipsInstructionSetFeatures::FromVariant("mips32r6", nullptr)) { + } + + protected: + // Get the typically used name for this architecture, e.g., aarch64, x86-64, ... + std::string GetArchitectureString() OVERRIDE { + return "mips"; + } + + std::string GetAssemblerParameters() OVERRIDE { + return " --no-warn -32 -march=mips32r6"; + } + + std::string GetDisassembleParameters() OVERRIDE { + return " -D -bbinary -mmips:isa32r6"; + } + + mips::MipsAssembler* CreateAssembler(ArenaAllocator* arena) OVERRIDE { + return new (arena) mips::MipsAssembler(arena, instruction_set_features_.get()); + } + + void SetUpHelpers() OVERRIDE { + if (registers_.size() == 0) { + registers_.push_back(new mips::Register(mips::ZERO)); + registers_.push_back(new mips::Register(mips::AT)); + registers_.push_back(new mips::Register(mips::V0)); + registers_.push_back(new mips::Register(mips::V1)); + registers_.push_back(new mips::Register(mips::A0)); + registers_.push_back(new mips::Register(mips::A1)); + registers_.push_back(new mips::Register(mips::A2)); + registers_.push_back(new mips::Register(mips::A3)); + registers_.push_back(new mips::Register(mips::T0)); + registers_.push_back(new mips::Register(mips::T1)); + registers_.push_back(new mips::Register(mips::T2)); + registers_.push_back(new mips::Register(mips::T3)); + registers_.push_back(new mips::Register(mips::T4)); + registers_.push_back(new mips::Register(mips::T5)); + registers_.push_back(new mips::Register(mips::T6)); + registers_.push_back(new mips::Register(mips::T7)); + registers_.push_back(new mips::Register(mips::S0)); + registers_.push_back(new mips::Register(mips::S1)); + registers_.push_back(new mips::Register(mips::S2)); + registers_.push_back(new mips::Register(mips::S3)); + registers_.push_back(new mips::Register(mips::S4)); + registers_.push_back(new mips::Register(mips::S5)); + registers_.push_back(new mips::Register(mips::S6)); + registers_.push_back(new mips::Register(mips::S7)); + registers_.push_back(new mips::Register(mips::T8)); + registers_.push_back(new mips::Register(mips::T9)); + registers_.push_back(new mips::Register(mips::K0)); + registers_.push_back(new mips::Register(mips::K1)); + registers_.push_back(new mips::Register(mips::GP)); + registers_.push_back(new mips::Register(mips::SP)); + registers_.push_back(new mips::Register(mips::FP)); + registers_.push_back(new mips::Register(mips::RA)); + + secondary_register_names_.emplace(mips::Register(mips::ZERO), "zero"); + secondary_register_names_.emplace(mips::Register(mips::AT), "at"); + secondary_register_names_.emplace(mips::Register(mips::V0), "v0"); + secondary_register_names_.emplace(mips::Register(mips::V1), "v1"); + secondary_register_names_.emplace(mips::Register(mips::A0), "a0"); + secondary_register_names_.emplace(mips::Register(mips::A1), "a1"); + secondary_register_names_.emplace(mips::Register(mips::A2), "a2"); + secondary_register_names_.emplace(mips::Register(mips::A3), "a3"); + secondary_register_names_.emplace(mips::Register(mips::T0), "t0"); + secondary_register_names_.emplace(mips::Register(mips::T1), "t1"); + secondary_register_names_.emplace(mips::Register(mips::T2), "t2"); + secondary_register_names_.emplace(mips::Register(mips::T3), "t3"); + secondary_register_names_.emplace(mips::Register(mips::T4), "t4"); + secondary_register_names_.emplace(mips::Register(mips::T5), "t5"); + secondary_register_names_.emplace(mips::Register(mips::T6), "t6"); + secondary_register_names_.emplace(mips::Register(mips::T7), "t7"); + secondary_register_names_.emplace(mips::Register(mips::S0), "s0"); + secondary_register_names_.emplace(mips::Register(mips::S1), "s1"); + secondary_register_names_.emplace(mips::Register(mips::S2), "s2"); + secondary_register_names_.emplace(mips::Register(mips::S3), "s3"); + secondary_register_names_.emplace(mips::Register(mips::S4), "s4"); + secondary_register_names_.emplace(mips::Register(mips::S5), "s5"); + secondary_register_names_.emplace(mips::Register(mips::S6), "s6"); + secondary_register_names_.emplace(mips::Register(mips::S7), "s7"); + secondary_register_names_.emplace(mips::Register(mips::T8), "t8"); + secondary_register_names_.emplace(mips::Register(mips::T9), "t9"); + secondary_register_names_.emplace(mips::Register(mips::K0), "k0"); + secondary_register_names_.emplace(mips::Register(mips::K1), "k1"); + secondary_register_names_.emplace(mips::Register(mips::GP), "gp"); + secondary_register_names_.emplace(mips::Register(mips::SP), "sp"); + secondary_register_names_.emplace(mips::Register(mips::FP), "fp"); + secondary_register_names_.emplace(mips::Register(mips::RA), "ra"); + + fp_registers_.push_back(new mips::FRegister(mips::F0)); + fp_registers_.push_back(new mips::FRegister(mips::F1)); + fp_registers_.push_back(new mips::FRegister(mips::F2)); + fp_registers_.push_back(new mips::FRegister(mips::F3)); + fp_registers_.push_back(new mips::FRegister(mips::F4)); + fp_registers_.push_back(new mips::FRegister(mips::F5)); + fp_registers_.push_back(new mips::FRegister(mips::F6)); + fp_registers_.push_back(new mips::FRegister(mips::F7)); + fp_registers_.push_back(new mips::FRegister(mips::F8)); + fp_registers_.push_back(new mips::FRegister(mips::F9)); + fp_registers_.push_back(new mips::FRegister(mips::F10)); + fp_registers_.push_back(new mips::FRegister(mips::F11)); + fp_registers_.push_back(new mips::FRegister(mips::F12)); + fp_registers_.push_back(new mips::FRegister(mips::F13)); + fp_registers_.push_back(new mips::FRegister(mips::F14)); + fp_registers_.push_back(new mips::FRegister(mips::F15)); + fp_registers_.push_back(new mips::FRegister(mips::F16)); + fp_registers_.push_back(new mips::FRegister(mips::F17)); + fp_registers_.push_back(new mips::FRegister(mips::F18)); + fp_registers_.push_back(new mips::FRegister(mips::F19)); + fp_registers_.push_back(new mips::FRegister(mips::F20)); + fp_registers_.push_back(new mips::FRegister(mips::F21)); + fp_registers_.push_back(new mips::FRegister(mips::F22)); + fp_registers_.push_back(new mips::FRegister(mips::F23)); + fp_registers_.push_back(new mips::FRegister(mips::F24)); + fp_registers_.push_back(new mips::FRegister(mips::F25)); + fp_registers_.push_back(new mips::FRegister(mips::F26)); + fp_registers_.push_back(new mips::FRegister(mips::F27)); + fp_registers_.push_back(new mips::FRegister(mips::F28)); + fp_registers_.push_back(new mips::FRegister(mips::F29)); + fp_registers_.push_back(new mips::FRegister(mips::F30)); + fp_registers_.push_back(new mips::FRegister(mips::F31)); + } + } + + void TearDown() OVERRIDE { + AssemblerTest::TearDown(); + STLDeleteElements(®isters_); + STLDeleteElements(&fp_registers_); + } + + std::vector<mips::Register*> GetRegisters() OVERRIDE { + return registers_; + } + + std::vector<mips::FRegister*> GetFPRegisters() OVERRIDE { + return fp_registers_; + } + + uint32_t CreateImmediate(int64_t imm_value) OVERRIDE { + return imm_value; + } + + std::string GetSecondaryRegisterName(const mips::Register& reg) OVERRIDE { + CHECK(secondary_register_names_.find(reg) != secondary_register_names_.end()); + return secondary_register_names_[reg]; + } + + std::string RepeatInsn(size_t count, const std::string& insn) { + std::string result; + for (; count != 0u; --count) { + result += insn; + } + return result; + } + + void BranchCondTwoRegsHelper(void (mips::MipsAssembler::*f)(mips::Register, + mips::Register, + mips::MipsLabel*), + std::string instr_name) { + mips::MipsLabel label; + (Base::GetAssembler()->*f)(mips::A0, mips::A1, &label); + constexpr size_t kAdduCount1 = 63; + for (size_t i = 0; i != kAdduCount1; ++i) { + __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); + } + __ Bind(&label); + constexpr size_t kAdduCount2 = 64; + for (size_t i = 0; i != kAdduCount2; ++i) { + __ Addu(mips::ZERO, mips::ZERO, mips::ZERO); + } + (Base::GetAssembler()->*f)(mips::A2, mips::A3, &label); + + std::string expected = + ".set noreorder\n" + + instr_name + " $a0, $a1, 1f\n" + "nop\n" + + RepeatInsn(kAdduCount1, "addu $zero, $zero, $zero\n") + + "1:\n" + + RepeatInsn(kAdduCount2, "addu $zero, $zero, $zero\n") + + instr_name + " $a2, $a3, 1b\n" + "nop\n"; + DriverStr(expected, instr_name); + } + + private: + std::vector<mips::Register*> registers_; + std::map<mips::Register, std::string, MIPSCpuRegisterCompare> secondary_register_names_; + + std::vector<mips::FRegister*> fp_registers_; + std::unique_ptr<const MipsInstructionSetFeatures> instruction_set_features_; +}; + + +TEST_F(AssemblerMIPS32r6Test, Toolchain) { + EXPECT_TRUE(CheckTools()); +} + +TEST_F(AssemblerMIPS32r6Test, MulR6) { + DriverStr(RepeatRRR(&mips::MipsAssembler::MulR6, "mul ${reg1}, ${reg2}, ${reg3}"), "MulR6"); +} + +TEST_F(AssemblerMIPS32r6Test, MuhR6) { + DriverStr(RepeatRRR(&mips::MipsAssembler::MuhR6, "muh ${reg1}, ${reg2}, ${reg3}"), "MuhR6"); +} + +TEST_F(AssemblerMIPS32r6Test, MuhuR6) { + DriverStr(RepeatRRR(&mips::MipsAssembler::MuhuR6, "muhu ${reg1}, ${reg2}, ${reg3}"), "MuhuR6"); +} + +TEST_F(AssemblerMIPS32r6Test, DivR6) { + DriverStr(RepeatRRR(&mips::MipsAssembler::DivR6, "div ${reg1}, ${reg2}, ${reg3}"), "DivR6"); +} + +TEST_F(AssemblerMIPS32r6Test, ModR6) { + DriverStr(RepeatRRR(&mips::MipsAssembler::ModR6, "mod ${reg1}, ${reg2}, ${reg3}"), "ModR6"); +} + +TEST_F(AssemblerMIPS32r6Test, DivuR6) { + DriverStr(RepeatRRR(&mips::MipsAssembler::DivuR6, "divu ${reg1}, ${reg2}, ${reg3}"), "DivuR6"); +} + +TEST_F(AssemblerMIPS32r6Test, ModuR6) { + DriverStr(RepeatRRR(&mips::MipsAssembler::ModuR6, "modu ${reg1}, ${reg2}, ${reg3}"), "ModuR6"); +} + +////////// +// MISC // +////////// + +TEST_F(AssemblerMIPS32r6Test, Aui) { + DriverStr(RepeatRRIb(&mips::MipsAssembler::Aui, 16, "aui ${reg1}, ${reg2}, {imm}"), "Aui"); +} + +TEST_F(AssemblerMIPS32r6Test, Bitswap) { + DriverStr(RepeatRR(&mips::MipsAssembler::Bitswap, "bitswap ${reg1}, ${reg2}"), "bitswap"); +} + +TEST_F(AssemblerMIPS32r6Test, Seleqz) { + DriverStr(RepeatRRR(&mips::MipsAssembler::Seleqz, "seleqz ${reg1}, ${reg2}, ${reg3}"), + "seleqz"); +} + +TEST_F(AssemblerMIPS32r6Test, Selnez) { + DriverStr(RepeatRRR(&mips::MipsAssembler::Selnez, "selnez ${reg1}, ${reg2}, ${reg3}"), + "selnez"); +} + +TEST_F(AssemblerMIPS32r6Test, ClzR6) { + DriverStr(RepeatRR(&mips::MipsAssembler::ClzR6, "clz ${reg1}, ${reg2}"), "clzR6"); +} + +TEST_F(AssemblerMIPS32r6Test, CloR6) { + DriverStr(RepeatRR(&mips::MipsAssembler::CloR6, "clo ${reg1}, ${reg2}"), "cloR6"); +} + +//////////////////// +// FLOATING POINT // +//////////////////// + +TEST_F(AssemblerMIPS32r6Test, SelS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::SelS, "sel.s ${reg1}, ${reg2}, ${reg3}"), "sel.s"); +} + +TEST_F(AssemblerMIPS32r6Test, SelD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::SelD, "sel.d ${reg1}, ${reg2}, ${reg3}"), "sel.d"); +} + +TEST_F(AssemblerMIPS32r6Test, ClassS) { + DriverStr(RepeatFF(&mips::MipsAssembler::ClassS, "class.s ${reg1}, ${reg2}"), "class.s"); +} + +TEST_F(AssemblerMIPS32r6Test, ClassD) { + DriverStr(RepeatFF(&mips::MipsAssembler::ClassD, "class.d ${reg1}, ${reg2}"), "class.d"); +} + +TEST_F(AssemblerMIPS32r6Test, MinS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::MinS, "min.s ${reg1}, ${reg2}, ${reg3}"), "min.s"); +} + +TEST_F(AssemblerMIPS32r6Test, MinD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::MinD, "min.d ${reg1}, ${reg2}, ${reg3}"), "min.d"); +} + +TEST_F(AssemblerMIPS32r6Test, MaxS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::MaxS, "max.s ${reg1}, ${reg2}, ${reg3}"), "max.s"); +} + +TEST_F(AssemblerMIPS32r6Test, MaxD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::MaxD, "max.d ${reg1}, ${reg2}, ${reg3}"), "max.d"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpUnS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUnS, "cmp.un.s ${reg1}, ${reg2}, ${reg3}"), + "cmp.un.s"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpEqS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpEqS, "cmp.eq.s ${reg1}, ${reg2}, ${reg3}"), + "cmp.eq.s"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpUeqS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUeqS, "cmp.ueq.s ${reg1}, ${reg2}, ${reg3}"), + "cmp.ueq.s"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpLtS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpLtS, "cmp.lt.s ${reg1}, ${reg2}, ${reg3}"), + "cmp.lt.s"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpUltS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUltS, "cmp.ult.s ${reg1}, ${reg2}, ${reg3}"), + "cmp.ult.s"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpLeS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpLeS, "cmp.le.s ${reg1}, ${reg2}, ${reg3}"), + "cmp.le.s"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpUleS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUleS, "cmp.ule.s ${reg1}, ${reg2}, ${reg3}"), + "cmp.ule.s"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpOrS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpOrS, "cmp.or.s ${reg1}, ${reg2}, ${reg3}"), + "cmp.or.s"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpUneS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUneS, "cmp.une.s ${reg1}, ${reg2}, ${reg3}"), + "cmp.une.s"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpNeS) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpNeS, "cmp.ne.s ${reg1}, ${reg2}, ${reg3}"), + "cmp.ne.s"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpUnD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUnD, "cmp.un.d ${reg1}, ${reg2}, ${reg3}"), + "cmp.un.d"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpEqD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpEqD, "cmp.eq.d ${reg1}, ${reg2}, ${reg3}"), + "cmp.eq.d"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpUeqD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUeqD, "cmp.ueq.d ${reg1}, ${reg2}, ${reg3}"), + "cmp.ueq.d"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpLtD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpLtD, "cmp.lt.d ${reg1}, ${reg2}, ${reg3}"), + "cmp.lt.d"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpUltD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUltD, "cmp.ult.d ${reg1}, ${reg2}, ${reg3}"), + "cmp.ult.d"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpLeD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpLeD, "cmp.le.d ${reg1}, ${reg2}, ${reg3}"), + "cmp.le.d"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpUleD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUleD, "cmp.ule.d ${reg1}, ${reg2}, ${reg3}"), + "cmp.ule.d"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpOrD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpOrD, "cmp.or.d ${reg1}, ${reg2}, ${reg3}"), + "cmp.or.d"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpUneD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpUneD, "cmp.une.d ${reg1}, ${reg2}, ${reg3}"), + "cmp.une.d"); +} + +TEST_F(AssemblerMIPS32r6Test, CmpNeD) { + DriverStr(RepeatFFF(&mips::MipsAssembler::CmpNeD, "cmp.ne.d ${reg1}, ${reg2}, ${reg3}"), + "cmp.ne.d"); +} + +TEST_F(AssemblerMIPS32r6Test, LoadDFromOffset) { + __ 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" + "ldc1 $f0, 0x7FF8($a0)\n" + "lwc1 $f0, 0x7FFB($a0)\n" + "lw $t8, 0x7FFF($a0)\n" + "mthc1 $t8, $f0\n" + "addiu $at, $a0, 0x7FF8\n" + "lwc1 $f0, 4($at)\n" + "lw $t8, 8($at)\n" + "mthc1 $t8, $f0\n" + "addiu $at, $a0, 0x7FF8\n" + "lwc1 $f0, 7($at)\n" + "lw $t8, 11($at)\n" + "mthc1 $t8, $f0\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" + "lw $t8, -5($at)\n" + "mthc1 $t8, $f0\n" + "addiu $at, $a0, 0x7FF8\n" + "ldc1 $f0, 8($at)\n" + "addiu $at, $a0, 0x7FF8\n" + "ldc1 $f0, 0x7FF8($at)\n" + "aui $at, $a0, 0xFFFF\n" + "ldc1 $f0, -0x7FE8($at)\n" + "aui $at, $a0, 0xFFFF\n" + "ldc1 $f0, 0x8($at)\n" + "aui $at, $a0, 0xFFFF\n" + "lwc1 $f0, 0xF($at)\n" + "lw $t8, 0x13($at)\n" + "mthc1 $t8, $f0\n" + "aui $at, $a0, 0x1\n" + "lwc1 $f0, -0xF($at)\n" + "lw $t8, -0xB($at)\n" + "mthc1 $t8, $f0\n" + "aui $at, $a0, 0x1\n" + "ldc1 $f0, -0x8($at)\n" + "aui $at, $a0, 0x1\n" + "ldc1 $f0, 0x7FE8($at)\n" + "aui $at, $a0, 0xFFFF\n" + "ldc1 $f0, -0x7FF0($at)\n" + "aui $at, $a0, 0xFFFF\n" + "lwc1 $f0, -0x7FE9($at)\n" + "lw $t8, -0x7FE5($at)\n" + "mthc1 $t8, $f0\n" + "aui $at, $a0, 0x1\n" + "lwc1 $f0, 0x7FE9($at)\n" + "lw $t8, 0x7FED($at)\n" + "mthc1 $t8, $f0\n" + "aui $at, $a0, 0x1\n" + "ldc1 $f0, 0x7FF0($at)\n" + "aui $at, $a0, 0x1234\n" + "ldc1 $f0, 0x5678($at)\n"; + DriverStr(expected, "LoadDFromOffset"); +} + +TEST_F(AssemblerMIPS32r6Test, StoreDToOffset) { + __ 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" + "sdc1 $f0, 0x7FF8($a0)\n" + "mfhc1 $t8, $f0\n" + "swc1 $f0, 0x7FFB($a0)\n" + "sw $t8, 0x7FFF($a0)\n" + "addiu $at, $a0, 0x7FF8\n" + "mfhc1 $t8, $f0\n" + "swc1 $f0, 4($at)\n" + "sw $t8, 8($at)\n" + "addiu $at, $a0, 0x7FF8\n" + "mfhc1 $t8, $f0\n" + "swc1 $f0, 7($at)\n" + "sw $t8, 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" + "mfhc1 $t8, $f0\n" + "swc1 $f0, -9($at)\n" + "sw $t8, -5($at)\n" + "addiu $at, $a0, 0x7FF8\n" + "sdc1 $f0, 8($at)\n" + "addiu $at, $a0, 0x7FF8\n" + "sdc1 $f0, 0x7FF8($at)\n" + "aui $at, $a0, 0xFFFF\n" + "sdc1 $f0, -0x7FE8($at)\n" + "aui $at, $a0, 0xFFFF\n" + "sdc1 $f0, 0x8($at)\n" + "aui $at, $a0, 0xFFFF\n" + "mfhc1 $t8, $f0\n" + "swc1 $f0, 0xF($at)\n" + "sw $t8, 0x13($at)\n" + "aui $at, $a0, 0x1\n" + "mfhc1 $t8, $f0\n" + "swc1 $f0, -0xF($at)\n" + "sw $t8, -0xB($at)\n" + "aui $at, $a0, 0x1\n" + "sdc1 $f0, -0x8($at)\n" + "aui $at, $a0, 0x1\n" + "sdc1 $f0, 0x7FE8($at)\n" + "aui $at, $a0, 0xFFFF\n" + "sdc1 $f0, -0x7FF0($at)\n" + "aui $at, $a0, 0xFFFF\n" + "mfhc1 $t8, $f0\n" + "swc1 $f0, -0x7FE9($at)\n" + "sw $t8, -0x7FE5($at)\n" + "aui $at, $a0, 0x1\n" + "mfhc1 $t8, $f0\n" + "swc1 $f0, 0x7FE9($at)\n" + "sw $t8, 0x7FED($at)\n" + "aui $at, $a0, 0x1\n" + "sdc1 $f0, 0x7FF0($at)\n" + "aui $at, $a0, 0x1234\n" + "sdc1 $f0, 0x5678($at)\n"; + DriverStr(expected, "StoreDToOffset"); +} + +////////////// +// BRANCHES // +////////////// + +// TODO: MipsAssembler::Auipc +// MipsAssembler::Addiupc +// MipsAssembler::Bc +// MipsAssembler::Jic +// MipsAssembler::Jialc +// MipsAssembler::Bltc +// MipsAssembler::Bltzc +// MipsAssembler::Bgtzc +// MipsAssembler::Bgec +// MipsAssembler::Bgezc +// MipsAssembler::Blezc +// MipsAssembler::Bltuc +// MipsAssembler::Bgeuc +// MipsAssembler::Beqc +// MipsAssembler::Bnec +// MipsAssembler::Beqzc +// MipsAssembler::Bnezc +// MipsAssembler::Bc1eqz +// MipsAssembler::Bc1nez +// MipsAssembler::Buncond +// MipsAssembler::Bcond +// MipsAssembler::Call + +// TODO: AssemblerMIPS32r6Test.B +// AssemblerMIPS32r6Test.Beq +// AssemblerMIPS32r6Test.Bne +// AssemblerMIPS32r6Test.Beqz +// AssemblerMIPS32r6Test.Bnez +// AssemblerMIPS32r6Test.Bltz +// AssemblerMIPS32r6Test.Bgez +// AssemblerMIPS32r6Test.Blez +// AssemblerMIPS32r6Test.Bgtz +// AssemblerMIPS32r6Test.Blt +// AssemblerMIPS32r6Test.Bge +// AssemblerMIPS32r6Test.Bltu +// AssemblerMIPS32r6Test.Bgeu + +#undef __ + +} // namespace art diff --git a/compiler/utils/mips/assembler_mips_test.cc b/compiler/utils/mips/assembler_mips_test.cc index 56e58849c9..c722d0c333 100644 --- a/compiler/utils/mips/assembler_mips_test.cc +++ b/compiler/utils/mips/assembler_mips_test.cc @@ -731,212 +731,538 @@ TEST_F(AssemblerMIPSTest, Not) { DriverStr(RepeatRR(&mips::MipsAssembler::Not, "nor ${reg1}, ${reg2}, $zero"), "Not"); } +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 = + "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 $a1, $a2, $at\n" + "lui $at, 1\n" + "ori $at, $at, 1\n" + "addu $a1, $a2, $at\n" + "lui $at, 0x1234\n" + "ori $at, $at, 0x5678\n" + "addu $a1, $a2, $at\n"; + DriverStr(expected, "Addiu32"); +} + 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); + __ 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 $a0, 0($a0)\n" - "lb $a0, 0($a1)\n" - "lb $a0, 256($a1)\n" - "lb $a0, 1000($a1)\n" - "ori $at, $zero, 0x8000\n" + "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" - "lb $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" + "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 $a0, 0($at)\n" + "lb $a3, 0($at)\n" "lui $at, 0x1234\n" - "ori $at, 0x5678\n" + "ori $at, $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" + "lb $a3, 0($at)\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" - "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" + "lbu $a3, 0($at)\n" + "lui $at, 0xFFFE\n" + "ori $at, $at, 0x8010\n" "addu $at, $at, $a1\n" - "lbu $a0, 0($at)\n" - "lui $at, 1\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 $a0, 0($at)\n" + "lbu $a3, 0($at)\n" "lui $at, 0x1234\n" - "ori $at, 0x5678\n" + "ori $at, $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" + "lbu $a3, 0($at)\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" - "lbu $a0, 0($at)\n" - - "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" + "lh $a3, 0($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" + "lh $a3, 7($at)\n" + "lui $at, 0x1\n" + "ori $at, $at, 0x7FE8\n" "addu $at, $at, $a1\n" - "lh $a0, 0($at)\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" - "lh $a0, 0($at)\n" - "lh $a0, -256($a1)\n" - "lh $a0, 0xFFFF8000($a1)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" + "lh $a3, 0($at)\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" - "lh $a0, 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" + "lhu $a3, 0($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" + "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 $a0, 0($at)\n" + "lhu $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" + "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" - "lhu $a0, 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" + "lw $a3, 0($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" + "lw $a3, 7($at)\n" + "lui $at, 0x1\n" + "ori $at, $at, 0x7FE8\n" "addu $at, $at, $a1\n" - "lw $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" + "lw $a3, 1($at)\n" + "lui $at, 0x1\n" + "ori $at, $at, 0x7FF0\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" + "lw $a3, 0($at)\n" + "lui $at, 0x1234\n" + "ori $at, $at, 0x5678\n" "addu $at, $at, $a1\n" - "lw $a0, 0($at)\n" + "lw $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" + "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, 0($at)\n" - "lw $a1, 4($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\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" - "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" + "lui $at, 0x1234\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, LoadFromOffset) { } 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" - "lui $at, 0x1234\n" - "ori $at, 0x5678\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 $f0, 0($at)\n" - "lwc1 $f0, -256($a0)\n" - "lwc1 $f0, 0xFFFF8000($a0)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" + "lwc1 $f2, 0($at)\n" + "lui $at, 0x1234\n" + "ori $at, $at, 0x5678\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" - "ldc1 $f0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\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" - "ldc1 $f0, -256($a0)\n" - "ldc1 $f0, 0xFFFF8000($a0)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" + "lui $at, 0x1234\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::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::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::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::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::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::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, -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 $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 $a0, 0($at)\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" + "sb $a3, 0($at)\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" - "sb $a0, 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, 0($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, 7($at)\n" + "lui $at, 0x1\n" + "ori $at, $at, 0x7FE8\n" "addu $at, $at, $a1\n" - "sh $a0, 0($at)\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" + "sh $a3, 0($at)\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" - "sh $a0, 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, 0($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, 7($at)\n" + "lui $at, 0x1\n" + "ori $at, $at, 0x7FE8\n" "addu $at, $at, $a1\n" - "sw $a0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" + "sw $a3, 1($at)\n" + "lui $at, 0x1\n" + "ori $at, $at, 0x7FF0\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" + "sw $a3, 0($at)\n" + "lui $at, 0x1234\n" + "ori $at, $at, 0x5678\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, 0($at)\n" - "sw $a1, 4($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\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" - "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" + "lui $at, 0x1234\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, StoreToOffset) { } 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" - "lui $at, 0x1234\n" - "ori $at, 0x5678\n" + "swc1 $f2, 7($at)\n" + "lui $at, 0x1\n" + "ori $at, $at, 0x7FE8\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" + "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, $at, 0x5678\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" - "sdc1 $f0, 0($at)\n" - "lui $at, 0x1234\n" - "ori $at, 0x5678\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" - "sdc1 $f0, -256($a0)\n" - "sdc1 $f0, 0xFFFF8000($a0)\n" - "lui $at, 0xABCD\n" - "ori $at, 0xEF00\n" + "lui $at, 0x1234\n" + "ori $at, $at, 0x5678\n" "addu $at, $at, $a0\n" "sdc1 $f0, 0($at)\n"; DriverStr(expected, "StoreDToOffset"); @@ -1492,6 +2228,51 @@ TEST_F(AssemblerMIPSTest, Bc1t) { DriverStr(expected, "Bc1t"); } +/////////////////////// +// Loading Constants // +/////////////////////// + +TEST_F(AssemblerMIPSTest, LoadConst32) { + // IsUint<16>(value) + __ LoadConst32(mips::V0, 0); + __ LoadConst32(mips::V0, 65535); + // IsInt<16>(value) + __ LoadConst32(mips::V0, -1); + __ LoadConst32(mips::V0, -32768); + // Everything else + __ LoadConst32(mips::V0, 65536); + __ LoadConst32(mips::V0, 65537); + __ LoadConst32(mips::V0, 2147483647); + __ LoadConst32(mips::V0, -32769); + __ LoadConst32(mips::V0, -65536); + __ LoadConst32(mips::V0, -65537); + __ LoadConst32(mips::V0, -2147483647); + __ LoadConst32(mips::V0, -2147483648); + + const char* expected = + // IsUint<16>(value) + "ori $v0, $zero, 0\n" // __ LoadConst32(mips::V0, 0); + "ori $v0, $zero, 65535\n" // __ LoadConst32(mips::V0, 65535); + // IsInt<16>(value) + "addiu $v0, $zero, -1\n" // __ LoadConst32(mips::V0, -1); + "addiu $v0, $zero, -32768\n" // __ LoadConst32(mips::V0, -32768); + // Everything else + "lui $v0, 1\n" // __ LoadConst32(mips::V0, 65536); + "lui $v0, 1\n" // __ LoadConst32(mips::V0, 65537); + "ori $v0, 1\n" // " + "lui $v0, 32767\n" // __ LoadConst32(mips::V0, 2147483647); + "ori $v0, 65535\n" // " + "lui $v0, 65535\n" // __ LoadConst32(mips::V0, -32769); + "ori $v0, 32767\n" // " + "lui $v0, 65535\n" // __ LoadConst32(mips::V0, -65536); + "lui $v0, 65534\n" // __ LoadConst32(mips::V0, -65537); + "ori $v0, 65535\n" // " + "lui $v0, 32768\n" // __ LoadConst32(mips::V0, -2147483647); + "ori $v0, 1\n" // " + "lui $v0, 32768\n"; // __ LoadConst32(mips::V0, -2147483648); + DriverStr(expected, "LoadConst32"); +} + #undef __ } // namespace art |