106c3fb27SDimitry Andric //===-- AMDGPUMCCodeEmitter.cpp - AMDGPU Code Emitter ---------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
1006c3fb27SDimitry Andric /// The AMDGPU code emitter produces machine code that can be executed
1106c3fb27SDimitry Andric /// directly on the GPU device.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric
1506c3fb27SDimitry Andric #include "MCTargetDesc/AMDGPUFixupKinds.h"
1606c3fb27SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
1706c3fb27SDimitry Andric #include "SIDefines.h"
1806c3fb27SDimitry Andric #include "Utils/AMDGPUBaseInfo.h"
1906c3fb27SDimitry Andric #include "llvm/ADT/APInt.h"
2006c3fb27SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
2106c3fb27SDimitry Andric #include "llvm/MC/MCContext.h"
2206c3fb27SDimitry Andric #include "llvm/MC/MCExpr.h"
2306c3fb27SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
2406c3fb27SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
2506c3fb27SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
2606c3fb27SDimitry Andric #include "llvm/Support/Casting.h"
2706c3fb27SDimitry Andric #include "llvm/Support/EndianStream.h"
2806c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h"
2906c3fb27SDimitry Andric #include <optional>
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric using namespace llvm;
320b57cec5SDimitry Andric
3306c3fb27SDimitry Andric namespace {
340b57cec5SDimitry Andric
3506c3fb27SDimitry Andric class AMDGPUMCCodeEmitter : public MCCodeEmitter {
3606c3fb27SDimitry Andric const MCRegisterInfo &MRI;
3706c3fb27SDimitry Andric const MCInstrInfo &MCII;
3806c3fb27SDimitry Andric
3906c3fb27SDimitry Andric public:
AMDGPUMCCodeEmitter(const MCInstrInfo & MCII,const MCRegisterInfo & MRI)4006c3fb27SDimitry Andric AMDGPUMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI)
4106c3fb27SDimitry Andric : MRI(MRI), MCII(MCII) {}
4206c3fb27SDimitry Andric
4306c3fb27SDimitry Andric /// Encode the instruction and write it to the OS.
4406c3fb27SDimitry Andric void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
4506c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
4606c3fb27SDimitry Andric const MCSubtargetInfo &STI) const override;
4706c3fb27SDimitry Andric
4806c3fb27SDimitry Andric void getMachineOpValue(const MCInst &MI, const MCOperand &MO, APInt &Op,
4906c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
5006c3fb27SDimitry Andric const MCSubtargetInfo &STI) const;
5106c3fb27SDimitry Andric
525f757f3fSDimitry Andric void getMachineOpValueT16(const MCInst &MI, unsigned OpNo, APInt &Op,
535f757f3fSDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
545f757f3fSDimitry Andric const MCSubtargetInfo &STI) const;
555f757f3fSDimitry Andric
565f757f3fSDimitry Andric void getMachineOpValueT16Lo128(const MCInst &MI, unsigned OpNo, APInt &Op,
575f757f3fSDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
585f757f3fSDimitry Andric const MCSubtargetInfo &STI) const;
595f757f3fSDimitry Andric
6006c3fb27SDimitry Andric /// Use a fixup to encode the simm16 field for SOPP branch
6106c3fb27SDimitry Andric /// instructions.
6206c3fb27SDimitry Andric void getSOPPBrEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
6306c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
6406c3fb27SDimitry Andric const MCSubtargetInfo &STI) const;
6506c3fb27SDimitry Andric
6606c3fb27SDimitry Andric void getSMEMOffsetEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
6706c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
6806c3fb27SDimitry Andric const MCSubtargetInfo &STI) const;
6906c3fb27SDimitry Andric
7006c3fb27SDimitry Andric void getSDWASrcEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
7106c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
7206c3fb27SDimitry Andric const MCSubtargetInfo &STI) const;
7306c3fb27SDimitry Andric
7406c3fb27SDimitry Andric void getSDWAVopcDstEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
7506c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
7606c3fb27SDimitry Andric const MCSubtargetInfo &STI) const;
7706c3fb27SDimitry Andric
7806c3fb27SDimitry Andric void getAVOperandEncoding(const MCInst &MI, unsigned OpNo, APInt &Op,
7906c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
8006c3fb27SDimitry Andric const MCSubtargetInfo &STI) const;
8106c3fb27SDimitry Andric
8206c3fb27SDimitry Andric private:
8306c3fb27SDimitry Andric uint64_t getImplicitOpSelHiEncoding(int Opcode) const;
8406c3fb27SDimitry Andric void getMachineOpValueCommon(const MCInst &MI, const MCOperand &MO,
8506c3fb27SDimitry Andric unsigned OpNo, APInt &Op,
8606c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
8706c3fb27SDimitry Andric const MCSubtargetInfo &STI) const;
8806c3fb27SDimitry Andric
8906c3fb27SDimitry Andric /// Encode an fp or int literal.
9006c3fb27SDimitry Andric std::optional<uint32_t> getLitEncoding(const MCOperand &MO,
9106c3fb27SDimitry Andric const MCOperandInfo &OpInfo,
9206c3fb27SDimitry Andric const MCSubtargetInfo &STI) const;
9306c3fb27SDimitry Andric
9406c3fb27SDimitry Andric void getBinaryCodeForInstr(const MCInst &MI, SmallVectorImpl<MCFixup> &Fixups,
9506c3fb27SDimitry Andric APInt &Inst, APInt &Scratch,
9606c3fb27SDimitry Andric const MCSubtargetInfo &STI) const;
9706c3fb27SDimitry Andric };
9806c3fb27SDimitry Andric
9906c3fb27SDimitry Andric } // end anonymous namespace
10006c3fb27SDimitry Andric
createAMDGPUMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)10106c3fb27SDimitry Andric MCCodeEmitter *llvm::createAMDGPUMCCodeEmitter(const MCInstrInfo &MCII,
10206c3fb27SDimitry Andric MCContext &Ctx) {
10306c3fb27SDimitry Andric return new AMDGPUMCCodeEmitter(MCII, *Ctx.getRegisterInfo());
10406c3fb27SDimitry Andric }
10506c3fb27SDimitry Andric
10606c3fb27SDimitry Andric // Returns the encoding value to use if the given integer is an integer inline
10706c3fb27SDimitry Andric // immediate value, or 0 if it is not.
10806c3fb27SDimitry Andric template <typename IntTy>
getIntInlineImmEncoding(IntTy Imm)10906c3fb27SDimitry Andric static uint32_t getIntInlineImmEncoding(IntTy Imm) {
11006c3fb27SDimitry Andric if (Imm >= 0 && Imm <= 64)
11106c3fb27SDimitry Andric return 128 + Imm;
11206c3fb27SDimitry Andric
11306c3fb27SDimitry Andric if (Imm >= -16 && Imm <= -1)
11406c3fb27SDimitry Andric return 192 + std::abs(Imm);
11506c3fb27SDimitry Andric
11606c3fb27SDimitry Andric return 0;
11706c3fb27SDimitry Andric }
11806c3fb27SDimitry Andric
getLit16Encoding(uint16_t Val,const MCSubtargetInfo & STI)11906c3fb27SDimitry Andric static uint32_t getLit16Encoding(uint16_t Val, const MCSubtargetInfo &STI) {
12006c3fb27SDimitry Andric uint16_t IntImm = getIntInlineImmEncoding(static_cast<int16_t>(Val));
12106c3fb27SDimitry Andric if (IntImm != 0)
12206c3fb27SDimitry Andric return IntImm;
12306c3fb27SDimitry Andric
12406c3fb27SDimitry Andric if (Val == 0x3800) // 0.5
12506c3fb27SDimitry Andric return 240;
12606c3fb27SDimitry Andric
12706c3fb27SDimitry Andric if (Val == 0xB800) // -0.5
12806c3fb27SDimitry Andric return 241;
12906c3fb27SDimitry Andric
13006c3fb27SDimitry Andric if (Val == 0x3C00) // 1.0
13106c3fb27SDimitry Andric return 242;
13206c3fb27SDimitry Andric
13306c3fb27SDimitry Andric if (Val == 0xBC00) // -1.0
13406c3fb27SDimitry Andric return 243;
13506c3fb27SDimitry Andric
13606c3fb27SDimitry Andric if (Val == 0x4000) // 2.0
13706c3fb27SDimitry Andric return 244;
13806c3fb27SDimitry Andric
13906c3fb27SDimitry Andric if (Val == 0xC000) // -2.0
14006c3fb27SDimitry Andric return 245;
14106c3fb27SDimitry Andric
14206c3fb27SDimitry Andric if (Val == 0x4400) // 4.0
14306c3fb27SDimitry Andric return 246;
14406c3fb27SDimitry Andric
14506c3fb27SDimitry Andric if (Val == 0xC400) // -4.0
14606c3fb27SDimitry Andric return 247;
14706c3fb27SDimitry Andric
14806c3fb27SDimitry Andric if (Val == 0x3118 && // 1.0 / (2.0 * pi)
14906c3fb27SDimitry Andric STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
15006c3fb27SDimitry Andric return 248;
15106c3fb27SDimitry Andric
15206c3fb27SDimitry Andric return 255;
15306c3fb27SDimitry Andric }
15406c3fb27SDimitry Andric
getLitBF16Encoding(uint16_t Val)155*0fca6ea1SDimitry Andric static uint32_t getLitBF16Encoding(uint16_t Val) {
156*0fca6ea1SDimitry Andric uint16_t IntImm = getIntInlineImmEncoding(static_cast<int16_t>(Val));
157*0fca6ea1SDimitry Andric if (IntImm != 0)
158*0fca6ea1SDimitry Andric return IntImm;
159*0fca6ea1SDimitry Andric
160*0fca6ea1SDimitry Andric // clang-format off
161*0fca6ea1SDimitry Andric switch (Val) {
162*0fca6ea1SDimitry Andric case 0x3F00: return 240; // 0.5
163*0fca6ea1SDimitry Andric case 0xBF00: return 241; // -0.5
164*0fca6ea1SDimitry Andric case 0x3F80: return 242; // 1.0
165*0fca6ea1SDimitry Andric case 0xBF80: return 243; // -1.0
166*0fca6ea1SDimitry Andric case 0x4000: return 244; // 2.0
167*0fca6ea1SDimitry Andric case 0xC000: return 245; // -2.0
168*0fca6ea1SDimitry Andric case 0x4080: return 246; // 4.0
169*0fca6ea1SDimitry Andric case 0xC080: return 247; // -4.0
170*0fca6ea1SDimitry Andric case 0x3E22: return 248; // 1.0 / (2.0 * pi)
171*0fca6ea1SDimitry Andric default: return 255;
172*0fca6ea1SDimitry Andric }
173*0fca6ea1SDimitry Andric // clang-format on
174*0fca6ea1SDimitry Andric }
175*0fca6ea1SDimitry Andric
getLit32Encoding(uint32_t Val,const MCSubtargetInfo & STI)17606c3fb27SDimitry Andric static uint32_t getLit32Encoding(uint32_t Val, const MCSubtargetInfo &STI) {
17706c3fb27SDimitry Andric uint32_t IntImm = getIntInlineImmEncoding(static_cast<int32_t>(Val));
17806c3fb27SDimitry Andric if (IntImm != 0)
17906c3fb27SDimitry Andric return IntImm;
18006c3fb27SDimitry Andric
18106c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint32_t>(0.5f))
18206c3fb27SDimitry Andric return 240;
18306c3fb27SDimitry Andric
18406c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint32_t>(-0.5f))
18506c3fb27SDimitry Andric return 241;
18606c3fb27SDimitry Andric
18706c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint32_t>(1.0f))
18806c3fb27SDimitry Andric return 242;
18906c3fb27SDimitry Andric
19006c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint32_t>(-1.0f))
19106c3fb27SDimitry Andric return 243;
19206c3fb27SDimitry Andric
19306c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint32_t>(2.0f))
19406c3fb27SDimitry Andric return 244;
19506c3fb27SDimitry Andric
19606c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint32_t>(-2.0f))
19706c3fb27SDimitry Andric return 245;
19806c3fb27SDimitry Andric
19906c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint32_t>(4.0f))
20006c3fb27SDimitry Andric return 246;
20106c3fb27SDimitry Andric
20206c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint32_t>(-4.0f))
20306c3fb27SDimitry Andric return 247;
20406c3fb27SDimitry Andric
20506c3fb27SDimitry Andric if (Val == 0x3e22f983 && // 1.0 / (2.0 * pi)
20606c3fb27SDimitry Andric STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
20706c3fb27SDimitry Andric return 248;
20806c3fb27SDimitry Andric
20906c3fb27SDimitry Andric return 255;
21006c3fb27SDimitry Andric }
21106c3fb27SDimitry Andric
getLit16IntEncoding(uint32_t Val,const MCSubtargetInfo & STI)212*0fca6ea1SDimitry Andric static uint32_t getLit16IntEncoding(uint32_t Val, const MCSubtargetInfo &STI) {
213*0fca6ea1SDimitry Andric return getLit32Encoding(Val, STI);
214*0fca6ea1SDimitry Andric }
215*0fca6ea1SDimitry Andric
getLit64Encoding(uint64_t Val,const MCSubtargetInfo & STI)21606c3fb27SDimitry Andric static uint32_t getLit64Encoding(uint64_t Val, const MCSubtargetInfo &STI) {
21706c3fb27SDimitry Andric uint32_t IntImm = getIntInlineImmEncoding(static_cast<int64_t>(Val));
21806c3fb27SDimitry Andric if (IntImm != 0)
21906c3fb27SDimitry Andric return IntImm;
22006c3fb27SDimitry Andric
22106c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint64_t>(0.5))
22206c3fb27SDimitry Andric return 240;
22306c3fb27SDimitry Andric
22406c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint64_t>(-0.5))
22506c3fb27SDimitry Andric return 241;
22606c3fb27SDimitry Andric
22706c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint64_t>(1.0))
22806c3fb27SDimitry Andric return 242;
22906c3fb27SDimitry Andric
23006c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint64_t>(-1.0))
23106c3fb27SDimitry Andric return 243;
23206c3fb27SDimitry Andric
23306c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint64_t>(2.0))
23406c3fb27SDimitry Andric return 244;
23506c3fb27SDimitry Andric
23606c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint64_t>(-2.0))
23706c3fb27SDimitry Andric return 245;
23806c3fb27SDimitry Andric
23906c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint64_t>(4.0))
24006c3fb27SDimitry Andric return 246;
24106c3fb27SDimitry Andric
24206c3fb27SDimitry Andric if (Val == llvm::bit_cast<uint64_t>(-4.0))
24306c3fb27SDimitry Andric return 247;
24406c3fb27SDimitry Andric
24506c3fb27SDimitry Andric if (Val == 0x3fc45f306dc9c882 && // 1.0 / (2.0 * pi)
24606c3fb27SDimitry Andric STI.hasFeature(AMDGPU::FeatureInv2PiInlineImm))
24706c3fb27SDimitry Andric return 248;
24806c3fb27SDimitry Andric
24906c3fb27SDimitry Andric return 255;
25006c3fb27SDimitry Andric }
25106c3fb27SDimitry Andric
25206c3fb27SDimitry Andric std::optional<uint32_t>
getLitEncoding(const MCOperand & MO,const MCOperandInfo & OpInfo,const MCSubtargetInfo & STI) const25306c3fb27SDimitry Andric AMDGPUMCCodeEmitter::getLitEncoding(const MCOperand &MO,
25406c3fb27SDimitry Andric const MCOperandInfo &OpInfo,
25506c3fb27SDimitry Andric const MCSubtargetInfo &STI) const {
25606c3fb27SDimitry Andric int64_t Imm;
25706c3fb27SDimitry Andric if (MO.isExpr()) {
25806c3fb27SDimitry Andric const auto *C = dyn_cast<MCConstantExpr>(MO.getExpr());
25906c3fb27SDimitry Andric if (!C)
26006c3fb27SDimitry Andric return 255;
26106c3fb27SDimitry Andric
26206c3fb27SDimitry Andric Imm = C->getValue();
26306c3fb27SDimitry Andric } else {
26406c3fb27SDimitry Andric
26506c3fb27SDimitry Andric assert(!MO.isDFPImm());
26606c3fb27SDimitry Andric
26706c3fb27SDimitry Andric if (!MO.isImm())
26806c3fb27SDimitry Andric return {};
26906c3fb27SDimitry Andric
27006c3fb27SDimitry Andric Imm = MO.getImm();
27106c3fb27SDimitry Andric }
27206c3fb27SDimitry Andric
27306c3fb27SDimitry Andric switch (OpInfo.OperandType) {
27406c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_IMM_INT32:
27506c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP32:
27606c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP32_DEFERRED:
27706c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_INT32:
27806c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_FP32:
27906c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_INT32:
28006c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
28106c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_IMM_V2INT32:
28206c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_IMM_V2FP32:
28306c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_V2INT32:
28406c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_V2FP32:
2855f757f3fSDimitry Andric case AMDGPU::OPERAND_INLINE_SPLIT_BARRIER_INT32:
28606c3fb27SDimitry Andric return getLit32Encoding(static_cast<uint32_t>(Imm), STI);
28706c3fb27SDimitry Andric
28806c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_IMM_INT64:
28906c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP64:
29006c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_INT64:
29106c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_FP64:
29206c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_FP64:
29306c3fb27SDimitry Andric return getLit64Encoding(static_cast<uint64_t>(Imm), STI);
29406c3fb27SDimitry Andric
29506c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_IMM_INT16:
29606c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_INT16:
29706c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_INT16:
298*0fca6ea1SDimitry Andric return getLit16IntEncoding(static_cast<uint32_t>(Imm), STI);
299*0fca6ea1SDimitry Andric
30006c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP16:
30106c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_IMM_FP16_DEFERRED:
30206c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_FP16:
30306c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_FP16:
30406c3fb27SDimitry Andric // FIXME Is this correct? What do inline immediates do on SI for f16 src
30506c3fb27SDimitry Andric // which does not have f16 support?
30606c3fb27SDimitry Andric return getLit16Encoding(static_cast<uint16_t>(Imm), STI);
307*0fca6ea1SDimitry Andric
308*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_IMM_BF16:
309*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_IMM_BF16_DEFERRED:
310*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_BF16:
311*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_BF16:
312*0fca6ea1SDimitry Andric // We don't actually need to check Inv2Pi here because BF16 instructions can
313*0fca6ea1SDimitry Andric // only be emitted for targets that already support the feature.
314*0fca6ea1SDimitry Andric return getLitBF16Encoding(static_cast<uint16_t>(Imm));
315*0fca6ea1SDimitry Andric
31606c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_IMM_V2INT16:
31706c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
31806c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16:
3191db9f3b2SDimitry Andric return AMDGPU::getInlineEncodingV2I16(static_cast<uint32_t>(Imm))
3201db9f3b2SDimitry Andric .value_or(255);
321*0fca6ea1SDimitry Andric
3221db9f3b2SDimitry Andric case AMDGPU::OPERAND_REG_IMM_V2FP16:
32306c3fb27SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
3241db9f3b2SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16:
3251db9f3b2SDimitry Andric return AMDGPU::getInlineEncodingV2F16(static_cast<uint32_t>(Imm))
3261db9f3b2SDimitry Andric .value_or(255);
327*0fca6ea1SDimitry Andric
328*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_IMM_V2BF16:
329*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_C_V2BF16:
330*0fca6ea1SDimitry Andric case AMDGPU::OPERAND_REG_INLINE_AC_V2BF16:
331*0fca6ea1SDimitry Andric return AMDGPU::getInlineEncodingV2BF16(static_cast<uint32_t>(Imm))
332*0fca6ea1SDimitry Andric .value_or(255);
333*0fca6ea1SDimitry Andric
33406c3fb27SDimitry Andric case AMDGPU::OPERAND_KIMM32:
33506c3fb27SDimitry Andric case AMDGPU::OPERAND_KIMM16:
33606c3fb27SDimitry Andric return MO.getImm();
33706c3fb27SDimitry Andric default:
33806c3fb27SDimitry Andric llvm_unreachable("invalid operand size");
33906c3fb27SDimitry Andric }
34006c3fb27SDimitry Andric }
34106c3fb27SDimitry Andric
getImplicitOpSelHiEncoding(int Opcode) const34206c3fb27SDimitry Andric uint64_t AMDGPUMCCodeEmitter::getImplicitOpSelHiEncoding(int Opcode) const {
34306c3fb27SDimitry Andric using namespace AMDGPU::VOP3PEncoding;
34406c3fb27SDimitry Andric using namespace AMDGPU::OpName;
34506c3fb27SDimitry Andric
34606c3fb27SDimitry Andric if (AMDGPU::hasNamedOperand(Opcode, op_sel_hi)) {
34706c3fb27SDimitry Andric if (AMDGPU::hasNamedOperand(Opcode, src2))
34806c3fb27SDimitry Andric return 0;
34906c3fb27SDimitry Andric if (AMDGPU::hasNamedOperand(Opcode, src1))
35006c3fb27SDimitry Andric return OP_SEL_HI_2;
35106c3fb27SDimitry Andric if (AMDGPU::hasNamedOperand(Opcode, src0))
35206c3fb27SDimitry Andric return OP_SEL_HI_1 | OP_SEL_HI_2;
35306c3fb27SDimitry Andric }
35406c3fb27SDimitry Andric return OP_SEL_HI_0 | OP_SEL_HI_1 | OP_SEL_HI_2;
35506c3fb27SDimitry Andric }
35606c3fb27SDimitry Andric
isVCMPX64(const MCInstrDesc & Desc)35706c3fb27SDimitry Andric static bool isVCMPX64(const MCInstrDesc &Desc) {
35806c3fb27SDimitry Andric return (Desc.TSFlags & SIInstrFlags::VOP3) &&
35906c3fb27SDimitry Andric Desc.hasImplicitDefOfPhysReg(AMDGPU::EXEC);
36006c3fb27SDimitry Andric }
36106c3fb27SDimitry Andric
encodeInstruction(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const36206c3fb27SDimitry Andric void AMDGPUMCCodeEmitter::encodeInstruction(const MCInst &MI,
36306c3fb27SDimitry Andric SmallVectorImpl<char> &CB,
36406c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
36506c3fb27SDimitry Andric const MCSubtargetInfo &STI) const {
36606c3fb27SDimitry Andric int Opcode = MI.getOpcode();
36706c3fb27SDimitry Andric APInt Encoding, Scratch;
36806c3fb27SDimitry Andric getBinaryCodeForInstr(MI, Fixups, Encoding, Scratch, STI);
36906c3fb27SDimitry Andric const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
37006c3fb27SDimitry Andric unsigned bytes = Desc.getSize();
37106c3fb27SDimitry Andric
37206c3fb27SDimitry Andric // Set unused op_sel_hi bits to 1 for VOP3P and MAI instructions.
37306c3fb27SDimitry Andric // Note that accvgpr_read/write are MAI, have src0, but do not use op_sel.
37406c3fb27SDimitry Andric if ((Desc.TSFlags & SIInstrFlags::VOP3P) ||
37506c3fb27SDimitry Andric Opcode == AMDGPU::V_ACCVGPR_READ_B32_vi ||
37606c3fb27SDimitry Andric Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_vi) {
37706c3fb27SDimitry Andric Encoding |= getImplicitOpSelHiEncoding(Opcode);
37806c3fb27SDimitry Andric }
37906c3fb27SDimitry Andric
38006c3fb27SDimitry Andric // GFX10+ v_cmpx opcodes promoted to VOP3 have implied dst=EXEC.
38106c3fb27SDimitry Andric // Documentation requires dst to be encoded as EXEC (0x7E),
38206c3fb27SDimitry Andric // but it looks like the actual value encoded for dst operand
38306c3fb27SDimitry Andric // is ignored by HW. It was decided to define dst as "do not care"
38406c3fb27SDimitry Andric // in td files to allow disassembler accept any dst value.
38506c3fb27SDimitry Andric // However, dst is encoded as EXEC for compatibility with SP3.
38606c3fb27SDimitry Andric if (AMDGPU::isGFX10Plus(STI) && isVCMPX64(Desc)) {
38706c3fb27SDimitry Andric assert((Encoding & 0xFF) == 0);
3885f757f3fSDimitry Andric Encoding |= MRI.getEncodingValue(AMDGPU::EXEC_LO) &
3895f757f3fSDimitry Andric AMDGPU::HWEncoding::REG_IDX_MASK;
39006c3fb27SDimitry Andric }
39106c3fb27SDimitry Andric
39206c3fb27SDimitry Andric for (unsigned i = 0; i < bytes; i++) {
39306c3fb27SDimitry Andric CB.push_back((uint8_t)Encoding.extractBitsAsZExtValue(8, 8 * i));
39406c3fb27SDimitry Andric }
39506c3fb27SDimitry Andric
39606c3fb27SDimitry Andric // NSA encoding.
39706c3fb27SDimitry Andric if (AMDGPU::isGFX10Plus(STI) && Desc.TSFlags & SIInstrFlags::MIMG) {
39806c3fb27SDimitry Andric int vaddr0 = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
39906c3fb27SDimitry Andric AMDGPU::OpName::vaddr0);
40006c3fb27SDimitry Andric int srsrc = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
40106c3fb27SDimitry Andric AMDGPU::OpName::srsrc);
40206c3fb27SDimitry Andric assert(vaddr0 >= 0 && srsrc > vaddr0);
40306c3fb27SDimitry Andric unsigned NumExtraAddrs = srsrc - vaddr0 - 1;
40406c3fb27SDimitry Andric unsigned NumPadding = (-NumExtraAddrs) & 3;
40506c3fb27SDimitry Andric
40606c3fb27SDimitry Andric for (unsigned i = 0; i < NumExtraAddrs; ++i) {
40706c3fb27SDimitry Andric getMachineOpValue(MI, MI.getOperand(vaddr0 + 1 + i), Encoding, Fixups,
40806c3fb27SDimitry Andric STI);
40906c3fb27SDimitry Andric CB.push_back((uint8_t)Encoding.getLimitedValue());
41006c3fb27SDimitry Andric }
41106c3fb27SDimitry Andric CB.append(NumPadding, 0);
41206c3fb27SDimitry Andric }
41306c3fb27SDimitry Andric
41406c3fb27SDimitry Andric if ((bytes > 8 && STI.hasFeature(AMDGPU::FeatureVOP3Literal)) ||
41506c3fb27SDimitry Andric (bytes > 4 && !STI.hasFeature(AMDGPU::FeatureVOP3Literal)))
41606c3fb27SDimitry Andric return;
41706c3fb27SDimitry Andric
41806c3fb27SDimitry Andric // Do not print literals from SISrc Operands for insts with mandatory literals
41906c3fb27SDimitry Andric if (AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::imm))
42006c3fb27SDimitry Andric return;
42106c3fb27SDimitry Andric
42206c3fb27SDimitry Andric // Check for additional literals
42306c3fb27SDimitry Andric for (unsigned i = 0, e = Desc.getNumOperands(); i < e; ++i) {
42406c3fb27SDimitry Andric
42506c3fb27SDimitry Andric // Check if this operand should be encoded as [SV]Src
42606c3fb27SDimitry Andric if (!AMDGPU::isSISrcOperand(Desc, i))
42706c3fb27SDimitry Andric continue;
42806c3fb27SDimitry Andric
42906c3fb27SDimitry Andric // Is this operand a literal immediate?
43006c3fb27SDimitry Andric const MCOperand &Op = MI.getOperand(i);
43106c3fb27SDimitry Andric auto Enc = getLitEncoding(Op, Desc.operands()[i], STI);
43206c3fb27SDimitry Andric if (!Enc || *Enc != 255)
43306c3fb27SDimitry Andric continue;
43406c3fb27SDimitry Andric
43506c3fb27SDimitry Andric // Yes! Encode it
43606c3fb27SDimitry Andric int64_t Imm = 0;
43706c3fb27SDimitry Andric
43806c3fb27SDimitry Andric if (Op.isImm())
43906c3fb27SDimitry Andric Imm = Op.getImm();
44006c3fb27SDimitry Andric else if (Op.isExpr()) {
44106c3fb27SDimitry Andric if (const auto *C = dyn_cast<MCConstantExpr>(Op.getExpr()))
44206c3fb27SDimitry Andric Imm = C->getValue();
443*0fca6ea1SDimitry Andric } else // Exprs will be replaced with a fixup value.
44406c3fb27SDimitry Andric llvm_unreachable("Must be immediate or expr");
44506c3fb27SDimitry Andric
4465f757f3fSDimitry Andric if (Desc.operands()[i].OperandType == AMDGPU::OPERAND_REG_IMM_FP64)
4475f757f3fSDimitry Andric Imm = Hi_32(Imm);
4485f757f3fSDimitry Andric
4495f757f3fSDimitry Andric support::endian::write<uint32_t>(CB, Imm, llvm::endianness::little);
45006c3fb27SDimitry Andric
45106c3fb27SDimitry Andric // Only one literal value allowed
45206c3fb27SDimitry Andric break;
45306c3fb27SDimitry Andric }
45406c3fb27SDimitry Andric }
45506c3fb27SDimitry Andric
getSOPPBrEncoding(const MCInst & MI,unsigned OpNo,APInt & Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const45606c3fb27SDimitry Andric void AMDGPUMCCodeEmitter::getSOPPBrEncoding(const MCInst &MI, unsigned OpNo,
45706c3fb27SDimitry Andric APInt &Op,
45806c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
45906c3fb27SDimitry Andric const MCSubtargetInfo &STI) const {
46006c3fb27SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
46106c3fb27SDimitry Andric
46206c3fb27SDimitry Andric if (MO.isExpr()) {
46306c3fb27SDimitry Andric const MCExpr *Expr = MO.getExpr();
46406c3fb27SDimitry Andric MCFixupKind Kind = (MCFixupKind)AMDGPU::fixup_si_sopp_br;
46506c3fb27SDimitry Andric Fixups.push_back(MCFixup::create(0, Expr, Kind, MI.getLoc()));
46606c3fb27SDimitry Andric Op = APInt::getZero(96);
46706c3fb27SDimitry Andric } else {
46806c3fb27SDimitry Andric getMachineOpValue(MI, MO, Op, Fixups, STI);
46906c3fb27SDimitry Andric }
47006c3fb27SDimitry Andric }
47106c3fb27SDimitry Andric
getSMEMOffsetEncoding(const MCInst & MI,unsigned OpNo,APInt & Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const47206c3fb27SDimitry Andric void AMDGPUMCCodeEmitter::getSMEMOffsetEncoding(
47306c3fb27SDimitry Andric const MCInst &MI, unsigned OpNo, APInt &Op,
47406c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
47506c3fb27SDimitry Andric auto Offset = MI.getOperand(OpNo).getImm();
47606c3fb27SDimitry Andric // VI only supports 20-bit unsigned offsets.
47706c3fb27SDimitry Andric assert(!AMDGPU::isVI(STI) || isUInt<20>(Offset));
47806c3fb27SDimitry Andric Op = Offset;
47906c3fb27SDimitry Andric }
48006c3fb27SDimitry Andric
getSDWASrcEncoding(const MCInst & MI,unsigned OpNo,APInt & Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const48106c3fb27SDimitry Andric void AMDGPUMCCodeEmitter::getSDWASrcEncoding(const MCInst &MI, unsigned OpNo,
48206c3fb27SDimitry Andric APInt &Op,
48306c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
48406c3fb27SDimitry Andric const MCSubtargetInfo &STI) const {
48506c3fb27SDimitry Andric using namespace AMDGPU::SDWA;
48606c3fb27SDimitry Andric
48706c3fb27SDimitry Andric uint64_t RegEnc = 0;
48806c3fb27SDimitry Andric
48906c3fb27SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
49006c3fb27SDimitry Andric
49106c3fb27SDimitry Andric if (MO.isReg()) {
49206c3fb27SDimitry Andric unsigned Reg = MO.getReg();
49306c3fb27SDimitry Andric RegEnc |= MRI.getEncodingValue(Reg);
49406c3fb27SDimitry Andric RegEnc &= SDWA9EncValues::SRC_VGPR_MASK;
49506c3fb27SDimitry Andric if (AMDGPU::isSGPR(AMDGPU::mc2PseudoReg(Reg), &MRI)) {
49606c3fb27SDimitry Andric RegEnc |= SDWA9EncValues::SRC_SGPR_MASK;
49706c3fb27SDimitry Andric }
49806c3fb27SDimitry Andric Op = RegEnc;
49906c3fb27SDimitry Andric return;
50006c3fb27SDimitry Andric } else {
50106c3fb27SDimitry Andric const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
50206c3fb27SDimitry Andric auto Enc = getLitEncoding(MO, Desc.operands()[OpNo], STI);
50306c3fb27SDimitry Andric if (Enc && *Enc != 255) {
50406c3fb27SDimitry Andric Op = *Enc | SDWA9EncValues::SRC_SGPR_MASK;
50506c3fb27SDimitry Andric return;
50606c3fb27SDimitry Andric }
50706c3fb27SDimitry Andric }
50806c3fb27SDimitry Andric
50906c3fb27SDimitry Andric llvm_unreachable("Unsupported operand kind");
51006c3fb27SDimitry Andric }
51106c3fb27SDimitry Andric
getSDWAVopcDstEncoding(const MCInst & MI,unsigned OpNo,APInt & Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const51206c3fb27SDimitry Andric void AMDGPUMCCodeEmitter::getSDWAVopcDstEncoding(
51306c3fb27SDimitry Andric const MCInst &MI, unsigned OpNo, APInt &Op,
51406c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
51506c3fb27SDimitry Andric using namespace AMDGPU::SDWA;
51606c3fb27SDimitry Andric
51706c3fb27SDimitry Andric uint64_t RegEnc = 0;
51806c3fb27SDimitry Andric
51906c3fb27SDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
52006c3fb27SDimitry Andric
52106c3fb27SDimitry Andric unsigned Reg = MO.getReg();
52206c3fb27SDimitry Andric if (Reg != AMDGPU::VCC && Reg != AMDGPU::VCC_LO) {
52306c3fb27SDimitry Andric RegEnc |= MRI.getEncodingValue(Reg);
52406c3fb27SDimitry Andric RegEnc &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
52506c3fb27SDimitry Andric RegEnc |= SDWA9EncValues::VOPC_DST_VCC_MASK;
52606c3fb27SDimitry Andric }
52706c3fb27SDimitry Andric Op = RegEnc;
52806c3fb27SDimitry Andric }
52906c3fb27SDimitry Andric
getAVOperandEncoding(const MCInst & MI,unsigned OpNo,APInt & Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const53006c3fb27SDimitry Andric void AMDGPUMCCodeEmitter::getAVOperandEncoding(
53106c3fb27SDimitry Andric const MCInst &MI, unsigned OpNo, APInt &Op,
53206c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
53306c3fb27SDimitry Andric unsigned Reg = MI.getOperand(OpNo).getReg();
5345f757f3fSDimitry Andric unsigned Enc = MRI.getEncodingValue(Reg);
5355f757f3fSDimitry Andric unsigned Idx = Enc & AMDGPU::HWEncoding::REG_IDX_MASK;
5365f757f3fSDimitry Andric bool IsVGPROrAGPR = Enc & AMDGPU::HWEncoding::IS_VGPR_OR_AGPR;
53706c3fb27SDimitry Andric
53806c3fb27SDimitry Andric // VGPR and AGPR have the same encoding, but SrcA and SrcB operands of mfma
53906c3fb27SDimitry Andric // instructions use acc[0:1] modifier bits to distinguish. These bits are
54006c3fb27SDimitry Andric // encoded as a virtual 9th bit of the register for these operands.
5415f757f3fSDimitry Andric bool IsAGPR = false;
54206c3fb27SDimitry Andric if (MRI.getRegClass(AMDGPU::AGPR_32RegClassID).contains(Reg) ||
54306c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AReg_64RegClassID).contains(Reg) ||
54406c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AReg_96RegClassID).contains(Reg) ||
54506c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AReg_128RegClassID).contains(Reg) ||
54606c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AReg_160RegClassID).contains(Reg) ||
54706c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AReg_192RegClassID).contains(Reg) ||
54806c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AReg_224RegClassID).contains(Reg) ||
54906c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AReg_256RegClassID).contains(Reg) ||
55006c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AReg_288RegClassID).contains(Reg) ||
55106c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AReg_320RegClassID).contains(Reg) ||
55206c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AReg_352RegClassID).contains(Reg) ||
55306c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AReg_384RegClassID).contains(Reg) ||
55406c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AReg_512RegClassID).contains(Reg) ||
55506c3fb27SDimitry Andric MRI.getRegClass(AMDGPU::AGPR_LO16RegClassID).contains(Reg))
5565f757f3fSDimitry Andric IsAGPR = true;
55706c3fb27SDimitry Andric
5585f757f3fSDimitry Andric Op = Idx | (IsVGPROrAGPR << 8) | (IsAGPR << 9);
55906c3fb27SDimitry Andric }
56006c3fb27SDimitry Andric
needsPCRel(const MCExpr * Expr)56106c3fb27SDimitry Andric static bool needsPCRel(const MCExpr *Expr) {
56206c3fb27SDimitry Andric switch (Expr->getKind()) {
56306c3fb27SDimitry Andric case MCExpr::SymbolRef: {
56406c3fb27SDimitry Andric auto *SE = cast<MCSymbolRefExpr>(Expr);
56506c3fb27SDimitry Andric MCSymbolRefExpr::VariantKind Kind = SE->getKind();
56606c3fb27SDimitry Andric return Kind != MCSymbolRefExpr::VK_AMDGPU_ABS32_LO &&
56706c3fb27SDimitry Andric Kind != MCSymbolRefExpr::VK_AMDGPU_ABS32_HI;
56806c3fb27SDimitry Andric }
56906c3fb27SDimitry Andric case MCExpr::Binary: {
57006c3fb27SDimitry Andric auto *BE = cast<MCBinaryExpr>(Expr);
57106c3fb27SDimitry Andric if (BE->getOpcode() == MCBinaryExpr::Sub)
57206c3fb27SDimitry Andric return false;
57306c3fb27SDimitry Andric return needsPCRel(BE->getLHS()) || needsPCRel(BE->getRHS());
57406c3fb27SDimitry Andric }
57506c3fb27SDimitry Andric case MCExpr::Unary:
57606c3fb27SDimitry Andric return needsPCRel(cast<MCUnaryExpr>(Expr)->getSubExpr());
57706c3fb27SDimitry Andric case MCExpr::Target:
57806c3fb27SDimitry Andric case MCExpr::Constant:
57906c3fb27SDimitry Andric return false;
58006c3fb27SDimitry Andric }
58106c3fb27SDimitry Andric llvm_unreachable("invalid kind");
58206c3fb27SDimitry Andric }
58306c3fb27SDimitry Andric
getMachineOpValue(const MCInst & MI,const MCOperand & MO,APInt & Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const58406c3fb27SDimitry Andric void AMDGPUMCCodeEmitter::getMachineOpValue(const MCInst &MI,
58506c3fb27SDimitry Andric const MCOperand &MO, APInt &Op,
58606c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups,
58706c3fb27SDimitry Andric const MCSubtargetInfo &STI) const {
58806c3fb27SDimitry Andric if (MO.isReg()){
5895f757f3fSDimitry Andric unsigned Enc = MRI.getEncodingValue(MO.getReg());
5905f757f3fSDimitry Andric unsigned Idx = Enc & AMDGPU::HWEncoding::REG_IDX_MASK;
5915f757f3fSDimitry Andric bool IsVGPR = Enc & AMDGPU::HWEncoding::IS_VGPR_OR_AGPR;
5925f757f3fSDimitry Andric Op = Idx | (IsVGPR << 8);
59306c3fb27SDimitry Andric return;
59406c3fb27SDimitry Andric }
59506c3fb27SDimitry Andric unsigned OpNo = &MO - MI.begin();
59606c3fb27SDimitry Andric getMachineOpValueCommon(MI, MO, OpNo, Op, Fixups, STI);
59706c3fb27SDimitry Andric }
59806c3fb27SDimitry Andric
getMachineOpValueT16(const MCInst & MI,unsigned OpNo,APInt & Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const5995f757f3fSDimitry Andric void AMDGPUMCCodeEmitter::getMachineOpValueT16(
6005f757f3fSDimitry Andric const MCInst &MI, unsigned OpNo, APInt &Op,
6015f757f3fSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
6027a6dacacSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
6037a6dacacSDimitry Andric if (MO.isReg()) {
6047a6dacacSDimitry Andric unsigned Enc = MRI.getEncodingValue(MO.getReg());
6057a6dacacSDimitry Andric unsigned Idx = Enc & AMDGPU::HWEncoding::REG_IDX_MASK;
6067a6dacacSDimitry Andric bool IsVGPR = Enc & AMDGPU::HWEncoding::IS_VGPR_OR_AGPR;
6077a6dacacSDimitry Andric Op = Idx | (IsVGPR << 8);
6087a6dacacSDimitry Andric return;
6097a6dacacSDimitry Andric }
6107a6dacacSDimitry Andric getMachineOpValueCommon(MI, MO, OpNo, Op, Fixups, STI);
6117a6dacacSDimitry Andric // VGPRs include the suffix/op_sel bit in the register encoding, but
6127a6dacacSDimitry Andric // immediates and SGPRs include it in src_modifiers. Therefore, copy the
6137a6dacacSDimitry Andric // op_sel bit from the src operands into src_modifier operands if Op is
6147a6dacacSDimitry Andric // src_modifiers and the corresponding src is a VGPR
6157a6dacacSDimitry Andric int SrcMOIdx = -1;
6167a6dacacSDimitry Andric assert(OpNo < INT_MAX);
6177a6dacacSDimitry Andric if ((int)OpNo == AMDGPU::getNamedOperandIdx(MI.getOpcode(),
6187a6dacacSDimitry Andric AMDGPU::OpName::src0_modifiers)) {
6197a6dacacSDimitry Andric SrcMOIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
6207a6dacacSDimitry Andric int VDstMOIdx =
6217a6dacacSDimitry Andric AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdst);
6227a6dacacSDimitry Andric if (VDstMOIdx != -1) {
6237a6dacacSDimitry Andric auto DstReg = MI.getOperand(VDstMOIdx).getReg();
6247a6dacacSDimitry Andric if (AMDGPU::isHi(DstReg, MRI))
6257a6dacacSDimitry Andric Op |= SISrcMods::DST_OP_SEL;
6267a6dacacSDimitry Andric }
6277a6dacacSDimitry Andric } else if ((int)OpNo == AMDGPU::getNamedOperandIdx(
6287a6dacacSDimitry Andric MI.getOpcode(), AMDGPU::OpName::src1_modifiers))
6297a6dacacSDimitry Andric SrcMOIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);
6307a6dacacSDimitry Andric else if ((int)OpNo == AMDGPU::getNamedOperandIdx(
6317a6dacacSDimitry Andric MI.getOpcode(), AMDGPU::OpName::src2_modifiers))
6327a6dacacSDimitry Andric SrcMOIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src2);
6337a6dacacSDimitry Andric if (SrcMOIdx == -1)
6347a6dacacSDimitry Andric return;
6357a6dacacSDimitry Andric
6367a6dacacSDimitry Andric const MCOperand &SrcMO = MI.getOperand(SrcMOIdx);
6377a6dacacSDimitry Andric if (!SrcMO.isReg())
6387a6dacacSDimitry Andric return;
6397a6dacacSDimitry Andric auto SrcReg = SrcMO.getReg();
6407a6dacacSDimitry Andric if (AMDGPU::isSGPR(SrcReg, &MRI))
6417a6dacacSDimitry Andric return;
6427a6dacacSDimitry Andric if (AMDGPU::isHi(SrcReg, MRI))
6437a6dacacSDimitry Andric Op |= SISrcMods::OP_SEL_0;
6445f757f3fSDimitry Andric }
6455f757f3fSDimitry Andric
getMachineOpValueT16Lo128(const MCInst & MI,unsigned OpNo,APInt & Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const6465f757f3fSDimitry Andric void AMDGPUMCCodeEmitter::getMachineOpValueT16Lo128(
6475f757f3fSDimitry Andric const MCInst &MI, unsigned OpNo, APInt &Op,
6485f757f3fSDimitry Andric SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
6495f757f3fSDimitry Andric const MCOperand &MO = MI.getOperand(OpNo);
6505f757f3fSDimitry Andric if (MO.isReg()) {
6515f757f3fSDimitry Andric uint16_t Encoding = MRI.getEncodingValue(MO.getReg());
6525f757f3fSDimitry Andric unsigned RegIdx = Encoding & AMDGPU::HWEncoding::REG_IDX_MASK;
6535f757f3fSDimitry Andric bool IsHi = Encoding & AMDGPU::HWEncoding::IS_HI;
6545f757f3fSDimitry Andric bool IsVGPR = Encoding & AMDGPU::HWEncoding::IS_VGPR_OR_AGPR;
6555f757f3fSDimitry Andric assert((!IsVGPR || isUInt<7>(RegIdx)) && "VGPR0-VGPR127 expected!");
6565f757f3fSDimitry Andric Op = (IsVGPR ? 0x100 : 0) | (IsHi ? 0x80 : 0) | RegIdx;
6575f757f3fSDimitry Andric return;
6585f757f3fSDimitry Andric }
6595f757f3fSDimitry Andric getMachineOpValueCommon(MI, MO, OpNo, Op, Fixups, STI);
6605f757f3fSDimitry Andric }
6615f757f3fSDimitry Andric
getMachineOpValueCommon(const MCInst & MI,const MCOperand & MO,unsigned OpNo,APInt & Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const66206c3fb27SDimitry Andric void AMDGPUMCCodeEmitter::getMachineOpValueCommon(
66306c3fb27SDimitry Andric const MCInst &MI, const MCOperand &MO, unsigned OpNo, APInt &Op,
66406c3fb27SDimitry Andric SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const {
665*0fca6ea1SDimitry Andric int64_t Val;
666*0fca6ea1SDimitry Andric if (MO.isExpr() && MO.getExpr()->evaluateAsAbsolute(Val)) {
667*0fca6ea1SDimitry Andric Op = Val;
668*0fca6ea1SDimitry Andric return;
669*0fca6ea1SDimitry Andric }
67006c3fb27SDimitry Andric
67106c3fb27SDimitry Andric if (MO.isExpr() && MO.getExpr()->getKind() != MCExpr::Constant) {
67206c3fb27SDimitry Andric // FIXME: If this is expression is PCRel or not should not depend on what
67306c3fb27SDimitry Andric // the expression looks like. Given that this is just a general expression,
67406c3fb27SDimitry Andric // it should probably be FK_Data_4 and whatever is producing
67506c3fb27SDimitry Andric //
67606c3fb27SDimitry Andric // s_add_u32 s2, s2, (extern_const_addrspace+16
67706c3fb27SDimitry Andric //
67806c3fb27SDimitry Andric // And expecting a PCRel should instead produce
67906c3fb27SDimitry Andric //
68006c3fb27SDimitry Andric // .Ltmp1:
68106c3fb27SDimitry Andric // s_add_u32 s2, s2, (extern_const_addrspace+16)-.Ltmp1
68206c3fb27SDimitry Andric MCFixupKind Kind;
68306c3fb27SDimitry Andric if (needsPCRel(MO.getExpr()))
68406c3fb27SDimitry Andric Kind = FK_PCRel_4;
68506c3fb27SDimitry Andric else
68606c3fb27SDimitry Andric Kind = FK_Data_4;
68706c3fb27SDimitry Andric
68806c3fb27SDimitry Andric const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
68906c3fb27SDimitry Andric uint32_t Offset = Desc.getSize();
69006c3fb27SDimitry Andric assert(Offset == 4 || Offset == 8);
69106c3fb27SDimitry Andric
69206c3fb27SDimitry Andric Fixups.push_back(MCFixup::create(Offset, MO.getExpr(), Kind, MI.getLoc()));
69306c3fb27SDimitry Andric }
69406c3fb27SDimitry Andric
69506c3fb27SDimitry Andric const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
69606c3fb27SDimitry Andric if (AMDGPU::isSISrcOperand(Desc, OpNo)) {
69706c3fb27SDimitry Andric if (auto Enc = getLitEncoding(MO, Desc.operands()[OpNo], STI)) {
69806c3fb27SDimitry Andric Op = *Enc;
69906c3fb27SDimitry Andric return;
70006c3fb27SDimitry Andric }
70106c3fb27SDimitry Andric } else if (MO.isImm()) {
70206c3fb27SDimitry Andric Op = MO.getImm();
70306c3fb27SDimitry Andric return;
70406c3fb27SDimitry Andric }
70506c3fb27SDimitry Andric
70606c3fb27SDimitry Andric llvm_unreachable("Encoding of this operand type is not supported yet.");
70706c3fb27SDimitry Andric }
70806c3fb27SDimitry Andric
70906c3fb27SDimitry Andric #include "AMDGPUGenMCCodeEmitter.inc"
710