xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceAssemblerMIPS32.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
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