1 //===-- Target.cpp ----------------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #include "MCTargetDesc/MipsBaseInfo.h"
12 #include "MipsRegisterInfo.h"
18 // Returns an error if we cannot handle the memory references in this
20 static Error
isInvalidMemoryInstr(const Instruction
&Instr
) {
21 switch (Instr
.Description
.TSFlags
& MipsII::FormMask
) {
23 llvm_unreachable("Unknown FormMask value");
24 // These have no memory access.
29 return Error::success();
30 // These access memory and are handled.
32 return Error::success();
33 // These access memory and are not handled yet.
35 case MipsII::FrmOther
:
36 return make_error
<Failure
>("unsupported opcode: non uniform memory access");
41 // Helper to fill a memory operand with a value.
42 static void setMemOp(InstructionTemplate
&IT
, int OpIdx
,
43 const MCOperand
&OpVal
) {
44 const auto Op
= IT
.getInstr().Operands
[OpIdx
];
45 assert(Op
.isExplicit() && "invalid memory pattern");
46 IT
.getValueFor(Op
) = OpVal
;
49 #include "MipsGenExegesis.inc"
52 class ExegesisMipsTarget
: public ExegesisTarget
{
54 ExegesisMipsTarget() : ExegesisTarget(MipsCpuPfmCounters
) {}
57 unsigned getScratchMemoryRegister(const llvm::Triple
&TT
) const override
;
58 unsigned getMaxMemoryAccessSize() const override
{ return 64; }
59 void fillMemoryOperands(InstructionTemplate
&IT
, unsigned Reg
,
60 unsigned Offset
) const override
;
62 std::vector
<MCInst
> setRegTo(const MCSubtargetInfo
&STI
, unsigned Reg
,
63 const APInt
&Value
) const override
;
64 bool matchesArch(Triple::ArchType Arch
) const override
{
65 return Arch
== Triple::mips
|| Arch
== Triple::mipsel
||
66 Arch
== Triple::mips64
|| Arch
== Triple::mips64el
;
69 } // end anonymous namespace
71 // Generates instructions to load an immediate value into a register.
72 static std::vector
<MCInst
> loadImmediate(unsigned Reg
, bool IsGPR32
,
75 unsigned ORi
, LUi
, SLL
;
82 ZeroReg
= Mips::ZERO_64
;
88 if (Value
.isIntN(16)) {
89 return {MCInstBuilder(ORi
)
92 .addImm(Value
.getZExtValue())};
95 std::vector
<MCInst
> Instructions
;
96 if (Value
.isIntN(32)) {
97 const uint16_t HiBits
= Value
.getHiBits(16).getZExtValue();
98 if (!IsGPR32
&& Value
.getActiveBits() == 32) {
99 // Expand to an ORi instead of a LUi to avoid sign-extending into the
101 Instructions
.push_back(
106 Instructions
.push_back(
112 Instructions
.push_back(
118 const uint16_t LoBits
= Value
.getLoBits(16).getZExtValue();
120 Instructions
.push_back(
130 llvm_unreachable("Not implemented for values wider than 32 bits");
133 unsigned ExegesisMipsTarget::getScratchMemoryRegister(const Triple
&TT
) const {
134 return TT
.isArch64Bit() ? Mips::A0_64
: Mips::A0
;
137 void ExegesisMipsTarget::fillMemoryOperands(InstructionTemplate
&IT
,
139 unsigned Offset
) const {
140 assert(!isInvalidMemoryInstr(IT
.getInstr()) &&
141 "fillMemoryOperands requires a valid memory instruction");
142 setMemOp(IT
, 0, MCOperand::createReg(0)); // IndexReg
143 setMemOp(IT
, 1, MCOperand::createReg(Reg
)); // BaseReg
144 setMemOp(IT
, 2, MCOperand::createImm(Offset
)); // Disp
147 std::vector
<MCInst
> ExegesisMipsTarget::setRegTo(const MCSubtargetInfo
&STI
,
149 const APInt
&Value
) const {
150 if (Mips::GPR32RegClass
.contains(Reg
))
151 return loadImmediate(Reg
, true, Value
);
152 if (Mips::GPR64RegClass
.contains(Reg
))
153 return loadImmediate(Reg
, false, Value
);
154 errs() << "setRegTo is not implemented, results will be unreliable\n";
158 static ExegesisTarget
*getTheExegesisMipsTarget() {
159 static ExegesisMipsTarget Target
;
163 void InitializeMipsExegesisTarget() {
164 ExegesisTarget::registerTarget(getTheExegesisMipsTarget());
167 } // namespace exegesis