diff options
Diffstat (limited to 'compiler/utils')
| -rw-r--r-- | compiler/utils/arm/assembler_arm.h | 6 | ||||
| -rw-r--r-- | compiler/utils/arm64/assembler_arm64.h | 7 | ||||
| -rw-r--r-- | compiler/utils/assembler.h | 104 | ||||
| -rw-r--r-- | compiler/utils/label.h | 129 | ||||
| -rw-r--r-- | compiler/utils/mips/assembler_mips.h | 7 | ||||
| -rw-r--r-- | compiler/utils/mips64/assembler_mips64.cc | 202 | ||||
| -rw-r--r-- | compiler/utils/mips64/assembler_mips64.h | 50 | ||||
| -rw-r--r-- | compiler/utils/x86/assembler_x86.cc | 34 | ||||
| -rw-r--r-- | compiler/utils/x86/assembler_x86.h | 12 | ||||
| -rw-r--r-- | compiler/utils/x86/assembler_x86_test.cc | 63 | ||||
| -rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.cc | 72 | ||||
| -rw-r--r-- | compiler/utils/x86_64/assembler_x86_64.h | 20 | ||||
| -rw-r--r-- | compiler/utils/x86_64/assembler_x86_64_test.cc | 130 |
13 files changed, 731 insertions, 105 deletions
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h index a4d1837748..967b191d32 100644 --- a/compiler/utils/arm/assembler_arm.h +++ b/compiler/utils/arm/assembler_arm.h @@ -834,8 +834,6 @@ class ArmAssembler : public Assembler { static bool IsInstructionForExceptionHandling(uintptr_t pc); - virtual void Bind(Label* label) = 0; - virtual void CompareAndBranchIfZero(Register r, Label* label) = 0; virtual void CompareAndBranchIfNonZero(Register r, Label* label) = 0; @@ -985,6 +983,10 @@ class ArmAssembler : public Assembler { } } + void Jump(Label* label) OVERRIDE { + b(label); + } + protected: // Returns whether or not the given register is used for passing parameters. static int RegisterCompare(const Register* reg1, const Register* reg2) { diff --git a/compiler/utils/arm64/assembler_arm64.h b/compiler/utils/arm64/assembler_arm64.h index 8e85fe96ab..7b25b8f3f5 100644 --- a/compiler/utils/arm64/assembler_arm64.h +++ b/compiler/utils/arm64/assembler_arm64.h @@ -193,6 +193,13 @@ class Arm64Assembler FINAL : public Assembler { // Unpoison a heap reference contained in `reg` if heap poisoning is enabled. void MaybeUnpoisonHeapReference(vixl::Register reg); + void Bind(Label* label ATTRIBUTE_UNUSED) OVERRIDE { + UNIMPLEMENTED(FATAL) << "Do not use Bind for ARM64"; + } + void Jump(Label* label ATTRIBUTE_UNUSED) OVERRIDE { + UNIMPLEMENTED(FATAL) << "Do not use Jump for ARM64"; + } + private: static vixl::Register reg_x(int code) { CHECK(code < kNumberOfXRegisters) << code; diff --git a/compiler/utils/assembler.h b/compiler/utils/assembler.h index 64d76b881d..1088cb1bbd 100644 --- a/compiler/utils/assembler.h +++ b/compiler/utils/assembler.h @@ -23,6 +23,7 @@ #include "base/logging.h" #include "base/macros.h" #include "arm/constants_arm.h" +#include "label.h" #include "managed_register.h" #include "memory_region.h" #include "mips/constants_mips.h" @@ -35,106 +36,6 @@ namespace art { class Assembler; class AssemblerBuffer; -class AssemblerFixup; - -namespace arm { - class ArmAssembler; - class Arm32Assembler; - class Thumb2Assembler; -} -namespace arm64 { - class Arm64Assembler; -} -namespace mips { - class MipsAssembler; -} -namespace mips64 { - class Mips64Assembler; -} -namespace x86 { - class X86Assembler; - class NearLabel; -} -namespace x86_64 { - class X86_64Assembler; - class NearLabel; -} - -class ExternalLabel { - public: - ExternalLabel(const char* name_in, uintptr_t address_in) - : name_(name_in), address_(address_in) { - DCHECK(name_in != nullptr); - } - - const char* name() const { return name_; } - uintptr_t address() const { - return address_; - } - - private: - const char* name_; - const uintptr_t address_; -}; - -class Label { - public: - Label() : position_(0) {} - - ~Label() { - // Assert if label is being destroyed with unresolved branches pending. - CHECK(!IsLinked()); - } - - // Returns the position for bound and linked labels. Cannot be used - // for unused labels. - int Position() const { - CHECK(!IsUnused()); - return IsBound() ? -position_ - sizeof(void*) : position_ - sizeof(void*); - } - - int LinkPosition() const { - CHECK(IsLinked()); - return position_ - sizeof(void*); - } - - bool IsBound() const { return position_ < 0; } - bool IsUnused() const { return position_ == 0; } - bool IsLinked() const { return position_ > 0; } - - private: - int position_; - - void Reinitialize() { - position_ = 0; - } - - void BindTo(int position) { - CHECK(!IsBound()); - position_ = -position - sizeof(void*); - CHECK(IsBound()); - } - - void LinkTo(int position) { - CHECK(!IsBound()); - position_ = position + sizeof(void*); - CHECK(IsLinked()); - } - - friend class arm::ArmAssembler; - friend class arm::Arm32Assembler; - friend class arm::Thumb2Assembler; - friend class arm64::Arm64Assembler; - friend class mips::MipsAssembler; - friend class mips64::Mips64Assembler; - friend class x86::X86Assembler; - friend class x86::NearLabel; - friend class x86_64::X86_64Assembler; - friend class x86_64::NearLabel; - - DISALLOW_COPY_AND_ASSIGN(Label); -}; - // Assembler fixups are positions in generated code that require processing // after the code has been copied to executable memory. This includes building @@ -534,6 +435,9 @@ class Assembler { // and branch to a ExceptionSlowPath if it is. virtual void ExceptionPoll(ManagedRegister scratch, size_t stack_adjust) = 0; + virtual void Bind(Label* label) = 0; + virtual void Jump(Label* label) = 0; + virtual ~Assembler() {} /** diff --git a/compiler/utils/label.h b/compiler/utils/label.h new file mode 100644 index 0000000000..ff4a1a4333 --- /dev/null +++ b/compiler/utils/label.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2011 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. + */ + +#ifndef ART_COMPILER_UTILS_LABEL_H_ +#define ART_COMPILER_UTILS_LABEL_H_ + +#include "base/logging.h" +#include "base/macros.h" + +namespace art { + +class Assembler; +class AssemblerBuffer; +class AssemblerFixup; + +namespace arm { + class ArmAssembler; + class Arm32Assembler; + class Thumb2Assembler; +} +namespace arm64 { + class Arm64Assembler; +} +namespace mips { + class MipsAssembler; +} +namespace mips64 { + class Mips64Assembler; +} +namespace x86 { + class X86Assembler; + class NearLabel; +} +namespace x86_64 { + class X86_64Assembler; + class NearLabel; +} + +class ExternalLabel { + public: + ExternalLabel(const char* name_in, uintptr_t address_in) + : name_(name_in), address_(address_in) { + DCHECK(name_in != nullptr); + } + + const char* name() const { return name_; } + uintptr_t address() const { + return address_; + } + + private: + const char* name_; + const uintptr_t address_; +}; + +class Label { + public: + Label() : position_(0) {} + + ~Label() { + // Assert if label is being destroyed with unresolved branches pending. + CHECK(!IsLinked()); + } + + // Returns the position for bound and linked labels. Cannot be used + // for unused labels. + int Position() const { + CHECK(!IsUnused()); + return IsBound() ? -position_ - sizeof(void*) : position_ - sizeof(void*); + } + + int LinkPosition() const { + CHECK(IsLinked()); + return position_ - sizeof(void*); + } + + bool IsBound() const { return position_ < 0; } + bool IsUnused() const { return position_ == 0; } + bool IsLinked() const { return position_ > 0; } + + private: + int position_; + + void Reinitialize() { + position_ = 0; + } + + void BindTo(int position) { + CHECK(!IsBound()); + position_ = -position - sizeof(void*); + CHECK(IsBound()); + } + + void LinkTo(int position) { + CHECK(!IsBound()); + position_ = position + sizeof(void*); + CHECK(IsLinked()); + } + + friend class arm::ArmAssembler; + friend class arm::Arm32Assembler; + friend class arm::Thumb2Assembler; + friend class arm64::Arm64Assembler; + friend class mips::MipsAssembler; + friend class mips64::Mips64Assembler; + friend class x86::X86Assembler; + friend class x86::NearLabel; + friend class x86_64::X86_64Assembler; + friend class x86_64::NearLabel; + + DISALLOW_COPY_AND_ASSIGN(Label); +}; + +} // namespace art + +#endif // ART_COMPILER_UTILS_LABEL_H_ diff --git a/compiler/utils/mips/assembler_mips.h b/compiler/utils/mips/assembler_mips.h index 6c8b162d62..378a59cb3e 100644 --- a/compiler/utils/mips/assembler_mips.h +++ b/compiler/utils/mips/assembler_mips.h @@ -150,6 +150,13 @@ class MipsAssembler FINAL : public Assembler { void EmitJump(Label* label, bool link); void Bind(Label* label, bool is_jump); + void Bind(Label* label) OVERRIDE { + Bind(label, false); + } + void Jump(Label* label) OVERRIDE { + EmitJump(label, false); + } + // // Overridden common assembler high-level functionality // diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc index 24ea9e25db..b078f3e4cf 100644 --- a/compiler/utils/mips64/assembler_mips64.cc +++ b/compiler/utils/mips64/assembler_mips64.cc @@ -44,6 +44,32 @@ void Mips64Assembler::EmitR(int opcode, GpuRegister rs, GpuRegister rt, GpuRegis Emit(encoding); } +void Mips64Assembler::EmitRsd(int opcode, GpuRegister rs, GpuRegister rd, + int shamt, int funct) { + CHECK_NE(rs, kNoGpuRegister); + CHECK_NE(rd, kNoGpuRegister); + uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | + static_cast<uint32_t>(rs) << kRsShift | + static_cast<uint32_t>(ZERO) << kRtShift | + static_cast<uint32_t>(rd) << kRdShift | + shamt << kShamtShift | + funct; + Emit(encoding); +} + +void Mips64Assembler::EmitRtd(int opcode, GpuRegister rt, GpuRegister rd, + int shamt, int funct) { + CHECK_NE(rt, kNoGpuRegister); + CHECK_NE(rd, kNoGpuRegister); + uint32_t encoding = static_cast<uint32_t>(opcode) << kOpcodeShift | + static_cast<uint32_t>(ZERO) << kRsShift | + static_cast<uint32_t>(rt) << kRtShift | + static_cast<uint32_t>(rd) << kRdShift | + shamt << kShamtShift | + funct; + Emit(encoding); +} + void Mips64Assembler::EmitI(int opcode, GpuRegister rs, GpuRegister rt, uint16_t imm) { CHECK_NE(rs, kNoGpuRegister); CHECK_NE(rt, kNoGpuRegister); @@ -235,6 +261,14 @@ void Mips64Assembler::Nor(GpuRegister rd, GpuRegister rs, GpuRegister rt) { EmitR(0, rs, rt, rd, 0, 0x27); } +void Mips64Assembler::Bitswap(GpuRegister rd, GpuRegister rt) { + EmitRtd(0x1f, rt, rd, 0x0, 0x20); +} + +void Mips64Assembler::Dbitswap(GpuRegister rd, GpuRegister rt) { + EmitRtd(0x1f, rt, rd, 0x0, 0x24); +} + void Mips64Assembler::Seb(GpuRegister rd, GpuRegister rt) { EmitR(0x1f, static_cast<GpuRegister>(0), rt, rd, 0x10, 0x20); } @@ -243,12 +277,44 @@ void Mips64Assembler::Seh(GpuRegister rd, GpuRegister rt) { EmitR(0x1f, static_cast<GpuRegister>(0), rt, rd, 0x18, 0x20); } +void Mips64Assembler::Dsbh(GpuRegister rd, GpuRegister rt) { + EmitRtd(0x1f, rt, rd, 0x2, 0x24); +} + +void Mips64Assembler::Dshd(GpuRegister rd, GpuRegister rt) { + EmitRtd(0x1f, rt, rd, 0x5, 0x24); +} + void Mips64Assembler::Dext(GpuRegister rt, GpuRegister rs, int pos, int size_less_one) { DCHECK(0 <= pos && pos < 32) << pos; DCHECK(0 <= size_less_one && size_less_one < 32) << size_less_one; EmitR(0x1f, rs, rt, static_cast<GpuRegister>(size_less_one), pos, 3); } +void Mips64Assembler::Wsbh(GpuRegister rd, GpuRegister rt) { + EmitRtd(0x1f, rt, rd, 2, 0x20); +} + +void Mips64Assembler::Sc(GpuRegister rt, GpuRegister base, int16_t imm9) { + DCHECK((-256 <= imm9) && (imm9 < 256)); + EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x26); +} + +void Mips64Assembler::Scd(GpuRegister rt, GpuRegister base, int16_t imm9) { + DCHECK((-256 <= imm9) && (imm9 < 256)); + EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x27); +} + +void Mips64Assembler::Ll(GpuRegister rt, GpuRegister base, int16_t imm9) { + DCHECK((-256 <= imm9) && (imm9 < 256)); + EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x36); +} + +void Mips64Assembler::Lld(GpuRegister rt, GpuRegister base, int16_t imm9) { + DCHECK((-256 <= imm9) && (imm9 < 256)); + EmitI(0x1f, base, rt, ((imm9 & 0x1FF) << 7) | 0x37); +} + void Mips64Assembler::Sll(GpuRegister rd, GpuRegister rt, int shamt) { EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x00); } @@ -257,6 +323,10 @@ void Mips64Assembler::Srl(GpuRegister rd, GpuRegister rt, int shamt) { EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x02); } +void Mips64Assembler::Rotr(GpuRegister rd, GpuRegister rt, int shamt) { + EmitR(0, static_cast<GpuRegister>(1), rt, rd, shamt, 0x02); +} + void Mips64Assembler::Sra(GpuRegister rd, GpuRegister rt, int shamt) { EmitR(0, static_cast<GpuRegister>(0), rt, rd, shamt, 0x03); } @@ -414,6 +484,30 @@ void Mips64Assembler::Jal(uint32_t addr26) { Nop(); } +void Mips64Assembler::Seleqz(GpuRegister rd, GpuRegister rs, GpuRegister rt) { + EmitR(0, rs, rt, rd, 0, 0x35); +} + +void Mips64Assembler::Selnez(GpuRegister rd, GpuRegister rs, GpuRegister rt) { + EmitR(0, rs, rt, rd, 0, 0x37); +} + +void Mips64Assembler::Clz(GpuRegister rd, GpuRegister rs) { + EmitRsd(0, rs, rd, 0x01, 0x10); +} + +void Mips64Assembler::Clo(GpuRegister rd, GpuRegister rs) { + EmitRsd(0, rs, rd, 0x01, 0x11); +} + +void Mips64Assembler::Dclz(GpuRegister rd, GpuRegister rs) { + EmitRsd(0, rs, rd, 0x01, 0x12); +} + +void Mips64Assembler::Dclo(GpuRegister rd, GpuRegister rs) { + EmitRsd(0, rs, rd, 0x01, 0x13); +} + void Mips64Assembler::Jalr(GpuRegister rd, GpuRegister rs) { EmitR(0, rs, static_cast<GpuRegister>(0), rd, 0, 0x09); Nop(); @@ -543,6 +637,22 @@ void Mips64Assembler::DivD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { EmitFR(0x11, 0x11, ft, fs, fd, 0x3); } +void Mips64Assembler::SqrtS(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x4); +} + +void Mips64Assembler::SqrtD(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x4); +} + +void Mips64Assembler::AbsS(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x5); +} + +void Mips64Assembler::AbsD(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x5); +} + void Mips64Assembler::MovS(FpuRegister fd, FpuRegister fs) { EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x6); } @@ -559,6 +669,94 @@ void Mips64Assembler::NegD(FpuRegister fd, FpuRegister fs) { EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x7); } +void Mips64Assembler::RoundLS(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x8); +} + +void Mips64Assembler::RoundLD(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x8); +} + +void Mips64Assembler::RoundWS(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xc); +} + +void Mips64Assembler::RoundWD(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xc); +} + +void Mips64Assembler::CeilLS(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xa); +} + +void Mips64Assembler::CeilLD(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xa); +} + +void Mips64Assembler::CeilWS(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xe); +} + +void Mips64Assembler::CeilWD(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xe); +} + +void Mips64Assembler::FloorLS(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xb); +} + +void Mips64Assembler::FloorLD(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xb); +} + +void Mips64Assembler::FloorWS(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0xf); +} + +void Mips64Assembler::FloorWD(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0xf); +} + +void Mips64Assembler::SelS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { + EmitFR(0x11, 0x10, ft, fs, fd, 0x10); +} + +void Mips64Assembler::SelD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { + EmitFR(0x11, 0x11, ft, fs, fd, 0x10); +} + +void Mips64Assembler::RintS(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1a); +} + +void Mips64Assembler::RintD(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1a); +} + +void Mips64Assembler::ClassS(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x1b); +} + +void Mips64Assembler::ClassD(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x11, static_cast<FpuRegister>(0), fs, fd, 0x1b); +} + +void Mips64Assembler::MinS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { + EmitFR(0x11, 0x10, ft, fs, fd, 0x1c); +} + +void Mips64Assembler::MinD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { + EmitFR(0x11, 0x11, ft, fs, fd, 0x1c); +} + +void Mips64Assembler::MaxS(FpuRegister fd, FpuRegister fs, FpuRegister ft) { + EmitFR(0x11, 0x10, ft, fs, fd, 0x1e); +} + +void Mips64Assembler::MaxD(FpuRegister fd, FpuRegister fs, FpuRegister ft) { + EmitFR(0x11, 0x11, ft, fs, fd, 0x1e); +} + void Mips64Assembler::Cvtsw(FpuRegister fd, FpuRegister fs) { EmitFR(0x11, 0x14, static_cast<FpuRegister>(0), fs, fd, 0x20); } @@ -575,6 +773,10 @@ void Mips64Assembler::Cvtds(FpuRegister fd, FpuRegister fs) { EmitFR(0x11, 0x10, static_cast<FpuRegister>(0), fs, fd, 0x21); } +void Mips64Assembler::Cvtdl(FpuRegister fd, FpuRegister fs) { + EmitFR(0x11, 0x15, static_cast<FpuRegister>(0), fs, fd, 0x21); +} + void Mips64Assembler::Mfc1(GpuRegister rt, FpuRegister fs) { EmitFR(0x11, 0x00, static_cast<FpuRegister>(rt), fs, static_cast<FpuRegister>(0), 0x0); } diff --git a/compiler/utils/mips64/assembler_mips64.h b/compiler/utils/mips64/assembler_mips64.h index 31130ea43d..c170313728 100644 --- a/compiler/utils/mips64/assembler_mips64.h +++ b/compiler/utils/mips64/assembler_mips64.h @@ -90,12 +90,22 @@ class Mips64Assembler FINAL : public Assembler { void Xori(GpuRegister rt, GpuRegister rs, uint16_t imm16); void Nor(GpuRegister rd, GpuRegister rs, GpuRegister rt); + void Bitswap(GpuRegister rd, GpuRegister rt); // R6 + void Dbitswap(GpuRegister rd, GpuRegister rt); // R6 void Seb(GpuRegister rd, GpuRegister rt); // R2+ void Seh(GpuRegister rd, GpuRegister rt); // R2+ + void Dsbh(GpuRegister rd, GpuRegister rt); // R2+ + void Dshd(GpuRegister rd, GpuRegister rt); // R2+ void Dext(GpuRegister rs, GpuRegister rt, int pos, int size_less_one); // MIPS64 + void Wsbh(GpuRegister rd, GpuRegister rt); + void Sc(GpuRegister rt, GpuRegister base, int16_t imm9 = 0); + void Scd(GpuRegister rt, GpuRegister base, int16_t imm9 = 0); + void Ll(GpuRegister rt, GpuRegister base, int16_t imm9 = 0); + void Lld(GpuRegister rt, GpuRegister base, int16_t imm9 = 0); void Sll(GpuRegister rd, GpuRegister rt, int shamt); void Srl(GpuRegister rd, GpuRegister rt, int shamt); + void Rotr(GpuRegister rd, GpuRegister rt, int shamt); void Sra(GpuRegister rd, GpuRegister rt, int shamt); void Sllv(GpuRegister rd, GpuRegister rt, GpuRegister rs); void Srlv(GpuRegister rd, GpuRegister rt, GpuRegister rs); @@ -133,6 +143,12 @@ class Mips64Assembler FINAL : public Assembler { void Sltu(GpuRegister rd, GpuRegister rs, GpuRegister rt); void Slti(GpuRegister rt, GpuRegister rs, uint16_t imm16); void Sltiu(GpuRegister rt, GpuRegister rs, uint16_t imm16); + void Seleqz(GpuRegister rd, GpuRegister rs, GpuRegister rt); + void Selnez(GpuRegister rd, GpuRegister rs, GpuRegister rt); + void Clz(GpuRegister rd, GpuRegister rs); + void Clo(GpuRegister rd, GpuRegister rs); + void Dclz(GpuRegister rd, GpuRegister rs); + void Dclo(GpuRegister rd, GpuRegister rs); void Beq(GpuRegister rs, GpuRegister rt, uint16_t imm16); void Bne(GpuRegister rs, GpuRegister rt, uint16_t imm16); @@ -165,15 +181,42 @@ class Mips64Assembler FINAL : public Assembler { void SubD(FpuRegister fd, FpuRegister fs, FpuRegister ft); void MulD(FpuRegister fd, FpuRegister fs, FpuRegister ft); void DivD(FpuRegister fd, FpuRegister fs, FpuRegister ft); + void SqrtS(FpuRegister fd, FpuRegister fs); + void SqrtD(FpuRegister fd, FpuRegister fs); + void AbsS(FpuRegister fd, FpuRegister fs); + void AbsD(FpuRegister fd, FpuRegister fs); void MovS(FpuRegister fd, FpuRegister fs); void MovD(FpuRegister fd, FpuRegister fs); void NegS(FpuRegister fd, FpuRegister fs); void NegD(FpuRegister fd, FpuRegister fs); + void RoundLS(FpuRegister fd, FpuRegister fs); + void RoundLD(FpuRegister fd, FpuRegister fs); + void RoundWS(FpuRegister fd, FpuRegister fs); + void RoundWD(FpuRegister fd, FpuRegister fs); + void CeilLS(FpuRegister fd, FpuRegister fs); + void CeilLD(FpuRegister fd, FpuRegister fs); + void CeilWS(FpuRegister fd, FpuRegister fs); + void CeilWD(FpuRegister fd, FpuRegister fs); + void FloorLS(FpuRegister fd, FpuRegister fs); + void FloorLD(FpuRegister fd, FpuRegister fs); + void FloorWS(FpuRegister fd, FpuRegister fs); + void FloorWD(FpuRegister fd, FpuRegister fs); + void SelS(FpuRegister fd, FpuRegister fs, FpuRegister ft); + void SelD(FpuRegister fd, FpuRegister fs, FpuRegister ft); + void RintS(FpuRegister fd, FpuRegister fs); + void RintD(FpuRegister fd, FpuRegister fs); + void ClassS(FpuRegister fd, FpuRegister fs); + void ClassD(FpuRegister fd, FpuRegister fs); + void MinS(FpuRegister fd, FpuRegister fs, FpuRegister ft); + void MinD(FpuRegister fd, FpuRegister fs, FpuRegister ft); + void MaxS(FpuRegister fd, FpuRegister fs, FpuRegister ft); + void MaxD(FpuRegister fd, FpuRegister fs, FpuRegister ft); void Cvtsw(FpuRegister fd, FpuRegister fs); void Cvtdw(FpuRegister fd, FpuRegister fs); void Cvtsd(FpuRegister fd, FpuRegister fs); void Cvtds(FpuRegister fd, FpuRegister fs); + void Cvtdl(FpuRegister fd, FpuRegister fs); void Mfc1(GpuRegister rt, FpuRegister fs); void Mtc1(GpuRegister rt, FpuRegister fs); @@ -197,7 +240,10 @@ class Mips64Assembler FINAL : public Assembler { void Addiu32(GpuRegister rt, GpuRegister rs, int32_t value, GpuRegister rtmp = AT); void Daddiu64(GpuRegister rt, GpuRegister rs, int64_t value, GpuRegister rtmp = AT); // MIPS64 - void Bind(Label* label); // R6 + void Bind(Label* label) OVERRIDE; // R6 + void Jump(Label* label) OVERRIDE { + B(label); + } void B(Label* label); // R6 void Jalr(Label* label, GpuRegister indirect_reg = RA); // R6 // TODO: implement common for R6 and non-R6 interface for conditional branches? @@ -342,6 +388,8 @@ class Mips64Assembler FINAL : public Assembler { private: void EmitR(int opcode, GpuRegister rs, GpuRegister rt, GpuRegister rd, int shamt, int funct); + void EmitRsd(int opcode, GpuRegister rs, GpuRegister rd, int shamt, int funct); + void EmitRtd(int opcode, GpuRegister rt, GpuRegister rd, int shamt, int funct); void EmitI(int opcode, GpuRegister rs, GpuRegister rt, uint16_t imm); void EmitI21(int opcode, GpuRegister rs, uint32_t imm21); void EmitJ(int opcode, uint32_t addr26); diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc index e3962b4d69..04e815aa1d 100644 --- a/compiler/utils/x86/assembler_x86.cc +++ b/compiler/utils/x86/assembler_x86.cc @@ -158,6 +158,20 @@ void X86Assembler::bswapl(Register dst) { EmitUint8(0xC8 + dst); } +void X86Assembler::bsfl(Register dst, Register src) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitUint8(0x0F); + EmitUint8(0xBC); + EmitRegisterOperand(dst, src); +} + +void X86Assembler::bsfl(Register dst, const Address& src) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitUint8(0x0F); + EmitUint8(0xBC); + EmitOperand(dst, src); +} + void X86Assembler::bsrl(Register dst, Register src) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitUint8(0x0F); @@ -1423,6 +1437,26 @@ void X86Assembler::shrd(Register dst, Register src, const Immediate& imm) { } +void X86Assembler::roll(Register reg, const Immediate& imm) { + EmitGenericShift(0, Operand(reg), imm); +} + + +void X86Assembler::roll(Register operand, Register shifter) { + EmitGenericShift(0, Operand(operand), shifter); +} + + +void X86Assembler::rorl(Register reg, const Immediate& imm) { + EmitGenericShift(1, Operand(reg), imm); +} + + +void X86Assembler::rorl(Register operand, Register shifter) { + EmitGenericShift(1, Operand(operand), shifter); +} + + void X86Assembler::negl(Register reg) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitUint8(0xF7); diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h index 7d7b3d347b..93ecdf52fe 100644 --- a/compiler/utils/x86/assembler_x86.h +++ b/compiler/utils/x86/assembler_x86.h @@ -319,9 +319,16 @@ class X86Assembler FINAL : public Assembler { void movntl(const Address& dst, Register src); void bswapl(Register dst); + void bsfl(Register dst, Register src); + void bsfl(Register dst, const Address& src); void bsrl(Register dst, Register src); void bsrl(Register dst, const Address& src); + void rorl(Register reg, const Immediate& imm); + void rorl(Register operand, Register shifter); + void roll(Register reg, const Immediate& imm); + void roll(Register operand, Register shifter); + void movzxb(Register dst, ByteRegister src); void movzxb(Register dst, const Address& src); void movsxb(Register dst, ByteRegister src); @@ -593,7 +600,10 @@ class X86Assembler FINAL : public Assembler { // int PreferredLoopAlignment() { return 16; } void Align(int alignment, int offset); - void Bind(Label* label); + void Bind(Label* label) OVERRIDE; + void Jump(Label* label) OVERRIDE { + jmp(label); + } void Bind(NearLabel* label); // diff --git a/compiler/utils/x86/assembler_x86_test.cc b/compiler/utils/x86/assembler_x86_test.cc index 9ac54afc11..16f9db43fb 100644 --- a/compiler/utils/x86/assembler_x86_test.cc +++ b/compiler/utils/x86/assembler_x86_test.cc @@ -32,6 +32,10 @@ TEST(AssemblerX86, CreateBuffer) { class AssemblerX86Test : public AssemblerTest<x86::X86Assembler, x86::Register, x86::XmmRegister, x86::Immediate> { + public: + typedef AssemblerTest<x86::X86Assembler, x86::Register, + x86::XmmRegister, x86::Immediate> Base; + protected: std::string GetArchitectureString() OVERRIDE { return "x86"; @@ -230,6 +234,19 @@ TEST_F(AssemblerX86Test, RepMovsw) { DriverStr(expected, "rep_movsw"); } +TEST_F(AssemblerX86Test, Bsfl) { + DriverStr(RepeatRR(&x86::X86Assembler::bsfl, "bsfl %{reg2}, %{reg1}"), "bsfl"); +} + +TEST_F(AssemblerX86Test, BsflAddress) { + GetAssembler()->bsfl(x86::Register(x86::EDI), x86::Address( + x86::Register(x86::EDI), x86::Register(x86::EBX), x86::TIMES_4, 12)); + const char* expected = + "bsfl 0xc(%EDI,%EBX,4), %EDI\n"; + + DriverStr(expected, "bsfl_address"); +} + TEST_F(AssemblerX86Test, Bsrl) { DriverStr(RepeatRR(&x86::X86Assembler::bsrl, "bsrl %{reg2}, %{reg1}"), "bsrl"); } @@ -243,6 +260,52 @@ TEST_F(AssemblerX86Test, BsrlAddress) { DriverStr(expected, "bsrl_address"); } +// Rorl only allows CL as the shift count. +std::string rorl_fn(AssemblerX86Test::Base* assembler_test, x86::X86Assembler* assembler) { + std::ostringstream str; + + std::vector<x86::Register*> registers = assembler_test->GetRegisters(); + + x86::Register shifter(x86::ECX); + for (auto reg : registers) { + assembler->rorl(*reg, shifter); + str << "rorl %cl, %" << assembler_test->GetRegisterName(*reg) << "\n"; + } + + return str.str(); +} + +TEST_F(AssemblerX86Test, RorlReg) { + DriverFn(&rorl_fn, "rorl"); +} + +TEST_F(AssemblerX86Test, RorlImm) { + DriverStr(RepeatRI(&x86::X86Assembler::rorl, 1U, "rorl ${imm}, %{reg}"), "rorli"); +} + +// Roll only allows CL as the shift count. +std::string roll_fn(AssemblerX86Test::Base* assembler_test, x86::X86Assembler* assembler) { + std::ostringstream str; + + std::vector<x86::Register*> registers = assembler_test->GetRegisters(); + + x86::Register shifter(x86::ECX); + for (auto reg : registers) { + assembler->roll(*reg, shifter); + str << "roll %cl, %" << assembler_test->GetRegisterName(*reg) << "\n"; + } + + return str.str(); +} + +TEST_F(AssemblerX86Test, RollReg) { + DriverFn(&roll_fn, "roll"); +} + +TEST_F(AssemblerX86Test, RollImm) { + DriverStr(RepeatRI(&x86::X86Assembler::roll, 1U, "roll ${imm}, %{reg}"), "rolli"); +} + ///////////////// // Near labels // ///////////////// diff --git a/compiler/utils/x86_64/assembler_x86_64.cc b/compiler/utils/x86_64/assembler_x86_64.cc index 88ea9900fe..89d7915f04 100644 --- a/compiler/utils/x86_64/assembler_x86_64.cc +++ b/compiler/utils/x86_64/assembler_x86_64.cc @@ -1866,6 +1866,46 @@ void X86_64Assembler::sarq(CpuRegister operand, CpuRegister shifter) { } +void X86_64Assembler::roll(CpuRegister reg, const Immediate& imm) { + EmitGenericShift(false, 0, reg, imm); +} + + +void X86_64Assembler::roll(CpuRegister operand, CpuRegister shifter) { + EmitGenericShift(false, 0, operand, shifter); +} + + +void X86_64Assembler::rorl(CpuRegister reg, const Immediate& imm) { + EmitGenericShift(false, 1, reg, imm); +} + + +void X86_64Assembler::rorl(CpuRegister operand, CpuRegister shifter) { + EmitGenericShift(false, 1, operand, shifter); +} + + +void X86_64Assembler::rolq(CpuRegister reg, const Immediate& imm) { + EmitGenericShift(true, 0, reg, imm); +} + + +void X86_64Assembler::rolq(CpuRegister operand, CpuRegister shifter) { + EmitGenericShift(true, 0, operand, shifter); +} + + +void X86_64Assembler::rorq(CpuRegister reg, const Immediate& imm) { + EmitGenericShift(true, 1, reg, imm); +} + + +void X86_64Assembler::rorq(CpuRegister operand, CpuRegister shifter) { + EmitGenericShift(true, 1, operand, shifter); +} + + void X86_64Assembler::negl(CpuRegister reg) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitOptionalRex32(reg); @@ -2140,6 +2180,38 @@ void X86_64Assembler::bswapq(CpuRegister dst) { EmitUint8(0xC8 + dst.LowBits()); } +void X86_64Assembler::bsfl(CpuRegister dst, CpuRegister src) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitOptionalRex32(dst, src); + EmitUint8(0x0F); + EmitUint8(0xBC); + EmitRegisterOperand(dst.LowBits(), src.LowBits()); +} + +void X86_64Assembler::bsfl(CpuRegister dst, const Address& src) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitOptionalRex32(dst, src); + EmitUint8(0x0F); + EmitUint8(0xBC); + EmitOperand(dst.LowBits(), src); +} + +void X86_64Assembler::bsfq(CpuRegister dst, CpuRegister src) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitRex64(dst, src); + EmitUint8(0x0F); + EmitUint8(0xBC); + EmitRegisterOperand(dst.LowBits(), src.LowBits()); +} + +void X86_64Assembler::bsfq(CpuRegister dst, const Address& src) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitRex64(dst, src); + EmitUint8(0x0F); + EmitUint8(0xBC); + EmitOperand(dst.LowBits(), src); +} + void X86_64Assembler::bsrl(CpuRegister dst, CpuRegister src) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitOptionalRex32(dst, src); diff --git a/compiler/utils/x86_64/assembler_x86_64.h b/compiler/utils/x86_64/assembler_x86_64.h index c38aba5e91..255f551675 100644 --- a/compiler/utils/x86_64/assembler_x86_64.h +++ b/compiler/utils/x86_64/assembler_x86_64.h @@ -633,11 +633,26 @@ class X86_64Assembler FINAL : public Assembler { void bswapl(CpuRegister dst); void bswapq(CpuRegister dst); + void bsfl(CpuRegister dst, CpuRegister src); + void bsfl(CpuRegister dst, const Address& src); + void bsfq(CpuRegister dst, CpuRegister src); + void bsfq(CpuRegister dst, const Address& src); + void bsrl(CpuRegister dst, CpuRegister src); void bsrl(CpuRegister dst, const Address& src); void bsrq(CpuRegister dst, CpuRegister src); void bsrq(CpuRegister dst, const Address& src); + void rorl(CpuRegister reg, const Immediate& imm); + void rorl(CpuRegister operand, CpuRegister shifter); + void roll(CpuRegister reg, const Immediate& imm); + void roll(CpuRegister operand, CpuRegister shifter); + + void rorq(CpuRegister reg, const Immediate& imm); + void rorq(CpuRegister operand, CpuRegister shifter); + void rolq(CpuRegister reg, const Immediate& imm); + void rolq(CpuRegister operand, CpuRegister shifter); + void repne_scasw(); void repe_cmpsw(); void repe_cmpsl(); @@ -665,7 +680,10 @@ class X86_64Assembler FINAL : public Assembler { // int PreferredLoopAlignment() { return 16; } void Align(int alignment, int offset); - void Bind(Label* label); + void Bind(Label* label) OVERRIDE; + void Jump(Label* label) OVERRIDE { + jmp(label); + } void Bind(NearLabel* label); // diff --git a/compiler/utils/x86_64/assembler_x86_64_test.cc b/compiler/utils/x86_64/assembler_x86_64_test.cc index 9e64b47c92..82378f724a 100644 --- a/compiler/utils/x86_64/assembler_x86_64_test.cc +++ b/compiler/utils/x86_64/assembler_x86_64_test.cc @@ -495,6 +495,98 @@ TEST_F(AssemblerX86_64Test, SarqImm) { DriverStr(RepeatRI(&x86_64::X86_64Assembler::sarq, 1U, "sarq ${imm}, %{reg}"), "sarqi"); } +// Rorl only allows CL as the shift count. +std::string rorl_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { + std::ostringstream str; + + std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); + + x86_64::CpuRegister shifter(x86_64::RCX); + for (auto reg : registers) { + assembler->rorl(*reg, shifter); + str << "rorl %cl, %" << assembler_test->GetSecondaryRegisterName(*reg) << "\n"; + } + + return str.str(); +} + +TEST_F(AssemblerX86_64Test, RorlReg) { + DriverFn(&rorl_fn, "rorl"); +} + +TEST_F(AssemblerX86_64Test, RorlImm) { + DriverStr(Repeatri(&x86_64::X86_64Assembler::rorl, 1U, "rorl ${imm}, %{reg}"), "rorli"); +} + +// Roll only allows CL as the shift count. +std::string roll_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { + std::ostringstream str; + + std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); + + x86_64::CpuRegister shifter(x86_64::RCX); + for (auto reg : registers) { + assembler->roll(*reg, shifter); + str << "roll %cl, %" << assembler_test->GetSecondaryRegisterName(*reg) << "\n"; + } + + return str.str(); +} + +TEST_F(AssemblerX86_64Test, RollReg) { + DriverFn(&roll_fn, "roll"); +} + +TEST_F(AssemblerX86_64Test, RollImm) { + DriverStr(Repeatri(&x86_64::X86_64Assembler::roll, 1U, "roll ${imm}, %{reg}"), "rolli"); +} + +// Rorq only allows CL as the shift count. +std::string rorq_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { + std::ostringstream str; + + std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); + + x86_64::CpuRegister shifter(x86_64::RCX); + for (auto reg : registers) { + assembler->rorq(*reg, shifter); + str << "rorq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n"; + } + + return str.str(); +} + +TEST_F(AssemblerX86_64Test, RorqReg) { + DriverFn(&rorq_fn, "rorq"); +} + +TEST_F(AssemblerX86_64Test, RorqImm) { + DriverStr(RepeatRI(&x86_64::X86_64Assembler::rorq, 1U, "rorq ${imm}, %{reg}"), "rorqi"); +} + +// Rolq only allows CL as the shift count. +std::string rolq_fn(AssemblerX86_64Test::Base* assembler_test, x86_64::X86_64Assembler* assembler) { + std::ostringstream str; + + std::vector<x86_64::CpuRegister*> registers = assembler_test->GetRegisters(); + + x86_64::CpuRegister shifter(x86_64::RCX); + for (auto reg : registers) { + assembler->rolq(*reg, shifter); + str << "rolq %cl, %" << assembler_test->GetRegisterName(*reg) << "\n"; + } + + return str.str(); +} + +TEST_F(AssemblerX86_64Test, RolqReg) { + DriverFn(&rolq_fn, "rolq"); +} + +TEST_F(AssemblerX86_64Test, RolqImm) { + DriverStr(RepeatRI(&x86_64::X86_64Assembler::rolq, 1U, "rolq ${imm}, %{reg}"), "rolqi"); +} + TEST_F(AssemblerX86_64Test, CmpqRegs) { DriverStr(RepeatRR(&x86_64::X86_64Assembler::cmpq, "cmpq %{reg2}, %{reg1}"), "cmpq"); } @@ -1141,6 +1233,44 @@ TEST_F(AssemblerX86_64Test, Bswapq) { DriverStr(RepeatR(&x86_64::X86_64Assembler::bswapq, "bswap %{reg}"), "bswapq"); } +TEST_F(AssemblerX86_64Test, Bsfl) { + DriverStr(Repeatrr(&x86_64::X86_64Assembler::bsfl, "bsfl %{reg2}, %{reg1}"), "bsfl"); +} + +TEST_F(AssemblerX86_64Test, BsflAddress) { + GetAssembler()->bsfl(x86_64::CpuRegister(x86_64::R10), x86_64::Address( + x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); + GetAssembler()->bsfl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( + x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); + GetAssembler()->bsfl(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( + x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); + const char* expected = + "bsfl 0xc(%RDI,%RBX,4), %R10d\n" + "bsfl 0xc(%R10,%RBX,4), %edi\n" + "bsfl 0xc(%RDI,%R9,4), %edi\n"; + + DriverStr(expected, "bsfl_address"); +} + +TEST_F(AssemblerX86_64Test, Bsfq) { + DriverStr(RepeatRR(&x86_64::X86_64Assembler::bsfq, "bsfq %{reg2}, %{reg1}"), "bsfq"); +} + +TEST_F(AssemblerX86_64Test, BsfqAddress) { + GetAssembler()->bsfq(x86_64::CpuRegister(x86_64::R10), x86_64::Address( + x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); + GetAssembler()->bsfq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( + x86_64::CpuRegister(x86_64::R10), x86_64::CpuRegister(x86_64::RBX), x86_64::TIMES_4, 12)); + GetAssembler()->bsfq(x86_64::CpuRegister(x86_64::RDI), x86_64::Address( + x86_64::CpuRegister(x86_64::RDI), x86_64::CpuRegister(x86_64::R9), x86_64::TIMES_4, 12)); + const char* expected = + "bsfq 0xc(%RDI,%RBX,4), %R10\n" + "bsfq 0xc(%R10,%RBX,4), %RDI\n" + "bsfq 0xc(%RDI,%R9,4), %RDI\n"; + + DriverStr(expected, "bsfq_address"); +} + TEST_F(AssemblerX86_64Test, Bsrl) { DriverStr(Repeatrr(&x86_64::X86_64Assembler::bsrl, "bsrl %{reg2}, %{reg1}"), "bsrl"); } |