1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceAssemblerMIPS32.cpp - MIPS32 Assembler --------------===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Implements the Assembler class for MIPS32.
12*03ce13f7SAndroid Build Coastguard Worker ///
13*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Worker #include "IceAssemblerMIPS32.h"
16*03ce13f7SAndroid Build Coastguard Worker #include "IceCfgNode.h"
17*03ce13f7SAndroid Build Coastguard Worker #include "IceRegistersMIPS32.h"
18*03ce13f7SAndroid Build Coastguard Worker #include "IceUtils.h"
19*03ce13f7SAndroid Build Coastguard Worker
20*03ce13f7SAndroid Build Coastguard Worker namespace {
21*03ce13f7SAndroid Build Coastguard Worker
22*03ce13f7SAndroid Build Coastguard Worker using namespace Ice;
23*03ce13f7SAndroid Build Coastguard Worker using namespace Ice::MIPS32;
24*03ce13f7SAndroid Build Coastguard Worker
25*03ce13f7SAndroid Build Coastguard Worker // Offset modifier to current PC for next instruction.
26*03ce13f7SAndroid Build Coastguard Worker static constexpr IOffsetT kPCReadOffset = 4;
27*03ce13f7SAndroid Build Coastguard Worker
28*03ce13f7SAndroid Build Coastguard Worker // Mask to pull out PC offset from branch instruction.
29*03ce13f7SAndroid Build Coastguard Worker static constexpr int kBranchOffsetBits = 16;
30*03ce13f7SAndroid Build Coastguard Worker static constexpr IOffsetT kBranchOffsetMask = 0x0000ffff;
31*03ce13f7SAndroid Build Coastguard Worker
32*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
33*03ce13f7SAndroid Build Coastguard Worker
34*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
35*03ce13f7SAndroid Build Coastguard Worker namespace MIPS32 {
36*03ce13f7SAndroid Build Coastguard Worker
emitTextInst(const std::string & Text,SizeT InstSize)37*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitTextInst(const std::string &Text, SizeT InstSize) {
38*03ce13f7SAndroid Build Coastguard Worker AssemblerFixup *F = createTextFixup(Text, InstSize);
39*03ce13f7SAndroid Build Coastguard Worker emitFixup(F);
40*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < InstSize; ++I) {
41*03ce13f7SAndroid Build Coastguard Worker AssemblerBuffer::EnsureCapacity ensured(&Buffer);
42*03ce13f7SAndroid Build Coastguard Worker Buffer.emit<char>(0);
43*03ce13f7SAndroid Build Coastguard Worker }
44*03ce13f7SAndroid Build Coastguard Worker }
45*03ce13f7SAndroid Build Coastguard Worker
46*03ce13f7SAndroid Build Coastguard Worker namespace {
47*03ce13f7SAndroid Build Coastguard Worker
48*03ce13f7SAndroid Build Coastguard Worker // TEQ $0, $0 - Trap if equal
49*03ce13f7SAndroid Build Coastguard Worker static constexpr uint8_t TrapBytesRaw[] = {0x00, 0x00, 0x00, 0x34};
50*03ce13f7SAndroid Build Coastguard Worker
51*03ce13f7SAndroid Build Coastguard Worker const auto TrapBytes =
52*03ce13f7SAndroid Build Coastguard Worker llvm::ArrayRef<uint8_t>(TrapBytesRaw, llvm::array_lengthof(TrapBytesRaw));
53*03ce13f7SAndroid Build Coastguard Worker
54*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
55*03ce13f7SAndroid Build Coastguard Worker
getNonExecBundlePadding() const56*03ce13f7SAndroid Build Coastguard Worker llvm::ArrayRef<uint8_t> AssemblerMIPS32::getNonExecBundlePadding() const {
57*03ce13f7SAndroid Build Coastguard Worker return TrapBytes;
58*03ce13f7SAndroid Build Coastguard Worker }
59*03ce13f7SAndroid Build Coastguard Worker
trap()60*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::trap() {
61*03ce13f7SAndroid Build Coastguard Worker AssemblerBuffer::EnsureCapacity ensured(&Buffer);
62*03ce13f7SAndroid Build Coastguard Worker for (const uint8_t &Byte : reverse_range(TrapBytes))
63*03ce13f7SAndroid Build Coastguard Worker Buffer.emit<uint8_t>(Byte);
64*03ce13f7SAndroid Build Coastguard Worker }
65*03ce13f7SAndroid Build Coastguard Worker
nop()66*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::nop() { emitInst(0); }
67*03ce13f7SAndroid Build Coastguard Worker
padWithNop(intptr_t Padding)68*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::padWithNop(intptr_t Padding) {
69*03ce13f7SAndroid Build Coastguard Worker constexpr intptr_t InstWidth = sizeof(IValueT);
70*03ce13f7SAndroid Build Coastguard Worker assert(Padding % InstWidth == 0 &&
71*03ce13f7SAndroid Build Coastguard Worker "Padding not multiple of instruction size");
72*03ce13f7SAndroid Build Coastguard Worker for (intptr_t i = 0; i < Padding; i += InstWidth)
73*03ce13f7SAndroid Build Coastguard Worker nop();
74*03ce13f7SAndroid Build Coastguard Worker }
75*03ce13f7SAndroid Build Coastguard Worker
getOrCreateLabel(SizeT Number,LabelVector & Labels)76*03ce13f7SAndroid Build Coastguard Worker Label *AssemblerMIPS32::getOrCreateLabel(SizeT Number, LabelVector &Labels) {
77*03ce13f7SAndroid Build Coastguard Worker Label *L = nullptr;
78*03ce13f7SAndroid Build Coastguard Worker if (Number == Labels.size()) {
79*03ce13f7SAndroid Build Coastguard Worker L = new (this->allocate<Label>()) Label();
80*03ce13f7SAndroid Build Coastguard Worker Labels.push_back(L);
81*03ce13f7SAndroid Build Coastguard Worker return L;
82*03ce13f7SAndroid Build Coastguard Worker }
83*03ce13f7SAndroid Build Coastguard Worker if (Number > Labels.size()) {
84*03ce13f7SAndroid Build Coastguard Worker Labels.resize(Number + 1);
85*03ce13f7SAndroid Build Coastguard Worker }
86*03ce13f7SAndroid Build Coastguard Worker L = Labels[Number];
87*03ce13f7SAndroid Build Coastguard Worker if (L == nullptr) {
88*03ce13f7SAndroid Build Coastguard Worker L = new (this->allocate<Label>()) Label();
89*03ce13f7SAndroid Build Coastguard Worker Labels[Number] = L;
90*03ce13f7SAndroid Build Coastguard Worker }
91*03ce13f7SAndroid Build Coastguard Worker return L;
92*03ce13f7SAndroid Build Coastguard Worker }
93*03ce13f7SAndroid Build Coastguard Worker
bindCfgNodeLabel(const CfgNode * Node)94*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::bindCfgNodeLabel(const CfgNode *Node) {
95*03ce13f7SAndroid Build Coastguard Worker if (BuildDefs::dump() && !getFlags().getDisableHybridAssembly()) {
96*03ce13f7SAndroid Build Coastguard Worker constexpr SizeT InstSize = 0;
97*03ce13f7SAndroid Build Coastguard Worker emitTextInst(Node->getAsmName() + ":", InstSize);
98*03ce13f7SAndroid Build Coastguard Worker }
99*03ce13f7SAndroid Build Coastguard Worker SizeT NodeNumber = Node->getIndex();
100*03ce13f7SAndroid Build Coastguard Worker assert(!getPreliminary());
101*03ce13f7SAndroid Build Coastguard Worker Label *L = getOrCreateCfgNodeLabel(NodeNumber);
102*03ce13f7SAndroid Build Coastguard Worker this->bind(L);
103*03ce13f7SAndroid Build Coastguard Worker }
104*03ce13f7SAndroid Build Coastguard Worker
105*03ce13f7SAndroid Build Coastguard Worker namespace {
106*03ce13f7SAndroid Build Coastguard Worker
107*03ce13f7SAndroid Build Coastguard Worker // Checks that Offset can fit in imm16 constant of branch instruction.
assertCanEncodeBranchOffset(IOffsetT Offset)108*03ce13f7SAndroid Build Coastguard Worker void assertCanEncodeBranchOffset(IOffsetT Offset) {
109*03ce13f7SAndroid Build Coastguard Worker (void)Offset;
110*03ce13f7SAndroid Build Coastguard Worker (void)kBranchOffsetBits;
111*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsAligned(Offset, 4));
112*03ce13f7SAndroid Build Coastguard Worker assert(Utils::IsInt(kBranchOffsetBits, Offset >> 2));
113*03ce13f7SAndroid Build Coastguard Worker }
114*03ce13f7SAndroid Build Coastguard Worker
encodeBranchOffset(IOffsetT Offset,IValueT Inst)115*03ce13f7SAndroid Build Coastguard Worker IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst) {
116*03ce13f7SAndroid Build Coastguard Worker Offset -= kPCReadOffset;
117*03ce13f7SAndroid Build Coastguard Worker assertCanEncodeBranchOffset(Offset);
118*03ce13f7SAndroid Build Coastguard Worker Offset >>= 2;
119*03ce13f7SAndroid Build Coastguard Worker Offset &= kBranchOffsetMask;
120*03ce13f7SAndroid Build Coastguard Worker return (Inst & ~kBranchOffsetMask) | Offset;
121*03ce13f7SAndroid Build Coastguard Worker }
122*03ce13f7SAndroid Build Coastguard Worker
123*03ce13f7SAndroid Build Coastguard Worker enum RegSetWanted { WantGPRegs, WantFPRegs };
124*03ce13f7SAndroid Build Coastguard Worker
getEncodedGPRegNum(const Variable * Var)125*03ce13f7SAndroid Build Coastguard Worker IValueT getEncodedGPRegNum(const Variable *Var) {
126*03ce13f7SAndroid Build Coastguard Worker assert(Var->hasReg() && isScalarIntegerType(Var->getType()));
127*03ce13f7SAndroid Build Coastguard Worker const auto Reg = Var->getRegNum();
128*03ce13f7SAndroid Build Coastguard Worker return RegMIPS32::getEncodedGPR(Reg);
129*03ce13f7SAndroid Build Coastguard Worker }
130*03ce13f7SAndroid Build Coastguard Worker
getEncodedFPRegNum(const Variable * Var)131*03ce13f7SAndroid Build Coastguard Worker IValueT getEncodedFPRegNum(const Variable *Var) {
132*03ce13f7SAndroid Build Coastguard Worker assert(Var->hasReg() && isScalarFloatingType(Var->getType()));
133*03ce13f7SAndroid Build Coastguard Worker const auto Reg = Var->getRegNum();
134*03ce13f7SAndroid Build Coastguard Worker IValueT RegEncoding;
135*03ce13f7SAndroid Build Coastguard Worker if (RegMIPS32::isFPRReg(Reg)) {
136*03ce13f7SAndroid Build Coastguard Worker RegEncoding = RegMIPS32::getEncodedFPR(Reg);
137*03ce13f7SAndroid Build Coastguard Worker } else {
138*03ce13f7SAndroid Build Coastguard Worker RegEncoding = RegMIPS32::getEncodedFPR64(Reg);
139*03ce13f7SAndroid Build Coastguard Worker }
140*03ce13f7SAndroid Build Coastguard Worker return RegEncoding;
141*03ce13f7SAndroid Build Coastguard Worker }
142*03ce13f7SAndroid Build Coastguard Worker
encodeOperand(const Operand * Opnd,IValueT & Value,RegSetWanted WantedRegSet)143*03ce13f7SAndroid Build Coastguard Worker bool encodeOperand(const Operand *Opnd, IValueT &Value,
144*03ce13f7SAndroid Build Coastguard Worker RegSetWanted WantedRegSet) {
145*03ce13f7SAndroid Build Coastguard Worker Value = 0;
146*03ce13f7SAndroid Build Coastguard Worker if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
147*03ce13f7SAndroid Build Coastguard Worker if (Var->hasReg()) {
148*03ce13f7SAndroid Build Coastguard Worker switch (WantedRegSet) {
149*03ce13f7SAndroid Build Coastguard Worker case WantGPRegs:
150*03ce13f7SAndroid Build Coastguard Worker Value = getEncodedGPRegNum(Var);
151*03ce13f7SAndroid Build Coastguard Worker break;
152*03ce13f7SAndroid Build Coastguard Worker case WantFPRegs:
153*03ce13f7SAndroid Build Coastguard Worker Value = getEncodedFPRegNum(Var);
154*03ce13f7SAndroid Build Coastguard Worker break;
155*03ce13f7SAndroid Build Coastguard Worker }
156*03ce13f7SAndroid Build Coastguard Worker return true;
157*03ce13f7SAndroid Build Coastguard Worker }
158*03ce13f7SAndroid Build Coastguard Worker return false;
159*03ce13f7SAndroid Build Coastguard Worker }
160*03ce13f7SAndroid Build Coastguard Worker return false;
161*03ce13f7SAndroid Build Coastguard Worker }
162*03ce13f7SAndroid Build Coastguard Worker
encodeRegister(const Operand * OpReg,RegSetWanted WantedRegSet,const char * RegName,const char * InstName)163*03ce13f7SAndroid Build Coastguard Worker IValueT encodeRegister(const Operand *OpReg, RegSetWanted WantedRegSet,
164*03ce13f7SAndroid Build Coastguard Worker const char *RegName, const char *InstName) {
165*03ce13f7SAndroid Build Coastguard Worker IValueT Reg = 0;
166*03ce13f7SAndroid Build Coastguard Worker if (encodeOperand(OpReg, Reg, WantedRegSet) != true)
167*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InstName) + ": Can't find register " +
168*03ce13f7SAndroid Build Coastguard Worker RegName);
169*03ce13f7SAndroid Build Coastguard Worker return Reg;
170*03ce13f7SAndroid Build Coastguard Worker }
171*03ce13f7SAndroid Build Coastguard Worker
encodeGPRegister(const Operand * OpReg,const char * RegName,const char * InstName)172*03ce13f7SAndroid Build Coastguard Worker IValueT encodeGPRegister(const Operand *OpReg, const char *RegName,
173*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
174*03ce13f7SAndroid Build Coastguard Worker return encodeRegister(OpReg, WantGPRegs, RegName, InstName);
175*03ce13f7SAndroid Build Coastguard Worker }
176*03ce13f7SAndroid Build Coastguard Worker
encodeFPRegister(const Operand * OpReg,const char * RegName,const char * InstName)177*03ce13f7SAndroid Build Coastguard Worker IValueT encodeFPRegister(const Operand *OpReg, const char *RegName,
178*03ce13f7SAndroid Build Coastguard Worker const char *InstName) {
179*03ce13f7SAndroid Build Coastguard Worker return encodeRegister(OpReg, WantFPRegs, RegName, InstName);
180*03ce13f7SAndroid Build Coastguard Worker }
181*03ce13f7SAndroid Build Coastguard Worker
182*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
183*03ce13f7SAndroid Build Coastguard Worker
decodeBranchOffset(IValueT Inst)184*03ce13f7SAndroid Build Coastguard Worker IOffsetT AssemblerMIPS32::decodeBranchOffset(IValueT Inst) {
185*03ce13f7SAndroid Build Coastguard Worker int16_t imm = (Inst & kBranchOffsetMask);
186*03ce13f7SAndroid Build Coastguard Worker IOffsetT Offset = imm;
187*03ce13f7SAndroid Build Coastguard Worker Offset = Offset << 2;
188*03ce13f7SAndroid Build Coastguard Worker return (Offset + kPCReadOffset);
189*03ce13f7SAndroid Build Coastguard Worker }
190*03ce13f7SAndroid Build Coastguard Worker
bind(Label * L)191*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::bind(Label *L) {
192*03ce13f7SAndroid Build Coastguard Worker IOffsetT BoundPc = Buffer.size();
193*03ce13f7SAndroid Build Coastguard Worker assert(!L->isBound()); // Labels can only be bound once.
194*03ce13f7SAndroid Build Coastguard Worker while (L->isLinked()) {
195*03ce13f7SAndroid Build Coastguard Worker IOffsetT Position = L->getLinkPosition();
196*03ce13f7SAndroid Build Coastguard Worker IOffsetT Dest = BoundPc - Position;
197*03ce13f7SAndroid Build Coastguard Worker IValueT Inst = Buffer.load<IValueT>(Position);
198*03ce13f7SAndroid Build Coastguard Worker Buffer.store<IValueT>(Position, encodeBranchOffset(Dest, Inst));
199*03ce13f7SAndroid Build Coastguard Worker IOffsetT NextBrPc = decodeBranchOffset(Inst);
200*03ce13f7SAndroid Build Coastguard Worker if (NextBrPc != 0)
201*03ce13f7SAndroid Build Coastguard Worker NextBrPc = Position - NextBrPc;
202*03ce13f7SAndroid Build Coastguard Worker L->setPosition(NextBrPc);
203*03ce13f7SAndroid Build Coastguard Worker }
204*03ce13f7SAndroid Build Coastguard Worker L->bindTo(BoundPc);
205*03ce13f7SAndroid Build Coastguard Worker }
206*03ce13f7SAndroid Build Coastguard Worker
emitRsRt(IValueT Opcode,const Operand * OpRs,const Operand * OpRt,const char * InsnName)207*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitRsRt(IValueT Opcode, const Operand *OpRs,
208*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt, const char *InsnName) {
209*03ce13f7SAndroid Build Coastguard Worker const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
210*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
211*03ce13f7SAndroid Build Coastguard Worker
212*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
213*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
214*03ce13f7SAndroid Build Coastguard Worker
215*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
216*03ce13f7SAndroid Build Coastguard Worker }
217*03ce13f7SAndroid Build Coastguard Worker
emitRtRsImm16(IValueT Opcode,const Operand * OpRt,const Operand * OpRs,const uint32_t Imm,const char * InsnName)218*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitRtRsImm16(IValueT Opcode, const Operand *OpRt,
219*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRs, const uint32_t Imm,
220*03ce13f7SAndroid Build Coastguard Worker const char *InsnName) {
221*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
222*03ce13f7SAndroid Build Coastguard Worker const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
223*03ce13f7SAndroid Build Coastguard Worker
224*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
225*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
226*03ce13f7SAndroid Build Coastguard Worker Opcode |= Imm & 0xffff;
227*03ce13f7SAndroid Build Coastguard Worker
228*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
229*03ce13f7SAndroid Build Coastguard Worker }
230*03ce13f7SAndroid Build Coastguard Worker
emitRtRsImm16Rel(IValueT Opcode,const Operand * OpRt,const Operand * OpRs,const Operand * OpImm,const RelocOp Reloc,const char * InsnName)231*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitRtRsImm16Rel(IValueT Opcode, const Operand *OpRt,
232*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRs,
233*03ce13f7SAndroid Build Coastguard Worker const Operand *OpImm,
234*03ce13f7SAndroid Build Coastguard Worker const RelocOp Reloc,
235*03ce13f7SAndroid Build Coastguard Worker const char *InsnName) {
236*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
237*03ce13f7SAndroid Build Coastguard Worker const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
238*03ce13f7SAndroid Build Coastguard Worker uint32_t Imm16 = 0;
239*03ce13f7SAndroid Build Coastguard Worker
240*03ce13f7SAndroid Build Coastguard Worker if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpImm)) {
241*03ce13f7SAndroid Build Coastguard Worker emitFixup(createMIPS32Fixup(Reloc, OpRel));
242*03ce13f7SAndroid Build Coastguard Worker } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpImm)) {
243*03ce13f7SAndroid Build Coastguard Worker Imm16 = C32->getValue();
244*03ce13f7SAndroid Build Coastguard Worker } else {
245*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error(std::string(InsnName) + ": Invalid 3rd operand");
246*03ce13f7SAndroid Build Coastguard Worker }
247*03ce13f7SAndroid Build Coastguard Worker
248*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
249*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
250*03ce13f7SAndroid Build Coastguard Worker Opcode |= Imm16 & 0xffff;
251*03ce13f7SAndroid Build Coastguard Worker
252*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
253*03ce13f7SAndroid Build Coastguard Worker }
254*03ce13f7SAndroid Build Coastguard Worker
emitFtRsImm16(IValueT Opcode,const Operand * OpFt,const Operand * OpRs,const uint32_t Imm,const char * InsnName)255*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitFtRsImm16(IValueT Opcode, const Operand *OpFt,
256*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRs, const uint32_t Imm,
257*03ce13f7SAndroid Build Coastguard Worker const char *InsnName) {
258*03ce13f7SAndroid Build Coastguard Worker const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName);
259*03ce13f7SAndroid Build Coastguard Worker const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
260*03ce13f7SAndroid Build Coastguard Worker
261*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
262*03ce13f7SAndroid Build Coastguard Worker Opcode |= Ft << 16;
263*03ce13f7SAndroid Build Coastguard Worker Opcode |= Imm & 0xffff;
264*03ce13f7SAndroid Build Coastguard Worker
265*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
266*03ce13f7SAndroid Build Coastguard Worker }
267*03ce13f7SAndroid Build Coastguard Worker
emitRdRtSa(IValueT Opcode,const Operand * OpRd,const Operand * OpRt,const uint32_t Sa,const char * InsnName)268*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitRdRtSa(IValueT Opcode, const Operand *OpRd,
269*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt, const uint32_t Sa,
270*03ce13f7SAndroid Build Coastguard Worker const char *InsnName) {
271*03ce13f7SAndroid Build Coastguard Worker const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName);
272*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
273*03ce13f7SAndroid Build Coastguard Worker
274*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
275*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rd << 11;
276*03ce13f7SAndroid Build Coastguard Worker Opcode |= (Sa & 0x1f) << 6;
277*03ce13f7SAndroid Build Coastguard Worker
278*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
279*03ce13f7SAndroid Build Coastguard Worker }
280*03ce13f7SAndroid Build Coastguard Worker
emitRdRsRt(IValueT Opcode,const Operand * OpRd,const Operand * OpRs,const Operand * OpRt,const char * InsnName)281*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitRdRsRt(IValueT Opcode, const Operand *OpRd,
282*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRs, const Operand *OpRt,
283*03ce13f7SAndroid Build Coastguard Worker const char *InsnName) {
284*03ce13f7SAndroid Build Coastguard Worker const IValueT Rd = encodeGPRegister(OpRd, "Rd", InsnName);
285*03ce13f7SAndroid Build Coastguard Worker const IValueT Rs = encodeGPRegister(OpRs, "Rs", InsnName);
286*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
287*03ce13f7SAndroid Build Coastguard Worker
288*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
289*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
290*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rd << 11;
291*03ce13f7SAndroid Build Coastguard Worker
292*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
293*03ce13f7SAndroid Build Coastguard Worker }
294*03ce13f7SAndroid Build Coastguard Worker
emitCOP1Fcmp(IValueT Opcode,FPInstDataFormat Format,const Operand * OpFs,const Operand * OpFt,IValueT CC,const char * InsnName)295*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitCOP1Fcmp(IValueT Opcode, FPInstDataFormat Format,
296*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFs, const Operand *OpFt,
297*03ce13f7SAndroid Build Coastguard Worker IValueT CC, const char *InsnName) {
298*03ce13f7SAndroid Build Coastguard Worker const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
299*03ce13f7SAndroid Build Coastguard Worker const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName);
300*03ce13f7SAndroid Build Coastguard Worker
301*03ce13f7SAndroid Build Coastguard Worker Opcode |= CC << 8;
302*03ce13f7SAndroid Build Coastguard Worker Opcode |= Fs << 11;
303*03ce13f7SAndroid Build Coastguard Worker Opcode |= Ft << 16;
304*03ce13f7SAndroid Build Coastguard Worker Opcode |= Format << 21;
305*03ce13f7SAndroid Build Coastguard Worker
306*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
307*03ce13f7SAndroid Build Coastguard Worker }
308*03ce13f7SAndroid Build Coastguard Worker
emitCOP1FmtFsFd(IValueT Opcode,FPInstDataFormat Format,const Operand * OpFd,const Operand * OpFs,const char * InsnName)309*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitCOP1FmtFsFd(IValueT Opcode, FPInstDataFormat Format,
310*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFd, const Operand *OpFs,
311*03ce13f7SAndroid Build Coastguard Worker const char *InsnName) {
312*03ce13f7SAndroid Build Coastguard Worker const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName);
313*03ce13f7SAndroid Build Coastguard Worker const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
314*03ce13f7SAndroid Build Coastguard Worker
315*03ce13f7SAndroid Build Coastguard Worker Opcode |= Fd << 6;
316*03ce13f7SAndroid Build Coastguard Worker Opcode |= Fs << 11;
317*03ce13f7SAndroid Build Coastguard Worker Opcode |= Format << 21;
318*03ce13f7SAndroid Build Coastguard Worker
319*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
320*03ce13f7SAndroid Build Coastguard Worker }
321*03ce13f7SAndroid Build Coastguard Worker
emitCOP1FmtFtFsFd(IValueT Opcode,FPInstDataFormat Format,const Operand * OpFd,const Operand * OpFs,const Operand * OpFt,const char * InsnName)322*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitCOP1FmtFtFsFd(IValueT Opcode, FPInstDataFormat Format,
323*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFd,
324*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFs,
325*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt,
326*03ce13f7SAndroid Build Coastguard Worker const char *InsnName) {
327*03ce13f7SAndroid Build Coastguard Worker const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName);
328*03ce13f7SAndroid Build Coastguard Worker const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
329*03ce13f7SAndroid Build Coastguard Worker const IValueT Ft = encodeFPRegister(OpFt, "Ft", InsnName);
330*03ce13f7SAndroid Build Coastguard Worker
331*03ce13f7SAndroid Build Coastguard Worker Opcode |= Fd << 6;
332*03ce13f7SAndroid Build Coastguard Worker Opcode |= Fs << 11;
333*03ce13f7SAndroid Build Coastguard Worker Opcode |= Ft << 16;
334*03ce13f7SAndroid Build Coastguard Worker Opcode |= Format << 21;
335*03ce13f7SAndroid Build Coastguard Worker
336*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
337*03ce13f7SAndroid Build Coastguard Worker }
338*03ce13f7SAndroid Build Coastguard Worker
emitCOP1FmtRtFsFd(IValueT Opcode,FPInstDataFormat Format,const Operand * OpFd,const Operand * OpFs,const Operand * OpRt,const char * InsnName)339*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitCOP1FmtRtFsFd(IValueT Opcode, FPInstDataFormat Format,
340*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFd,
341*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFs,
342*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt,
343*03ce13f7SAndroid Build Coastguard Worker const char *InsnName) {
344*03ce13f7SAndroid Build Coastguard Worker const IValueT Fd = encodeFPRegister(OpFd, "Fd", InsnName);
345*03ce13f7SAndroid Build Coastguard Worker const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
346*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
347*03ce13f7SAndroid Build Coastguard Worker
348*03ce13f7SAndroid Build Coastguard Worker Opcode |= Fd << 6;
349*03ce13f7SAndroid Build Coastguard Worker Opcode |= Fs << 11;
350*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
351*03ce13f7SAndroid Build Coastguard Worker Opcode |= Format << 21;
352*03ce13f7SAndroid Build Coastguard Worker
353*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
354*03ce13f7SAndroid Build Coastguard Worker }
355*03ce13f7SAndroid Build Coastguard Worker
emitCOP1MovRtFs(IValueT Opcode,const Operand * OpRt,const Operand * OpFs,const char * InsnName)356*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitCOP1MovRtFs(IValueT Opcode, const Operand *OpRt,
357*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFs,
358*03ce13f7SAndroid Build Coastguard Worker const char *InsnName) {
359*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeGPRegister(OpRt, "Rt", InsnName);
360*03ce13f7SAndroid Build Coastguard Worker const IValueT Fs = encodeFPRegister(OpFs, "Fs", InsnName);
361*03ce13f7SAndroid Build Coastguard Worker Opcode |= Fs << 11;
362*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
363*03ce13f7SAndroid Build Coastguard Worker
364*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
365*03ce13f7SAndroid Build Coastguard Worker }
366*03ce13f7SAndroid Build Coastguard Worker
abs_d(const Operand * OpFd,const Operand * OpFs)367*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::abs_d(const Operand *OpFd, const Operand *OpFs) {
368*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000005;
369*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "abs.d");
370*03ce13f7SAndroid Build Coastguard Worker }
371*03ce13f7SAndroid Build Coastguard Worker
abs_s(const Operand * OpFd,const Operand * OpFs)372*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::abs_s(const Operand *OpFd, const Operand *OpFs) {
373*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000005;
374*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "abs.s");
375*03ce13f7SAndroid Build Coastguard Worker }
376*03ce13f7SAndroid Build Coastguard Worker
addi(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)377*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::addi(const Operand *OpRt, const Operand *OpRs,
378*03ce13f7SAndroid Build Coastguard Worker const uint32_t Imm) {
379*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x20000000;
380*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addi");
381*03ce13f7SAndroid Build Coastguard Worker }
382*03ce13f7SAndroid Build Coastguard Worker
add_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)383*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::add_d(const Operand *OpFd, const Operand *OpFs,
384*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt) {
385*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000000;
386*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "add.d");
387*03ce13f7SAndroid Build Coastguard Worker }
388*03ce13f7SAndroid Build Coastguard Worker
add_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)389*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::add_s(const Operand *OpFd, const Operand *OpFs,
390*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt) {
391*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000000;
392*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "add.s");
393*03ce13f7SAndroid Build Coastguard Worker }
394*03ce13f7SAndroid Build Coastguard Worker
addiu(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)395*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs,
396*03ce13f7SAndroid Build Coastguard Worker const uint32_t Imm) {
397*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x24000000;
398*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "addiu");
399*03ce13f7SAndroid Build Coastguard Worker }
400*03ce13f7SAndroid Build Coastguard Worker
addiu(const Operand * OpRt,const Operand * OpRs,const Operand * OpImm,const RelocOp Reloc)401*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::addiu(const Operand *OpRt, const Operand *OpRs,
402*03ce13f7SAndroid Build Coastguard Worker const Operand *OpImm, const RelocOp Reloc) {
403*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x24000000;
404*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16Rel(Opcode, OpRt, OpRs, OpImm, Reloc, "addiu");
405*03ce13f7SAndroid Build Coastguard Worker }
406*03ce13f7SAndroid Build Coastguard Worker
addu(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)407*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::addu(const Operand *OpRd, const Operand *OpRs,
408*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt) {
409*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000021;
410*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "addu");
411*03ce13f7SAndroid Build Coastguard Worker }
412*03ce13f7SAndroid Build Coastguard Worker
and_(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)413*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::and_(const Operand *OpRd, const Operand *OpRs,
414*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt) {
415*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000024;
416*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "and");
417*03ce13f7SAndroid Build Coastguard Worker }
418*03ce13f7SAndroid Build Coastguard Worker
andi(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)419*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::andi(const Operand *OpRt, const Operand *OpRs,
420*03ce13f7SAndroid Build Coastguard Worker const uint32_t Imm) {
421*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x30000000;
422*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "andi");
423*03ce13f7SAndroid Build Coastguard Worker }
424*03ce13f7SAndroid Build Coastguard Worker
b(Label * TargetLabel)425*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::b(Label *TargetLabel) {
426*03ce13f7SAndroid Build Coastguard Worker static constexpr Operand *OpRsNone = nullptr;
427*03ce13f7SAndroid Build Coastguard Worker static constexpr Operand *OpRtNone = nullptr;
428*03ce13f7SAndroid Build Coastguard Worker if (TargetLabel->isBound()) {
429*03ce13f7SAndroid Build Coastguard Worker const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
430*03ce13f7SAndroid Build Coastguard Worker emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, Dest);
431*03ce13f7SAndroid Build Coastguard Worker return;
432*03ce13f7SAndroid Build Coastguard Worker }
433*03ce13f7SAndroid Build Coastguard Worker const IOffsetT Position = Buffer.size();
434*03ce13f7SAndroid Build Coastguard Worker IOffsetT PrevPosition = TargetLabel->getEncodedPosition();
435*03ce13f7SAndroid Build Coastguard Worker if (PrevPosition != 0)
436*03ce13f7SAndroid Build Coastguard Worker PrevPosition = Position - PrevPosition;
437*03ce13f7SAndroid Build Coastguard Worker emitBr(CondMIPS32::AL, OpRsNone, OpRtNone, PrevPosition);
438*03ce13f7SAndroid Build Coastguard Worker TargetLabel->linkTo(*this, Position);
439*03ce13f7SAndroid Build Coastguard Worker }
440*03ce13f7SAndroid Build Coastguard Worker
c_eq_d(const Operand * OpFs,const Operand * OpFt)441*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_eq_d(const Operand *OpFs, const Operand *OpFt) {
442*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000032;
443*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
444*03ce13f7SAndroid Build Coastguard Worker "c.eq.d");
445*03ce13f7SAndroid Build Coastguard Worker }
446*03ce13f7SAndroid Build Coastguard Worker
c_eq_s(const Operand * OpFs,const Operand * OpFt)447*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_eq_s(const Operand *OpFs, const Operand *OpFt) {
448*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000032;
449*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
450*03ce13f7SAndroid Build Coastguard Worker "c.eq.s");
451*03ce13f7SAndroid Build Coastguard Worker }
452*03ce13f7SAndroid Build Coastguard Worker
c_ole_d(const Operand * OpFs,const Operand * OpFt)453*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_ole_d(const Operand *OpFs, const Operand *OpFt) {
454*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000036;
455*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
456*03ce13f7SAndroid Build Coastguard Worker "c.ole.d");
457*03ce13f7SAndroid Build Coastguard Worker }
458*03ce13f7SAndroid Build Coastguard Worker
c_ole_s(const Operand * OpFs,const Operand * OpFt)459*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_ole_s(const Operand *OpFs, const Operand *OpFt) {
460*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000036;
461*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
462*03ce13f7SAndroid Build Coastguard Worker "c.ole.s");
463*03ce13f7SAndroid Build Coastguard Worker }
464*03ce13f7SAndroid Build Coastguard Worker
c_olt_d(const Operand * OpFs,const Operand * OpFt)465*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_olt_d(const Operand *OpFs, const Operand *OpFt) {
466*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000034;
467*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
468*03ce13f7SAndroid Build Coastguard Worker "c.olt.d");
469*03ce13f7SAndroid Build Coastguard Worker }
470*03ce13f7SAndroid Build Coastguard Worker
c_olt_s(const Operand * OpFs,const Operand * OpFt)471*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_olt_s(const Operand *OpFs, const Operand *OpFt) {
472*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000034;
473*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
474*03ce13f7SAndroid Build Coastguard Worker "c.olt.s");
475*03ce13f7SAndroid Build Coastguard Worker }
476*03ce13f7SAndroid Build Coastguard Worker
c_ueq_d(const Operand * OpFs,const Operand * OpFt)477*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_ueq_d(const Operand *OpFs, const Operand *OpFt) {
478*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000033;
479*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
480*03ce13f7SAndroid Build Coastguard Worker "c.ueq.d");
481*03ce13f7SAndroid Build Coastguard Worker }
482*03ce13f7SAndroid Build Coastguard Worker
c_ueq_s(const Operand * OpFs,const Operand * OpFt)483*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_ueq_s(const Operand *OpFs, const Operand *OpFt) {
484*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000033;
485*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
486*03ce13f7SAndroid Build Coastguard Worker "c.ueq.s");
487*03ce13f7SAndroid Build Coastguard Worker }
488*03ce13f7SAndroid Build Coastguard Worker
c_ule_d(const Operand * OpFs,const Operand * OpFt)489*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_ule_d(const Operand *OpFs, const Operand *OpFt) {
490*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000037;
491*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
492*03ce13f7SAndroid Build Coastguard Worker "c.ule.d");
493*03ce13f7SAndroid Build Coastguard Worker }
494*03ce13f7SAndroid Build Coastguard Worker
c_ule_s(const Operand * OpFs,const Operand * OpFt)495*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_ule_s(const Operand *OpFs, const Operand *OpFt) {
496*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000037;
497*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
498*03ce13f7SAndroid Build Coastguard Worker "c.ule.s");
499*03ce13f7SAndroid Build Coastguard Worker }
500*03ce13f7SAndroid Build Coastguard Worker
c_ult_d(const Operand * OpFs,const Operand * OpFt)501*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_ult_d(const Operand *OpFs, const Operand *OpFt) {
502*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000035;
503*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
504*03ce13f7SAndroid Build Coastguard Worker "c.ult.d");
505*03ce13f7SAndroid Build Coastguard Worker }
506*03ce13f7SAndroid Build Coastguard Worker
c_ult_s(const Operand * OpFs,const Operand * OpFt)507*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_ult_s(const Operand *OpFs, const Operand *OpFt) {
508*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000035;
509*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
510*03ce13f7SAndroid Build Coastguard Worker "c.ult.s");
511*03ce13f7SAndroid Build Coastguard Worker }
512*03ce13f7SAndroid Build Coastguard Worker
c_un_d(const Operand * OpFs,const Operand * OpFt)513*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_un_d(const Operand *OpFs, const Operand *OpFt) {
514*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000031;
515*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, DoublePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
516*03ce13f7SAndroid Build Coastguard Worker "c.un.d");
517*03ce13f7SAndroid Build Coastguard Worker }
518*03ce13f7SAndroid Build Coastguard Worker
c_un_s(const Operand * OpFs,const Operand * OpFt)519*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::c_un_s(const Operand *OpFs, const Operand *OpFt) {
520*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000031;
521*03ce13f7SAndroid Build Coastguard Worker emitCOP1Fcmp(Opcode, SinglePrecision, OpFs, OpFt, OperandMIPS32FCC::FCC0,
522*03ce13f7SAndroid Build Coastguard Worker "c.un.s");
523*03ce13f7SAndroid Build Coastguard Worker }
524*03ce13f7SAndroid Build Coastguard Worker
clz(const Operand * OpRd,const Operand * OpRs)525*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::clz(const Operand *OpRd, const Operand *OpRs) {
526*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0x70000020;
527*03ce13f7SAndroid Build Coastguard Worker const IValueT Rd = encodeGPRegister(OpRd, "Rd", "clz");
528*03ce13f7SAndroid Build Coastguard Worker const IValueT Rs = encodeGPRegister(OpRs, "Rs", "clz");
529*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rd << 11;
530*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rd << 16;
531*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
532*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
533*03ce13f7SAndroid Build Coastguard Worker }
534*03ce13f7SAndroid Build Coastguard Worker
cvt_d_l(const Operand * OpFd,const Operand * OpFs)535*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::cvt_d_l(const Operand *OpFd, const Operand *OpFs) {
536*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000021;
537*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "cvt.d.l");
538*03ce13f7SAndroid Build Coastguard Worker }
539*03ce13f7SAndroid Build Coastguard Worker
cvt_d_s(const Operand * OpFd,const Operand * OpFs)540*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::cvt_d_s(const Operand *OpFd, const Operand *OpFs) {
541*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000021;
542*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "cvt.d.s");
543*03ce13f7SAndroid Build Coastguard Worker }
544*03ce13f7SAndroid Build Coastguard Worker
cvt_d_w(const Operand * OpFd,const Operand * OpFs)545*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::cvt_d_w(const Operand *OpFd, const Operand *OpFs) {
546*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000021;
547*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "cvt.d.w");
548*03ce13f7SAndroid Build Coastguard Worker }
549*03ce13f7SAndroid Build Coastguard Worker
cvt_s_d(const Operand * OpFd,const Operand * OpFs)550*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::cvt_s_d(const Operand *OpFd, const Operand *OpFs) {
551*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000020;
552*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "cvt.s.d");
553*03ce13f7SAndroid Build Coastguard Worker }
554*03ce13f7SAndroid Build Coastguard Worker
cvt_s_l(const Operand * OpFd,const Operand * OpFs)555*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::cvt_s_l(const Operand *OpFd, const Operand *OpFs) {
556*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000020;
557*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "cvt.s.l");
558*03ce13f7SAndroid Build Coastguard Worker }
559*03ce13f7SAndroid Build Coastguard Worker
cvt_s_w(const Operand * OpFd,const Operand * OpFs)560*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::cvt_s_w(const Operand *OpFd, const Operand *OpFs) {
561*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000020;
562*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, Word, OpFd, OpFs, "cvt.s.w");
563*03ce13f7SAndroid Build Coastguard Worker }
564*03ce13f7SAndroid Build Coastguard Worker
div(const Operand * OpRs,const Operand * OpRt)565*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::div(const Operand *OpRs, const Operand *OpRt) {
566*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x0000001A;
567*03ce13f7SAndroid Build Coastguard Worker emitRsRt(Opcode, OpRs, OpRt, "div");
568*03ce13f7SAndroid Build Coastguard Worker }
569*03ce13f7SAndroid Build Coastguard Worker
div_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)570*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::div_d(const Operand *OpFd, const Operand *OpFs,
571*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt) {
572*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000003;
573*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "div.d");
574*03ce13f7SAndroid Build Coastguard Worker }
575*03ce13f7SAndroid Build Coastguard Worker
div_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)576*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::div_s(const Operand *OpFd, const Operand *OpFs,
577*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt) {
578*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000003;
579*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "div.s");
580*03ce13f7SAndroid Build Coastguard Worker }
581*03ce13f7SAndroid Build Coastguard Worker
divu(const Operand * OpRs,const Operand * OpRt)582*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::divu(const Operand *OpRs, const Operand *OpRt) {
583*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x0000001B;
584*03ce13f7SAndroid Build Coastguard Worker emitRsRt(Opcode, OpRs, OpRt, "divu");
585*03ce13f7SAndroid Build Coastguard Worker }
586*03ce13f7SAndroid Build Coastguard Worker
createMIPS32Fixup(const RelocOp Reloc,const Constant * RelOp)587*03ce13f7SAndroid Build Coastguard Worker MIPS32Fixup *AssemblerMIPS32::createMIPS32Fixup(const RelocOp Reloc,
588*03ce13f7SAndroid Build Coastguard Worker const Constant *RelOp) {
589*03ce13f7SAndroid Build Coastguard Worker MIPS32Fixup *Fixup = new (allocate<MIPS32Fixup>()) MIPS32Fixup();
590*03ce13f7SAndroid Build Coastguard Worker switch (Reloc) {
591*03ce13f7SAndroid Build Coastguard Worker case RelocOp::RO_Hi:
592*03ce13f7SAndroid Build Coastguard Worker Fixup->set_kind(llvm::ELF::R_MIPS_HI16);
593*03ce13f7SAndroid Build Coastguard Worker break;
594*03ce13f7SAndroid Build Coastguard Worker case RelocOp::RO_Lo:
595*03ce13f7SAndroid Build Coastguard Worker Fixup->set_kind(llvm::ELF::R_MIPS_LO16);
596*03ce13f7SAndroid Build Coastguard Worker break;
597*03ce13f7SAndroid Build Coastguard Worker case RelocOp::RO_Jal:
598*03ce13f7SAndroid Build Coastguard Worker Fixup->set_kind(llvm::ELF::R_MIPS_26);
599*03ce13f7SAndroid Build Coastguard Worker break;
600*03ce13f7SAndroid Build Coastguard Worker default:
601*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("Fixup: Invalid Reloc type");
602*03ce13f7SAndroid Build Coastguard Worker break;
603*03ce13f7SAndroid Build Coastguard Worker }
604*03ce13f7SAndroid Build Coastguard Worker Fixup->set_value(RelOp);
605*03ce13f7SAndroid Build Coastguard Worker Buffer.installFixup(Fixup);
606*03ce13f7SAndroid Build Coastguard Worker return Fixup;
607*03ce13f7SAndroid Build Coastguard Worker }
608*03ce13f7SAndroid Build Coastguard Worker
emit(GlobalContext * Ctx,const Assembler & Asm) const609*03ce13f7SAndroid Build Coastguard Worker size_t MIPS32Fixup::emit(GlobalContext *Ctx, const Assembler &Asm) const {
610*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::dump())
611*03ce13f7SAndroid Build Coastguard Worker return InstMIPS32::InstSize;
612*03ce13f7SAndroid Build Coastguard Worker Ostream &Str = Ctx->getStrEmit();
613*03ce13f7SAndroid Build Coastguard Worker IValueT Inst = Asm.load<IValueT>(position());
614*03ce13f7SAndroid Build Coastguard Worker const auto Symbol = symbol().toString();
615*03ce13f7SAndroid Build Coastguard Worker Str << "\t"
616*03ce13f7SAndroid Build Coastguard Worker << ".word " << llvm::format_hex(Inst, 8) << " # ";
617*03ce13f7SAndroid Build Coastguard Worker switch (kind()) {
618*03ce13f7SAndroid Build Coastguard Worker case llvm::ELF::R_MIPS_HI16:
619*03ce13f7SAndroid Build Coastguard Worker Str << "R_MIPS_HI16 ";
620*03ce13f7SAndroid Build Coastguard Worker break;
621*03ce13f7SAndroid Build Coastguard Worker case llvm::ELF::R_MIPS_LO16:
622*03ce13f7SAndroid Build Coastguard Worker Str << "R_MIPS_LO16 ";
623*03ce13f7SAndroid Build Coastguard Worker break;
624*03ce13f7SAndroid Build Coastguard Worker case llvm::ELF::R_MIPS_26:
625*03ce13f7SAndroid Build Coastguard Worker Str << "R_MIPS_26 ";
626*03ce13f7SAndroid Build Coastguard Worker break;
627*03ce13f7SAndroid Build Coastguard Worker default:
628*03ce13f7SAndroid Build Coastguard Worker Str << "Unknown ";
629*03ce13f7SAndroid Build Coastguard Worker break;
630*03ce13f7SAndroid Build Coastguard Worker }
631*03ce13f7SAndroid Build Coastguard Worker Str << Symbol << "\n";
632*03ce13f7SAndroid Build Coastguard Worker return InstMIPS32::InstSize;
633*03ce13f7SAndroid Build Coastguard Worker }
634*03ce13f7SAndroid Build Coastguard Worker
emitOffset(Assembler * Asm) const635*03ce13f7SAndroid Build Coastguard Worker void MIPS32Fixup::emitOffset(Assembler *Asm) const {
636*03ce13f7SAndroid Build Coastguard Worker const IValueT Inst = Asm->load<IValueT>(position());
637*03ce13f7SAndroid Build Coastguard Worker IValueT ImmMask = 0;
638*03ce13f7SAndroid Build Coastguard Worker const IValueT Imm = offset();
639*03ce13f7SAndroid Build Coastguard Worker if (kind() == llvm::ELF::R_MIPS_26) {
640*03ce13f7SAndroid Build Coastguard Worker ImmMask = 0x03FFFFFF;
641*03ce13f7SAndroid Build Coastguard Worker } else {
642*03ce13f7SAndroid Build Coastguard Worker ImmMask = 0x0000FFFF;
643*03ce13f7SAndroid Build Coastguard Worker }
644*03ce13f7SAndroid Build Coastguard Worker Asm->store(position(), (Inst & ~ImmMask) | (Imm & ImmMask));
645*03ce13f7SAndroid Build Coastguard Worker }
646*03ce13f7SAndroid Build Coastguard Worker
jal(const ConstantRelocatable * Target)647*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::jal(const ConstantRelocatable *Target) {
648*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0x0C000000;
649*03ce13f7SAndroid Build Coastguard Worker emitFixup(createMIPS32Fixup(RelocOp::RO_Jal, Target));
650*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
651*03ce13f7SAndroid Build Coastguard Worker nop();
652*03ce13f7SAndroid Build Coastguard Worker }
653*03ce13f7SAndroid Build Coastguard Worker
jalr(const Operand * OpRs,const Operand * OpRd)654*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::jalr(const Operand *OpRs, const Operand *OpRd) {
655*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0x00000009;
656*03ce13f7SAndroid Build Coastguard Worker const IValueT Rs = encodeGPRegister(OpRs, "Rs", "jalr");
657*03ce13f7SAndroid Build Coastguard Worker const IValueT Rd =
658*03ce13f7SAndroid Build Coastguard Worker (OpRd == nullptr) ? 31 : encodeGPRegister(OpRd, "Rd", "jalr");
659*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rd << 11;
660*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
661*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
662*03ce13f7SAndroid Build Coastguard Worker nop();
663*03ce13f7SAndroid Build Coastguard Worker }
664*03ce13f7SAndroid Build Coastguard Worker
lui(const Operand * OpRt,const Operand * OpImm,const RelocOp Reloc)665*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::lui(const Operand *OpRt, const Operand *OpImm,
666*03ce13f7SAndroid Build Coastguard Worker const RelocOp Reloc) {
667*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0x3C000000;
668*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeGPRegister(OpRt, "Rt", "lui");
669*03ce13f7SAndroid Build Coastguard Worker IValueT Imm16 = 0;
670*03ce13f7SAndroid Build Coastguard Worker
671*03ce13f7SAndroid Build Coastguard Worker if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpImm)) {
672*03ce13f7SAndroid Build Coastguard Worker emitFixup(createMIPS32Fixup(Reloc, OpRel));
673*03ce13f7SAndroid Build Coastguard Worker } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpImm)) {
674*03ce13f7SAndroid Build Coastguard Worker Imm16 = C32->getValue();
675*03ce13f7SAndroid Build Coastguard Worker } else {
676*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("lui: Invalid 2nd operand");
677*03ce13f7SAndroid Build Coastguard Worker }
678*03ce13f7SAndroid Build Coastguard Worker
679*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
680*03ce13f7SAndroid Build Coastguard Worker Opcode |= Imm16;
681*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
682*03ce13f7SAndroid Build Coastguard Worker }
683*03ce13f7SAndroid Build Coastguard Worker
ldc1(const Operand * OpRt,const Operand * OpBase,const Operand * OpOff,const RelocOp Reloc)684*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::ldc1(const Operand *OpRt, const Operand *OpBase,
685*03ce13f7SAndroid Build Coastguard Worker const Operand *OpOff, const RelocOp Reloc) {
686*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0xD4000000;
687*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeFPRegister(OpRt, "Ft", "ldc1");
688*03ce13f7SAndroid Build Coastguard Worker const IValueT Base = encodeGPRegister(OpBase, "Base", "ldc1");
689*03ce13f7SAndroid Build Coastguard Worker IValueT Imm16 = 0;
690*03ce13f7SAndroid Build Coastguard Worker
691*03ce13f7SAndroid Build Coastguard Worker if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
692*03ce13f7SAndroid Build Coastguard Worker emitFixup(createMIPS32Fixup(Reloc, OpRel));
693*03ce13f7SAndroid Build Coastguard Worker } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
694*03ce13f7SAndroid Build Coastguard Worker Imm16 = C32->getValue();
695*03ce13f7SAndroid Build Coastguard Worker } else {
696*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("ldc1: Invalid 2nd operand");
697*03ce13f7SAndroid Build Coastguard Worker }
698*03ce13f7SAndroid Build Coastguard Worker
699*03ce13f7SAndroid Build Coastguard Worker Opcode |= Base << 21;
700*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
701*03ce13f7SAndroid Build Coastguard Worker Opcode |= Imm16;
702*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
703*03ce13f7SAndroid Build Coastguard Worker }
704*03ce13f7SAndroid Build Coastguard Worker
ll(const Operand * OpRt,const Operand * OpBase,const uint32_t Offset)705*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::ll(const Operand *OpRt, const Operand *OpBase,
706*03ce13f7SAndroid Build Coastguard Worker const uint32_t Offset) {
707*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0xC0000000;
708*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "ll");
709*03ce13f7SAndroid Build Coastguard Worker }
710*03ce13f7SAndroid Build Coastguard Worker
lw(const Operand * OpRt,const Operand * OpBase,const uint32_t Offset)711*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::lw(const Operand *OpRt, const Operand *OpBase,
712*03ce13f7SAndroid Build Coastguard Worker const uint32_t Offset) {
713*03ce13f7SAndroid Build Coastguard Worker switch (OpRt->getType()) {
714*03ce13f7SAndroid Build Coastguard Worker case IceType_i1:
715*03ce13f7SAndroid Build Coastguard Worker case IceType_i8: {
716*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x80000000;
717*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lb");
718*03ce13f7SAndroid Build Coastguard Worker break;
719*03ce13f7SAndroid Build Coastguard Worker }
720*03ce13f7SAndroid Build Coastguard Worker case IceType_i16: {
721*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x84000000;
722*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lh");
723*03ce13f7SAndroid Build Coastguard Worker break;
724*03ce13f7SAndroid Build Coastguard Worker }
725*03ce13f7SAndroid Build Coastguard Worker case IceType_i32: {
726*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x8C000000;
727*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "lw");
728*03ce13f7SAndroid Build Coastguard Worker break;
729*03ce13f7SAndroid Build Coastguard Worker }
730*03ce13f7SAndroid Build Coastguard Worker case IceType_f32: {
731*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0xC4000000;
732*03ce13f7SAndroid Build Coastguard Worker emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "lwc1");
733*03ce13f7SAndroid Build Coastguard Worker break;
734*03ce13f7SAndroid Build Coastguard Worker }
735*03ce13f7SAndroid Build Coastguard Worker case IceType_f64: {
736*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0xD4000000;
737*03ce13f7SAndroid Build Coastguard Worker emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "ldc1");
738*03ce13f7SAndroid Build Coastguard Worker break;
739*03ce13f7SAndroid Build Coastguard Worker }
740*03ce13f7SAndroid Build Coastguard Worker default: {
741*03ce13f7SAndroid Build Coastguard Worker UnimplementedError(getFlags());
742*03ce13f7SAndroid Build Coastguard Worker }
743*03ce13f7SAndroid Build Coastguard Worker }
744*03ce13f7SAndroid Build Coastguard Worker }
745*03ce13f7SAndroid Build Coastguard Worker
lwc1(const Operand * OpRt,const Operand * OpBase,const Operand * OpOff,const RelocOp Reloc)746*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::lwc1(const Operand *OpRt, const Operand *OpBase,
747*03ce13f7SAndroid Build Coastguard Worker const Operand *OpOff, const RelocOp Reloc) {
748*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0xC4000000;
749*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeFPRegister(OpRt, "Ft", "lwc1");
750*03ce13f7SAndroid Build Coastguard Worker const IValueT Base = encodeGPRegister(OpBase, "Base", "lwc1");
751*03ce13f7SAndroid Build Coastguard Worker IValueT Imm16 = 0;
752*03ce13f7SAndroid Build Coastguard Worker
753*03ce13f7SAndroid Build Coastguard Worker if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
754*03ce13f7SAndroid Build Coastguard Worker emitFixup(createMIPS32Fixup(Reloc, OpRel));
755*03ce13f7SAndroid Build Coastguard Worker } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
756*03ce13f7SAndroid Build Coastguard Worker Imm16 = C32->getValue();
757*03ce13f7SAndroid Build Coastguard Worker } else {
758*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("lwc1: Invalid 2nd operand");
759*03ce13f7SAndroid Build Coastguard Worker }
760*03ce13f7SAndroid Build Coastguard Worker
761*03ce13f7SAndroid Build Coastguard Worker Opcode |= Base << 21;
762*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
763*03ce13f7SAndroid Build Coastguard Worker Opcode |= Imm16;
764*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
765*03ce13f7SAndroid Build Coastguard Worker }
766*03ce13f7SAndroid Build Coastguard Worker
mfc1(const Operand * OpRt,const Operand * OpFs)767*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::mfc1(const Operand *OpRt, const Operand *OpFs) {
768*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000000;
769*03ce13f7SAndroid Build Coastguard Worker emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mfc1");
770*03ce13f7SAndroid Build Coastguard Worker }
771*03ce13f7SAndroid Build Coastguard Worker
mfhi(const Operand * OpRd)772*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::mfhi(const Operand *OpRd) {
773*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0x000000010;
774*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", "mfhi");
775*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rd << 11;
776*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
777*03ce13f7SAndroid Build Coastguard Worker }
778*03ce13f7SAndroid Build Coastguard Worker
mflo(const Operand * OpRd)779*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::mflo(const Operand *OpRd) {
780*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0x000000012;
781*03ce13f7SAndroid Build Coastguard Worker IValueT Rd = encodeGPRegister(OpRd, "Rd", "mflo");
782*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rd << 11;
783*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
784*03ce13f7SAndroid Build Coastguard Worker }
785*03ce13f7SAndroid Build Coastguard Worker
mov_d(const Operand * OpFd,const Operand * OpFs)786*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::mov_d(const Operand *OpFd, const Operand *OpFs) {
787*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000006;
788*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "mov.d");
789*03ce13f7SAndroid Build Coastguard Worker }
790*03ce13f7SAndroid Build Coastguard Worker
mov_s(const Operand * OpFd,const Operand * OpFs)791*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::mov_s(const Operand *OpFd, const Operand *OpFs) {
792*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000006;
793*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "mov.s");
794*03ce13f7SAndroid Build Coastguard Worker }
795*03ce13f7SAndroid Build Coastguard Worker
move(const Operand * OpRd,const Operand * OpRs)796*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::move(const Operand *OpRd, const Operand *OpRs) {
797*03ce13f7SAndroid Build Coastguard Worker
798*03ce13f7SAndroid Build Coastguard Worker const Type DstType = OpRd->getType();
799*03ce13f7SAndroid Build Coastguard Worker const Type SrcType = OpRs->getType();
800*03ce13f7SAndroid Build Coastguard Worker
801*03ce13f7SAndroid Build Coastguard Worker if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
802*03ce13f7SAndroid Build Coastguard Worker (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
803*03ce13f7SAndroid Build Coastguard Worker if (isScalarFloatingType(DstType)) {
804*03ce13f7SAndroid Build Coastguard Worker mtc1(OpRs, OpRd);
805*03ce13f7SAndroid Build Coastguard Worker } else {
806*03ce13f7SAndroid Build Coastguard Worker mfc1(OpRd, OpRs);
807*03ce13f7SAndroid Build Coastguard Worker }
808*03ce13f7SAndroid Build Coastguard Worker } else {
809*03ce13f7SAndroid Build Coastguard Worker switch (DstType) {
810*03ce13f7SAndroid Build Coastguard Worker case IceType_f32:
811*03ce13f7SAndroid Build Coastguard Worker mov_s(OpRd, OpRs);
812*03ce13f7SAndroid Build Coastguard Worker break;
813*03ce13f7SAndroid Build Coastguard Worker case IceType_f64:
814*03ce13f7SAndroid Build Coastguard Worker mov_d(OpRd, OpRs);
815*03ce13f7SAndroid Build Coastguard Worker break;
816*03ce13f7SAndroid Build Coastguard Worker case IceType_i1:
817*03ce13f7SAndroid Build Coastguard Worker case IceType_i8:
818*03ce13f7SAndroid Build Coastguard Worker case IceType_i16:
819*03ce13f7SAndroid Build Coastguard Worker case IceType_i32: {
820*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0x00000021;
821*03ce13f7SAndroid Build Coastguard Worker const IValueT Rd = encodeGPRegister(OpRd, "Rd", "pseudo-move");
822*03ce13f7SAndroid Build Coastguard Worker const IValueT Rs = encodeGPRegister(OpRs, "Rs", "pseudo-move");
823*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = 0; // $0
824*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
825*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
826*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rd << 11;
827*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
828*03ce13f7SAndroid Build Coastguard Worker break;
829*03ce13f7SAndroid Build Coastguard Worker }
830*03ce13f7SAndroid Build Coastguard Worker default: {
831*03ce13f7SAndroid Build Coastguard Worker UnimplementedError(getFlags());
832*03ce13f7SAndroid Build Coastguard Worker }
833*03ce13f7SAndroid Build Coastguard Worker }
834*03ce13f7SAndroid Build Coastguard Worker }
835*03ce13f7SAndroid Build Coastguard Worker }
836*03ce13f7SAndroid Build Coastguard Worker
movf(const Operand * OpRd,const Operand * OpRs,const Operand * OpCc)837*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::movf(const Operand *OpRd, const Operand *OpRs,
838*03ce13f7SAndroid Build Coastguard Worker const Operand *OpCc) {
839*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0x00000001;
840*03ce13f7SAndroid Build Coastguard Worker const IValueT Rd = encodeGPRegister(OpRd, "Rd", "movf");
841*03ce13f7SAndroid Build Coastguard Worker const IValueT Rs = encodeGPRegister(OpRs, "Rs", "movf");
842*03ce13f7SAndroid Build Coastguard Worker OperandMIPS32FCC::FCC Cc = OperandMIPS32FCC::FCC0;
843*03ce13f7SAndroid Build Coastguard Worker if (const auto *OpFCC = llvm::dyn_cast<OperandMIPS32FCC>(OpCc)) {
844*03ce13f7SAndroid Build Coastguard Worker Cc = OpFCC->getFCC();
845*03ce13f7SAndroid Build Coastguard Worker }
846*03ce13f7SAndroid Build Coastguard Worker const IValueT InstEncodingFalse = 0;
847*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rd << 11;
848*03ce13f7SAndroid Build Coastguard Worker Opcode |= InstEncodingFalse << 16;
849*03ce13f7SAndroid Build Coastguard Worker Opcode |= Cc << 18;
850*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
851*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
852*03ce13f7SAndroid Build Coastguard Worker }
853*03ce13f7SAndroid Build Coastguard Worker
movn(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)854*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::movn(const Operand *OpRd, const Operand *OpRs,
855*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt) {
856*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x0000000B;
857*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "movn");
858*03ce13f7SAndroid Build Coastguard Worker }
859*03ce13f7SAndroid Build Coastguard Worker
movn_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)860*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::movn_d(const Operand *OpFd, const Operand *OpFs,
861*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt) {
862*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000013;
863*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtRtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "movn.d");
864*03ce13f7SAndroid Build Coastguard Worker }
865*03ce13f7SAndroid Build Coastguard Worker
movn_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)866*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::movn_s(const Operand *OpFd, const Operand *OpFs,
867*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt) {
868*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000013;
869*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtRtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movn.s");
870*03ce13f7SAndroid Build Coastguard Worker }
871*03ce13f7SAndroid Build Coastguard Worker
movt(const Operand * OpRd,const Operand * OpRs,const Operand * OpCc)872*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::movt(const Operand *OpRd, const Operand *OpRs,
873*03ce13f7SAndroid Build Coastguard Worker const Operand *OpCc) {
874*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0x00000001;
875*03ce13f7SAndroid Build Coastguard Worker const IValueT Rd = encodeGPRegister(OpRd, "Rd", "movt");
876*03ce13f7SAndroid Build Coastguard Worker const IValueT Rs = encodeGPRegister(OpRs, "Rs", "movt");
877*03ce13f7SAndroid Build Coastguard Worker OperandMIPS32FCC::FCC Cc = OperandMIPS32FCC::FCC0;
878*03ce13f7SAndroid Build Coastguard Worker if (const auto *OpFCC = llvm::dyn_cast<OperandMIPS32FCC>(OpCc)) {
879*03ce13f7SAndroid Build Coastguard Worker Cc = OpFCC->getFCC();
880*03ce13f7SAndroid Build Coastguard Worker }
881*03ce13f7SAndroid Build Coastguard Worker const IValueT InstEncodingTrue = 1;
882*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rd << 11;
883*03ce13f7SAndroid Build Coastguard Worker Opcode |= InstEncodingTrue << 16;
884*03ce13f7SAndroid Build Coastguard Worker Opcode |= Cc << 18;
885*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
886*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
887*03ce13f7SAndroid Build Coastguard Worker }
888*03ce13f7SAndroid Build Coastguard Worker
movz_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)889*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::movz_d(const Operand *OpFd, const Operand *OpFs,
890*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt) {
891*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000012;
892*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "movz.d");
893*03ce13f7SAndroid Build Coastguard Worker }
894*03ce13f7SAndroid Build Coastguard Worker
movz(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)895*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::movz(const Operand *OpRd, const Operand *OpRs,
896*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt) {
897*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x0000000A;
898*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "movz");
899*03ce13f7SAndroid Build Coastguard Worker }
900*03ce13f7SAndroid Build Coastguard Worker
movz_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)901*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::movz_s(const Operand *OpFd, const Operand *OpFs,
902*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt) {
903*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000012;
904*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "movz.s");
905*03ce13f7SAndroid Build Coastguard Worker }
906*03ce13f7SAndroid Build Coastguard Worker
mtc1(const Operand * OpRt,const Operand * OpFs)907*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::mtc1(const Operand *OpRt, const Operand *OpFs) {
908*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44800000;
909*03ce13f7SAndroid Build Coastguard Worker emitCOP1MovRtFs(Opcode, OpRt, OpFs, "mtc1");
910*03ce13f7SAndroid Build Coastguard Worker }
911*03ce13f7SAndroid Build Coastguard Worker
mthi(const Operand * OpRs)912*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::mthi(const Operand *OpRs) {
913*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0x000000011;
914*03ce13f7SAndroid Build Coastguard Worker IValueT Rs = encodeGPRegister(OpRs, "Rs", "mthi");
915*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
916*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
917*03ce13f7SAndroid Build Coastguard Worker }
918*03ce13f7SAndroid Build Coastguard Worker
mtlo(const Operand * OpRs)919*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::mtlo(const Operand *OpRs) {
920*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0x000000013;
921*03ce13f7SAndroid Build Coastguard Worker IValueT Rs = encodeGPRegister(OpRs, "Rs", "mtlo");
922*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
923*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
924*03ce13f7SAndroid Build Coastguard Worker }
925*03ce13f7SAndroid Build Coastguard Worker
mul(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)926*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::mul(const Operand *OpRd, const Operand *OpRs,
927*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt) {
928*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x70000002;
929*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "mul");
930*03ce13f7SAndroid Build Coastguard Worker }
931*03ce13f7SAndroid Build Coastguard Worker
mul_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)932*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::mul_d(const Operand *OpFd, const Operand *OpFs,
933*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt) {
934*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000002;
935*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "mul.d");
936*03ce13f7SAndroid Build Coastguard Worker }
937*03ce13f7SAndroid Build Coastguard Worker
mul_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)938*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::mul_s(const Operand *OpFd, const Operand *OpFs,
939*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt) {
940*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000002;
941*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "mul.s");
942*03ce13f7SAndroid Build Coastguard Worker }
943*03ce13f7SAndroid Build Coastguard Worker
mult(const Operand * OpRs,const Operand * OpRt)944*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::mult(const Operand *OpRs, const Operand *OpRt) {
945*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000018;
946*03ce13f7SAndroid Build Coastguard Worker emitRsRt(Opcode, OpRs, OpRt, "mult");
947*03ce13f7SAndroid Build Coastguard Worker }
948*03ce13f7SAndroid Build Coastguard Worker
multu(const Operand * OpRs,const Operand * OpRt)949*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::multu(const Operand *OpRs, const Operand *OpRt) {
950*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000019;
951*03ce13f7SAndroid Build Coastguard Worker emitRsRt(Opcode, OpRs, OpRt, "multu");
952*03ce13f7SAndroid Build Coastguard Worker }
953*03ce13f7SAndroid Build Coastguard Worker
nor(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)954*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::nor(const Operand *OpRd, const Operand *OpRs,
955*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt) {
956*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000027;
957*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "nor");
958*03ce13f7SAndroid Build Coastguard Worker }
959*03ce13f7SAndroid Build Coastguard Worker
or_(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)960*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::or_(const Operand *OpRd, const Operand *OpRs,
961*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt) {
962*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000025;
963*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "or");
964*03ce13f7SAndroid Build Coastguard Worker }
965*03ce13f7SAndroid Build Coastguard Worker
ori(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)966*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::ori(const Operand *OpRt, const Operand *OpRs,
967*03ce13f7SAndroid Build Coastguard Worker const uint32_t Imm) {
968*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x34000000;
969*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "ori");
970*03ce13f7SAndroid Build Coastguard Worker }
971*03ce13f7SAndroid Build Coastguard Worker
ret(void)972*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::ret(void) {
973*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x03E00008; // JR $31
974*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
975*03ce13f7SAndroid Build Coastguard Worker nop(); // delay slot
976*03ce13f7SAndroid Build Coastguard Worker }
977*03ce13f7SAndroid Build Coastguard Worker
sc(const Operand * OpRt,const Operand * OpBase,const uint32_t Offset)978*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sc(const Operand *OpRt, const Operand *OpBase,
979*03ce13f7SAndroid Build Coastguard Worker const uint32_t Offset) {
980*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0xE0000000;
981*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sc");
982*03ce13f7SAndroid Build Coastguard Worker }
983*03ce13f7SAndroid Build Coastguard Worker
sll(const Operand * OpRd,const Operand * OpRt,const uint32_t Sa)984*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sll(const Operand *OpRd, const Operand *OpRt,
985*03ce13f7SAndroid Build Coastguard Worker const uint32_t Sa) {
986*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000000;
987*03ce13f7SAndroid Build Coastguard Worker emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sll");
988*03ce13f7SAndroid Build Coastguard Worker }
989*03ce13f7SAndroid Build Coastguard Worker
sllv(const Operand * OpRd,const Operand * OpRt,const Operand * OpRs)990*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sllv(const Operand *OpRd, const Operand *OpRt,
991*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRs) {
992*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000004;
993*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sllv");
994*03ce13f7SAndroid Build Coastguard Worker }
995*03ce13f7SAndroid Build Coastguard Worker
slt(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)996*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::slt(const Operand *OpRd, const Operand *OpRs,
997*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt) {
998*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x0000002A;
999*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "slt");
1000*03ce13f7SAndroid Build Coastguard Worker }
1001*03ce13f7SAndroid Build Coastguard Worker
slti(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)1002*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::slti(const Operand *OpRt, const Operand *OpRs,
1003*03ce13f7SAndroid Build Coastguard Worker const uint32_t Imm) {
1004*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x28000000;
1005*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "slti");
1006*03ce13f7SAndroid Build Coastguard Worker }
1007*03ce13f7SAndroid Build Coastguard Worker
sltu(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)1008*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sltu(const Operand *OpRd, const Operand *OpRs,
1009*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt) {
1010*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x0000002B;
1011*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "sltu");
1012*03ce13f7SAndroid Build Coastguard Worker }
1013*03ce13f7SAndroid Build Coastguard Worker
sltiu(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)1014*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sltiu(const Operand *OpRt, const Operand *OpRs,
1015*03ce13f7SAndroid Build Coastguard Worker const uint32_t Imm) {
1016*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x2c000000;
1017*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "sltiu");
1018*03ce13f7SAndroid Build Coastguard Worker }
1019*03ce13f7SAndroid Build Coastguard Worker
sqrt_d(const Operand * OpFd,const Operand * OpFs)1020*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sqrt_d(const Operand *OpFd, const Operand *OpFs) {
1021*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000004;
1022*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "sqrt.d");
1023*03ce13f7SAndroid Build Coastguard Worker }
1024*03ce13f7SAndroid Build Coastguard Worker
sqrt_s(const Operand * OpFd,const Operand * OpFs)1025*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sqrt_s(const Operand *OpFd, const Operand *OpFs) {
1026*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000004;
1027*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "sqrt.s");
1028*03ce13f7SAndroid Build Coastguard Worker }
1029*03ce13f7SAndroid Build Coastguard Worker
sra(const Operand * OpRd,const Operand * OpRt,const uint32_t Sa)1030*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sra(const Operand *OpRd, const Operand *OpRt,
1031*03ce13f7SAndroid Build Coastguard Worker const uint32_t Sa) {
1032*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000003;
1033*03ce13f7SAndroid Build Coastguard Worker emitRdRtSa(Opcode, OpRd, OpRt, Sa, "sra");
1034*03ce13f7SAndroid Build Coastguard Worker }
1035*03ce13f7SAndroid Build Coastguard Worker
srl(const Operand * OpRd,const Operand * OpRt,const uint32_t Sa)1036*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::srl(const Operand *OpRd, const Operand *OpRt,
1037*03ce13f7SAndroid Build Coastguard Worker const uint32_t Sa) {
1038*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000002;
1039*03ce13f7SAndroid Build Coastguard Worker emitRdRtSa(Opcode, OpRd, OpRt, Sa, "srl");
1040*03ce13f7SAndroid Build Coastguard Worker }
1041*03ce13f7SAndroid Build Coastguard Worker
srav(const Operand * OpRd,const Operand * OpRt,const Operand * OpRs)1042*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::srav(const Operand *OpRd, const Operand *OpRt,
1043*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRs) {
1044*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000007;
1045*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "srav");
1046*03ce13f7SAndroid Build Coastguard Worker }
1047*03ce13f7SAndroid Build Coastguard Worker
srlv(const Operand * OpRd,const Operand * OpRt,const Operand * OpRs)1048*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::srlv(const Operand *OpRd, const Operand *OpRt,
1049*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRs) {
1050*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000006;
1051*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "srlv");
1052*03ce13f7SAndroid Build Coastguard Worker }
1053*03ce13f7SAndroid Build Coastguard Worker
sub_d(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)1054*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sub_d(const Operand *OpFd, const Operand *OpFs,
1055*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt) {
1056*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000001;
1057*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFtFsFd(Opcode, DoublePrecision, OpFd, OpFs, OpFt, "sub.d");
1058*03ce13f7SAndroid Build Coastguard Worker }
1059*03ce13f7SAndroid Build Coastguard Worker
sub_s(const Operand * OpFd,const Operand * OpFs,const Operand * OpFt)1060*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sub_s(const Operand *OpFd, const Operand *OpFs,
1061*03ce13f7SAndroid Build Coastguard Worker const Operand *OpFt) {
1062*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x44000001;
1063*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFtFsFd(Opcode, SinglePrecision, OpFd, OpFs, OpFt, "sub.s");
1064*03ce13f7SAndroid Build Coastguard Worker }
1065*03ce13f7SAndroid Build Coastguard Worker
subu(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)1066*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::subu(const Operand *OpRd, const Operand *OpRs,
1067*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt) {
1068*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000023;
1069*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "subu");
1070*03ce13f7SAndroid Build Coastguard Worker }
1071*03ce13f7SAndroid Build Coastguard Worker
sdc1(const Operand * OpRt,const Operand * OpBase,const Operand * OpOff,const RelocOp Reloc)1072*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sdc1(const Operand *OpRt, const Operand *OpBase,
1073*03ce13f7SAndroid Build Coastguard Worker const Operand *OpOff, const RelocOp Reloc) {
1074*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0xF4000000;
1075*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeFPRegister(OpRt, "Ft", "sdc1");
1076*03ce13f7SAndroid Build Coastguard Worker const IValueT Base = encodeGPRegister(OpBase, "Base", "sdc1");
1077*03ce13f7SAndroid Build Coastguard Worker IValueT Imm16 = 0;
1078*03ce13f7SAndroid Build Coastguard Worker
1079*03ce13f7SAndroid Build Coastguard Worker if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
1080*03ce13f7SAndroid Build Coastguard Worker emitFixup(createMIPS32Fixup(Reloc, OpRel));
1081*03ce13f7SAndroid Build Coastguard Worker } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
1082*03ce13f7SAndroid Build Coastguard Worker Imm16 = C32->getValue();
1083*03ce13f7SAndroid Build Coastguard Worker } else {
1084*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("sdc1: Invalid 2nd operand");
1085*03ce13f7SAndroid Build Coastguard Worker }
1086*03ce13f7SAndroid Build Coastguard Worker
1087*03ce13f7SAndroid Build Coastguard Worker Opcode |= Base << 21;
1088*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
1089*03ce13f7SAndroid Build Coastguard Worker Opcode |= Imm16;
1090*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
1091*03ce13f7SAndroid Build Coastguard Worker }
1092*03ce13f7SAndroid Build Coastguard Worker
sw(const Operand * OpRt,const Operand * OpBase,const uint32_t Offset)1093*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sw(const Operand *OpRt, const Operand *OpBase,
1094*03ce13f7SAndroid Build Coastguard Worker const uint32_t Offset) {
1095*03ce13f7SAndroid Build Coastguard Worker switch (OpRt->getType()) {
1096*03ce13f7SAndroid Build Coastguard Worker case IceType_i1:
1097*03ce13f7SAndroid Build Coastguard Worker case IceType_i8: {
1098*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0xA0000000;
1099*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sb");
1100*03ce13f7SAndroid Build Coastguard Worker break;
1101*03ce13f7SAndroid Build Coastguard Worker }
1102*03ce13f7SAndroid Build Coastguard Worker case IceType_i16: {
1103*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0xA4000000;
1104*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sh");
1105*03ce13f7SAndroid Build Coastguard Worker break;
1106*03ce13f7SAndroid Build Coastguard Worker }
1107*03ce13f7SAndroid Build Coastguard Worker case IceType_i32: {
1108*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0xAC000000;
1109*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpBase, Offset, "sw");
1110*03ce13f7SAndroid Build Coastguard Worker break;
1111*03ce13f7SAndroid Build Coastguard Worker }
1112*03ce13f7SAndroid Build Coastguard Worker case IceType_f32: {
1113*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0xE4000000;
1114*03ce13f7SAndroid Build Coastguard Worker emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "swc1");
1115*03ce13f7SAndroid Build Coastguard Worker break;
1116*03ce13f7SAndroid Build Coastguard Worker }
1117*03ce13f7SAndroid Build Coastguard Worker case IceType_f64: {
1118*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0xF4000000;
1119*03ce13f7SAndroid Build Coastguard Worker emitFtRsImm16(Opcode, OpRt, OpBase, Offset, "sdc1");
1120*03ce13f7SAndroid Build Coastguard Worker break;
1121*03ce13f7SAndroid Build Coastguard Worker }
1122*03ce13f7SAndroid Build Coastguard Worker default: {
1123*03ce13f7SAndroid Build Coastguard Worker UnimplementedError(getFlags());
1124*03ce13f7SAndroid Build Coastguard Worker }
1125*03ce13f7SAndroid Build Coastguard Worker }
1126*03ce13f7SAndroid Build Coastguard Worker }
1127*03ce13f7SAndroid Build Coastguard Worker
swc1(const Operand * OpRt,const Operand * OpBase,const Operand * OpOff,const RelocOp Reloc)1128*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::swc1(const Operand *OpRt, const Operand *OpBase,
1129*03ce13f7SAndroid Build Coastguard Worker const Operand *OpOff, const RelocOp Reloc) {
1130*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0xE4000000;
1131*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeFPRegister(OpRt, "Ft", "swc1");
1132*03ce13f7SAndroid Build Coastguard Worker const IValueT Base = encodeGPRegister(OpBase, "Base", "swc1");
1133*03ce13f7SAndroid Build Coastguard Worker IValueT Imm16 = 0;
1134*03ce13f7SAndroid Build Coastguard Worker
1135*03ce13f7SAndroid Build Coastguard Worker if (const auto *OpRel = llvm::dyn_cast<ConstantRelocatable>(OpOff)) {
1136*03ce13f7SAndroid Build Coastguard Worker emitFixup(createMIPS32Fixup(Reloc, OpRel));
1137*03ce13f7SAndroid Build Coastguard Worker } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(OpOff)) {
1138*03ce13f7SAndroid Build Coastguard Worker Imm16 = C32->getValue();
1139*03ce13f7SAndroid Build Coastguard Worker } else {
1140*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("swc1: Invalid 2nd operand");
1141*03ce13f7SAndroid Build Coastguard Worker }
1142*03ce13f7SAndroid Build Coastguard Worker
1143*03ce13f7SAndroid Build Coastguard Worker Opcode |= Base << 21;
1144*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
1145*03ce13f7SAndroid Build Coastguard Worker Opcode |= Imm16;
1146*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
1147*03ce13f7SAndroid Build Coastguard Worker }
1148*03ce13f7SAndroid Build Coastguard Worker
sync()1149*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::sync() {
1150*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x0000000f;
1151*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
1152*03ce13f7SAndroid Build Coastguard Worker }
1153*03ce13f7SAndroid Build Coastguard Worker
teq(const Operand * OpRs,const Operand * OpRt,const uint32_t TrapCode)1154*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::teq(const Operand *OpRs, const Operand *OpRt,
1155*03ce13f7SAndroid Build Coastguard Worker const uint32_t TrapCode) {
1156*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0x00000034;
1157*03ce13f7SAndroid Build Coastguard Worker const IValueT Rs = encodeGPRegister(OpRs, "Rs", "teq");
1158*03ce13f7SAndroid Build Coastguard Worker const IValueT Rt = encodeGPRegister(OpRt, "Rt", "teq");
1159*03ce13f7SAndroid Build Coastguard Worker Opcode |= (TrapCode & 0xFFFFF) << 6;
1160*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
1161*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
1162*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
1163*03ce13f7SAndroid Build Coastguard Worker }
1164*03ce13f7SAndroid Build Coastguard Worker
trunc_l_d(const Operand * OpFd,const Operand * OpFs)1165*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::trunc_l_d(const Operand *OpFd, const Operand *OpFs) {
1166*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x4400000D;
1167*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.d");
1168*03ce13f7SAndroid Build Coastguard Worker }
1169*03ce13f7SAndroid Build Coastguard Worker
trunc_l_s(const Operand * OpFd,const Operand * OpFs)1170*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::trunc_l_s(const Operand *OpFd, const Operand *OpFs) {
1171*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x4400000D;
1172*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, Long, OpFd, OpFs, "trunc.l.s");
1173*03ce13f7SAndroid Build Coastguard Worker }
1174*03ce13f7SAndroid Build Coastguard Worker
trunc_w_d(const Operand * OpFd,const Operand * OpFs)1175*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::trunc_w_d(const Operand *OpFd, const Operand *OpFs) {
1176*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x4400000D;
1177*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, DoublePrecision, OpFd, OpFs, "trunc.w.d");
1178*03ce13f7SAndroid Build Coastguard Worker }
1179*03ce13f7SAndroid Build Coastguard Worker
trunc_w_s(const Operand * OpFd,const Operand * OpFs)1180*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::trunc_w_s(const Operand *OpFd, const Operand *OpFs) {
1181*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x4400000D;
1182*03ce13f7SAndroid Build Coastguard Worker emitCOP1FmtFsFd(Opcode, SinglePrecision, OpFd, OpFs, "trunc.w.s");
1183*03ce13f7SAndroid Build Coastguard Worker }
1184*03ce13f7SAndroid Build Coastguard Worker
xor_(const Operand * OpRd,const Operand * OpRs,const Operand * OpRt)1185*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::xor_(const Operand *OpRd, const Operand *OpRs,
1186*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt) {
1187*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x00000026;
1188*03ce13f7SAndroid Build Coastguard Worker emitRdRsRt(Opcode, OpRd, OpRs, OpRt, "xor");
1189*03ce13f7SAndroid Build Coastguard Worker }
1190*03ce13f7SAndroid Build Coastguard Worker
xori(const Operand * OpRt,const Operand * OpRs,const uint32_t Imm)1191*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::xori(const Operand *OpRt, const Operand *OpRs,
1192*03ce13f7SAndroid Build Coastguard Worker const uint32_t Imm) {
1193*03ce13f7SAndroid Build Coastguard Worker static constexpr IValueT Opcode = 0x38000000;
1194*03ce13f7SAndroid Build Coastguard Worker emitRtRsImm16(Opcode, OpRt, OpRs, Imm, "xori");
1195*03ce13f7SAndroid Build Coastguard Worker }
1196*03ce13f7SAndroid Build Coastguard Worker
emitBr(const CondMIPS32::Cond Cond,const Operand * OpRs,const Operand * OpRt,IOffsetT Offset)1197*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::emitBr(const CondMIPS32::Cond Cond, const Operand *OpRs,
1198*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt, IOffsetT Offset) {
1199*03ce13f7SAndroid Build Coastguard Worker IValueT Opcode = 0;
1200*03ce13f7SAndroid Build Coastguard Worker
1201*03ce13f7SAndroid Build Coastguard Worker switch (Cond) {
1202*03ce13f7SAndroid Build Coastguard Worker default:
1203*03ce13f7SAndroid Build Coastguard Worker break;
1204*03ce13f7SAndroid Build Coastguard Worker case CondMIPS32::AL:
1205*03ce13f7SAndroid Build Coastguard Worker case CondMIPS32::EQ:
1206*03ce13f7SAndroid Build Coastguard Worker case CondMIPS32::EQZ:
1207*03ce13f7SAndroid Build Coastguard Worker Opcode = 0x10000000;
1208*03ce13f7SAndroid Build Coastguard Worker break;
1209*03ce13f7SAndroid Build Coastguard Worker case CondMIPS32::NE:
1210*03ce13f7SAndroid Build Coastguard Worker case CondMIPS32::NEZ:
1211*03ce13f7SAndroid Build Coastguard Worker Opcode = 0x14000000;
1212*03ce13f7SAndroid Build Coastguard Worker break;
1213*03ce13f7SAndroid Build Coastguard Worker case CondMIPS32::LEZ:
1214*03ce13f7SAndroid Build Coastguard Worker Opcode = 0x18000000;
1215*03ce13f7SAndroid Build Coastguard Worker break;
1216*03ce13f7SAndroid Build Coastguard Worker case CondMIPS32::LTZ:
1217*03ce13f7SAndroid Build Coastguard Worker Opcode = 0x04000000;
1218*03ce13f7SAndroid Build Coastguard Worker break;
1219*03ce13f7SAndroid Build Coastguard Worker case CondMIPS32::GEZ:
1220*03ce13f7SAndroid Build Coastguard Worker Opcode = 0x04010000;
1221*03ce13f7SAndroid Build Coastguard Worker break;
1222*03ce13f7SAndroid Build Coastguard Worker case CondMIPS32::GTZ:
1223*03ce13f7SAndroid Build Coastguard Worker Opcode = 0x1C000000;
1224*03ce13f7SAndroid Build Coastguard Worker break;
1225*03ce13f7SAndroid Build Coastguard Worker }
1226*03ce13f7SAndroid Build Coastguard Worker
1227*03ce13f7SAndroid Build Coastguard Worker if (Opcode == 0) {
1228*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("Branch: Invalid condition");
1229*03ce13f7SAndroid Build Coastguard Worker }
1230*03ce13f7SAndroid Build Coastguard Worker
1231*03ce13f7SAndroid Build Coastguard Worker if (OpRs != nullptr) {
1232*03ce13f7SAndroid Build Coastguard Worker IValueT Rs = encodeGPRegister(OpRs, "Rs", "branch");
1233*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rs << 21;
1234*03ce13f7SAndroid Build Coastguard Worker }
1235*03ce13f7SAndroid Build Coastguard Worker
1236*03ce13f7SAndroid Build Coastguard Worker if (OpRt != nullptr) {
1237*03ce13f7SAndroid Build Coastguard Worker IValueT Rt = encodeGPRegister(OpRt, "Rt", "branch");
1238*03ce13f7SAndroid Build Coastguard Worker Opcode |= Rt << 16;
1239*03ce13f7SAndroid Build Coastguard Worker }
1240*03ce13f7SAndroid Build Coastguard Worker
1241*03ce13f7SAndroid Build Coastguard Worker Opcode = encodeBranchOffset(Offset, Opcode);
1242*03ce13f7SAndroid Build Coastguard Worker emitInst(Opcode);
1243*03ce13f7SAndroid Build Coastguard Worker nop(); // delay slot
1244*03ce13f7SAndroid Build Coastguard Worker }
1245*03ce13f7SAndroid Build Coastguard Worker
bcc(const CondMIPS32::Cond Cond,const Operand * OpRs,const Operand * OpRt,Label * TargetLabel)1246*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::bcc(const CondMIPS32::Cond Cond, const Operand *OpRs,
1247*03ce13f7SAndroid Build Coastguard Worker const Operand *OpRt, Label *TargetLabel) {
1248*03ce13f7SAndroid Build Coastguard Worker if (TargetLabel->isBound()) {
1249*03ce13f7SAndroid Build Coastguard Worker const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
1250*03ce13f7SAndroid Build Coastguard Worker emitBr(Cond, OpRs, OpRt, Dest);
1251*03ce13f7SAndroid Build Coastguard Worker return;
1252*03ce13f7SAndroid Build Coastguard Worker }
1253*03ce13f7SAndroid Build Coastguard Worker const IOffsetT Position = Buffer.size();
1254*03ce13f7SAndroid Build Coastguard Worker IOffsetT PrevPosition = TargetLabel->getEncodedPosition();
1255*03ce13f7SAndroid Build Coastguard Worker if (PrevPosition != 0)
1256*03ce13f7SAndroid Build Coastguard Worker PrevPosition = Position - PrevPosition;
1257*03ce13f7SAndroid Build Coastguard Worker emitBr(Cond, OpRs, OpRt, PrevPosition);
1258*03ce13f7SAndroid Build Coastguard Worker TargetLabel->linkTo(*this, Position);
1259*03ce13f7SAndroid Build Coastguard Worker }
1260*03ce13f7SAndroid Build Coastguard Worker
bzc(const CondMIPS32::Cond Cond,const Operand * OpRs,Label * TargetLabel)1261*03ce13f7SAndroid Build Coastguard Worker void AssemblerMIPS32::bzc(const CondMIPS32::Cond Cond, const Operand *OpRs,
1262*03ce13f7SAndroid Build Coastguard Worker Label *TargetLabel) {
1263*03ce13f7SAndroid Build Coastguard Worker static constexpr Operand *OpRtNone = nullptr;
1264*03ce13f7SAndroid Build Coastguard Worker if (TargetLabel->isBound()) {
1265*03ce13f7SAndroid Build Coastguard Worker const int32_t Dest = TargetLabel->getPosition() - Buffer.size();
1266*03ce13f7SAndroid Build Coastguard Worker emitBr(Cond, OpRs, OpRtNone, Dest);
1267*03ce13f7SAndroid Build Coastguard Worker return;
1268*03ce13f7SAndroid Build Coastguard Worker }
1269*03ce13f7SAndroid Build Coastguard Worker const IOffsetT Position = Buffer.size();
1270*03ce13f7SAndroid Build Coastguard Worker IOffsetT PrevPosition = TargetLabel->getEncodedPosition();
1271*03ce13f7SAndroid Build Coastguard Worker if (PrevPosition)
1272*03ce13f7SAndroid Build Coastguard Worker PrevPosition = Position - PrevPosition;
1273*03ce13f7SAndroid Build Coastguard Worker emitBr(Cond, OpRs, OpRtNone, PrevPosition);
1274*03ce13f7SAndroid Build Coastguard Worker TargetLabel->linkTo(*this, Position);
1275*03ce13f7SAndroid Build Coastguard Worker }
1276*03ce13f7SAndroid Build Coastguard Worker
1277*03ce13f7SAndroid Build Coastguard Worker } // end of namespace MIPS32
1278*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
1279