summaryrefslogtreecommitdiff
path: root/compiler/utils/mips/assembler_mips.h
diff options
context:
space:
mode:
author Alexey Frunze <Alexey.Frunze@imgtec.com> 2016-09-02 22:14:06 -0700
committer Alexey Frunze <Alexey.Frunze@imgtec.com> 2016-09-15 19:11:14 -0700
commitf58b24831f7203e248798dce4c62bf61c51ba15d (patch)
treeab7c886781ba6328b350513352b763cd433627a3 /compiler/utils/mips/assembler_mips.h
parent7d26164308e9eab5c596a19b841e4ab1c27828a8 (diff)
MIPS32: Improve storing of constants in fields and array elements
Test: booted MIPS32 in QEMU Test: test-art-target-run-test-optimizing on CI20 Test: test-art-host-gtest Change-Id: Ifcf8c1e215e3768711c391e8da6f663bba71f8d9
Diffstat (limited to 'compiler/utils/mips/assembler_mips.h')
-rw-r--r--compiler/utils/mips/assembler_mips.h83
1 files changed, 49 insertions, 34 deletions
diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h
index 099620ccb8..e1255f7f23 100644
--- a/compiler/utils/mips/assembler_mips.h
+++ b/compiler/utils/mips/assembler_mips.h
@@ -496,46 +496,61 @@ class MipsAssembler FINAL : public Assembler, public JNIMacroAssembler<PointerSi
public:
template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void StoreConst32ToOffset(int32_t value,
- Register base,
- int32_t offset,
- Register temp,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
+ void StoreConstToOffset(StoreOperandType type,
+ int64_t value,
+ Register base,
+ int32_t offset,
+ Register temp,
+ ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
+ // We permit `base` and `temp` to coincide (however, we check that neither is AT),
+ // in which case the `base` register may be overwritten in the process.
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 {
- LoadConst32(temp, value);
- }
- Sw(temp, base, offset);
- null_checker();
- }
-
- template <typename ImplicitNullChecker = NoImplicitNullChecker>
- void StoreConst64ToOffset(int64_t value,
- Register base,
- int32_t offset,
- Register temp,
- ImplicitNullChecker null_checker = NoImplicitNullChecker()) {
- CHECK_NE(temp, AT); // Must not use AT as temp, so as not to overwrite the adjusted base.
- AdjustBaseAndOffset(base, offset, /* is_doubleword */ true);
+ AdjustBaseAndOffset(base, offset, /* is_doubleword */ (type == kStoreDoubleword));
uint32_t low = Low32Bits(value);
uint32_t high = High32Bits(value);
+ Register reg;
+ // If the adjustment left `base` unchanged and equal to `temp`, we can't use `temp`
+ // to load and hold the value but we can use AT instead as AT hasn't been used yet.
+ // Otherwise, `temp` can be used for the value. And if `temp` is the same as the
+ // original `base` (that is, `base` prior to the adjustment), the original `base`
+ // register will be overwritten.
+ if (base == temp) {
+ temp = AT;
+ }
if (low == 0) {
- Sw(ZERO, base, offset);
+ reg = ZERO;
} else {
- LoadConst32(temp, low);
- Sw(temp, base, offset);
+ reg = temp;
+ LoadConst32(reg, low);
}
- null_checker();
- if (high == 0) {
- Sw(ZERO, base, offset + kMipsWordSize);
- } else {
- if (high != low) {
- LoadConst32(temp, high);
- }
- Sw(temp, base, offset + kMipsWordSize);
+ switch (type) {
+ case kStoreByte:
+ Sb(reg, base, offset);
+ break;
+ case kStoreHalfword:
+ Sh(reg, base, offset);
+ break;
+ case kStoreWord:
+ Sw(reg, base, offset);
+ break;
+ case kStoreDoubleword:
+ Sw(reg, base, offset);
+ null_checker();
+ if (high == 0) {
+ reg = ZERO;
+ } else {
+ reg = temp;
+ if (high != low) {
+ LoadConst32(reg, high);
+ }
+ }
+ Sw(reg, base, offset + kMipsWordSize);
+ break;
+ default:
+ LOG(FATAL) << "UNREACHABLE";
+ }
+ if (type != kStoreDoubleword) {
+ null_checker();
}
}