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"
14 #define GET_AVAILABLE_OPCODE_CHECKER
15 #include "MipsGenInstrInfo.inc"
21 // Returns an error if we cannot handle the memory references in this
23 static Error
isInvalidMemoryInstr(const Instruction
&Instr
) {
24 switch (Instr
.Description
.TSFlags
& MipsII::FormMask
) {
26 llvm_unreachable("Unknown FormMask value");
27 // These have no memory access.
32 return Error::success();
33 // These access memory and are handled.
35 return Error::success();
36 // These access memory and are not handled yet.
38 case MipsII::FrmOther
:
39 return make_error
<Failure
>("unsupported opcode: non uniform memory access");
44 // Helper to fill a memory operand with a value.
45 static void setMemOp(InstructionTemplate
&IT
, int OpIdx
,
46 const MCOperand
&OpVal
) {
47 const auto Op
= IT
.getInstr().Operands
[OpIdx
];
48 assert(Op
.isExplicit() && "invalid memory pattern");
49 IT
.getValueFor(Op
) = OpVal
;
52 #include "MipsGenExegesis.inc"
55 class ExegesisMipsTarget
: public ExegesisTarget
{
58 : ExegesisTarget(MipsCpuPfmCounters
, Mips_MC::isOpcodeAvailable
) {}
61 unsigned getScratchMemoryRegister(const llvm::Triple
&TT
) const override
;
62 unsigned getMaxMemoryAccessSize() const override
{ return 64; }
63 void fillMemoryOperands(InstructionTemplate
&IT
, unsigned Reg
,
64 unsigned Offset
) const override
;
66 std::vector
<MCInst
> setRegTo(const MCSubtargetInfo
&STI
, unsigned Reg
,
67 const APInt
&Value
) const override
;
68 bool matchesArch(Triple::ArchType Arch
) const override
{
69 return Arch
== Triple::mips
|| Arch
== Triple::mipsel
||
70 Arch
== Triple::mips64
|| Arch
== Triple::mips64el
;
73 } // end anonymous namespace
75 // Generates instructions to load an immediate value into a register.
76 static std::vector
<MCInst
> loadImmediate(unsigned Reg
, bool IsGPR32
,
79 unsigned ORi
, LUi
, SLL
;
86 ZeroReg
= Mips::ZERO_64
;
92 if (Value
.isIntN(16)) {
93 return {MCInstBuilder(ORi
)
96 .addImm(Value
.getZExtValue())};
99 std::vector
<MCInst
> Instructions
;
100 if (Value
.isIntN(32)) {
101 const uint16_t HiBits
= Value
.getHiBits(16).getZExtValue();
102 if (!IsGPR32
&& Value
.getActiveBits() == 32) {
103 // Expand to an ORi instead of a LUi to avoid sign-extending into the
105 Instructions
.push_back(
110 Instructions
.push_back(
116 Instructions
.push_back(
122 const uint16_t LoBits
= Value
.getLoBits(16).getZExtValue();
124 Instructions
.push_back(
134 llvm_unreachable("Not implemented for values wider than 32 bits");
137 unsigned ExegesisMipsTarget::getScratchMemoryRegister(const Triple
&TT
) const {
138 return TT
.isArch64Bit() ? Mips::A0_64
: Mips::A0
;
141 void ExegesisMipsTarget::fillMemoryOperands(InstructionTemplate
&IT
,
143 unsigned Offset
) const {
144 assert(!isInvalidMemoryInstr(IT
.getInstr()) &&
145 "fillMemoryOperands requires a valid memory instruction");
146 setMemOp(IT
, 0, MCOperand::createReg(0)); // IndexReg
147 setMemOp(IT
, 1, MCOperand::createReg(Reg
)); // BaseReg
148 setMemOp(IT
, 2, MCOperand::createImm(Offset
)); // Disp
151 std::vector
<MCInst
> ExegesisMipsTarget::setRegTo(const MCSubtargetInfo
&STI
,
153 const APInt
&Value
) const {
154 if (Mips::GPR32RegClass
.contains(Reg
))
155 return loadImmediate(Reg
, true, Value
);
156 if (Mips::GPR64RegClass
.contains(Reg
))
157 return loadImmediate(Reg
, false, Value
);
158 errs() << "setRegTo is not implemented, results will be unreliable\n";
162 static ExegesisTarget
*getTheExegesisMipsTarget() {
163 static ExegesisMipsTarget Target
;
167 void InitializeMipsExegesisTarget() {
168 ExegesisTarget::registerTarget(getTheExegesisMipsTarget());
171 } // namespace exegesis