blob: 732651685501dfd23dda77ac7c4d59a208d79161 [file] [log] [blame]
Reed Kotlerd00d48d2015-07-08 09:49:07 -07001//===- subzero/src/IceInstMips32.cpp - Mips32 instruction implementation --===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Implements the InstMips32 and OperandMips32 classes, primarily the
Andrew Scull57e12682015-09-16 11:30:19 -070012/// constructors and the dump()/emit() methods.
Reed Kotlerd00d48d2015-07-08 09:49:07 -070013///
14//===----------------------------------------------------------------------===//
Reed Kotlerd00d48d2015-07-08 09:49:07 -070015#include "IceAssemblerMIPS32.h"
16#include "IceCfg.h"
17#include "IceCfgNode.h"
18#include "IceInst.h"
19#include "IceInstMIPS32.h"
20#include "IceOperand.h"
21#include "IceRegistersMIPS32.h"
22#include "IceTargetLoweringMIPS32.h"
Jim Stichnothac8da5c2015-10-21 06:57:46 -070023#include <limits>
Reed Kotlerd00d48d2015-07-08 09:49:07 -070024
25namespace Ice {
John Porto4a566862016-01-04 09:33:41 -080026namespace MIPS32 {
Reed Kotlerd00d48d2015-07-08 09:49:07 -070027
Sagar Thakur5cce7612016-05-24 06:25:50 -070028const struct InstMIPS32CondAttributes_ {
29 CondMIPS32::Cond Opposite;
30 const char *EmitString;
31} InstMIPS32CondAttributes[] = {
32#define X(tag, opp, emit) \
33 { CondMIPS32::opp, emit } \
34 ,
35 ICEINSTMIPS32COND_TABLE
36#undef X
37};
38
Jim Stichnothac8da5c2015-10-21 06:57:46 -070039bool OperandMIPS32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) {
40 (void)SignExt;
41 (void)Ty;
42 if ((std::numeric_limits<int16_t>::min() <= Offset) &&
43 (Offset <= std::numeric_limits<int16_t>::max()))
44 return true;
45 return false;
46}
47
48OperandMIPS32Mem::OperandMIPS32Mem(Cfg *Func, Type Ty, Variable *Base,
Mohit Bhakkadd1e97772016-07-07 05:07:35 -070049 Operand *ImmOffset, AddrMode Mode)
Jim Stichnothac8da5c2015-10-21 06:57:46 -070050 : OperandMIPS32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Mode(Mode) {
51 // The Neg modes are only needed for Reg +/- Reg.
52 (void)Func;
53 // assert(!isNegAddrMode());
54 NumVars = 1;
55 Vars = &this->Base;
56}
57
Jan Voung3469b022015-07-09 10:32:31 -070058const char *InstMIPS32::getWidthString(Type Ty) {
59 (void)Ty;
60 return "TBD";
61}
Reed Kotlerd00d48d2015-07-08 09:49:07 -070062
Srdjan Obucina53d05682016-09-10 08:25:37 -070063template <> const char *InstMIPS32Abs_d::Opcode = "abs.d";
64template <> const char *InstMIPS32Abs_s::Opcode = "abs.s";
Reed Kotler37af5b02015-11-05 17:07:19 -080065template <> const char *InstMIPS32Add::Opcode = "add";
Srdjan Obucina2f593bb2016-05-27 14:40:32 -070066template <> const char *InstMIPS32Add_d::Opcode = "add.d";
67template <> const char *InstMIPS32Add_s::Opcode = "add.s";
Srdjan Obucina418135a2016-06-02 06:47:06 -070068template <> const char *InstMIPS32Addiu::Opcode = "addiu";
Reed Kotler00e36042016-02-01 20:52:19 -080069template <> const char *InstMIPS32Addu::Opcode = "addu";
Reed Kotler37af5b02015-11-05 17:07:19 -080070template <> const char *InstMIPS32And::Opcode = "and";
Sagar Thakur38dcb592016-05-09 11:57:59 -070071template <> const char *InstMIPS32Andi::Opcode = "andi";
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -070072template <> const char *InstMIPS32C_eq_d::Opcode = "c.eq.d";
73template <> const char *InstMIPS32C_eq_s::Opcode = "c.eq.s";
74template <> const char *InstMIPS32C_ole_d::Opcode = "c.ole.d";
75template <> const char *InstMIPS32C_ole_s::Opcode = "c.ole.s";
76template <> const char *InstMIPS32C_olt_d::Opcode = "c.olt.d";
77template <> const char *InstMIPS32C_olt_s::Opcode = "c.olt.s";
78template <> const char *InstMIPS32C_ueq_d::Opcode = "c.ueq.d";
79template <> const char *InstMIPS32C_ueq_s::Opcode = "c.ueq.s";
80template <> const char *InstMIPS32C_ule_d::Opcode = "c.ule.d";
81template <> const char *InstMIPS32C_ule_s::Opcode = "c.ule.s";
82template <> const char *InstMIPS32C_ult_d::Opcode = "c.ult.d";
83template <> const char *InstMIPS32C_ult_s::Opcode = "c.ult.s";
84template <> const char *InstMIPS32C_un_d::Opcode = "c.un.d";
85template <> const char *InstMIPS32C_un_s::Opcode = "c.un.s";
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -070086template <> const char *InstMIPS32Clz::Opcode = "clz";
Srdjan Obucina418135a2016-06-02 06:47:06 -070087template <> const char *InstMIPS32Cvt_d_l::Opcode = "cvt.d.l";
88template <> const char *InstMIPS32Cvt_d_s::Opcode = "cvt.d.s";
89template <> const char *InstMIPS32Cvt_d_w::Opcode = "cvt.d.w";
90template <> const char *InstMIPS32Cvt_s_d::Opcode = "cvt.s.d";
91template <> const char *InstMIPS32Cvt_s_l::Opcode = "cvt.s.l";
92template <> const char *InstMIPS32Cvt_s_w::Opcode = "cvt.s.w";
Srdjan Obucinaae93eee2016-05-18 11:31:15 -070093template <> const char *InstMIPS32Div::Opcode = "div";
Srdjan Obucina2f593bb2016-05-27 14:40:32 -070094template <> const char *InstMIPS32Div_d::Opcode = "div.d";
95template <> const char *InstMIPS32Div_s::Opcode = "div.s";
Srdjan Obucinaae93eee2016-05-18 11:31:15 -070096template <> const char *InstMIPS32Divu::Opcode = "divu";
Srdjan Obucina418135a2016-06-02 06:47:06 -070097template <> const char *InstMIPS32La::Opcode = "la";
98template <> const char *InstMIPS32Ldc1::Opcode = "ldc1";
99template <> const char *InstMIPS32Lui::Opcode = "lui";
Sagar Thakur633394c2016-06-25 08:34:10 -0700100template <> const char *InstMIPS32Lw::Opcode = "lw";
Srdjan Obucina418135a2016-06-02 06:47:06 -0700101template <> const char *InstMIPS32Lwc1::Opcode = "lwc1";
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700102template <> const char *InstMIPS32Mfc1::Opcode = "mfc1";
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800103template <> const char *InstMIPS32Mfhi::Opcode = "mfhi";
104template <> const char *InstMIPS32Mflo::Opcode = "mflo";
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700105template <> const char *InstMIPS32Mov_d::Opcode = "mov.d";
106template <> const char *InstMIPS32Mov_s::Opcode = "mov.s";
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700107template <> const char *InstMIPS32Movf::Opcode = "movf";
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700108template <> const char *InstMIPS32Movn::Opcode = "movn";
109template <> const char *InstMIPS32Movn_d::Opcode = "movn.d";
110template <> const char *InstMIPS32Movn_s::Opcode = "movn.s";
Srdjan Obucinaf315f0d2016-09-13 05:46:30 -0700111template <> const char *InstMIPS32Movt::Opcode = "movt";
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700112template <> const char *InstMIPS32Movz::Opcode = "movz";
113template <> const char *InstMIPS32Movz_d::Opcode = "movz.d";
114template <> const char *InstMIPS32Movz_s::Opcode = "movz.s";
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700115template <> const char *InstMIPS32Mtc1::Opcode = "mtc1";
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800116template <> const char *InstMIPS32Mthi::Opcode = "mthi";
117template <> const char *InstMIPS32Mtlo::Opcode = "mtlo";
Reed Kotler37af5b02015-11-05 17:07:19 -0800118template <> const char *InstMIPS32Mul::Opcode = "mul";
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700119template <> const char *InstMIPS32Mul_d::Opcode = "mul.d";
120template <> const char *InstMIPS32Mul_s::Opcode = "mul.s";
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800121template <> const char *InstMIPS32Mult::Opcode = "mult";
122template <> const char *InstMIPS32Multu::Opcode = "multu";
Srdjan Obucinacadda792016-09-22 11:24:44 -0700123template <> const char *InstMIPS32Nor::Opcode = "nor";
Reed Kotler37af5b02015-11-05 17:07:19 -0800124template <> const char *InstMIPS32Or::Opcode = "or";
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700125template <> const char *InstMIPS32Ori::Opcode = "ori";
Srdjan Obucina418135a2016-06-02 06:47:06 -0700126template <> const char *InstMIPS32Sdc1::Opcode = "sdc1";
Sagar Thakur38dcb592016-05-09 11:57:59 -0700127template <> const char *InstMIPS32Sll::Opcode = "sll";
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700128template <> const char *InstMIPS32Sllv::Opcode = "sllv";
Sagar Thakur1a478b12016-04-25 08:39:19 -0700129template <> const char *InstMIPS32Slt::Opcode = "slt";
130template <> const char *InstMIPS32Slti::Opcode = "slti";
131template <> const char *InstMIPS32Sltiu::Opcode = "sltiu";
Reed Kotler00e36042016-02-01 20:52:19 -0800132template <> const char *InstMIPS32Sltu::Opcode = "sltu";
Srdjan Obucina53d05682016-09-10 08:25:37 -0700133template <> const char *InstMIPS32Sqrt_d::Opcode = "sqrt.d";
134template <> const char *InstMIPS32Sqrt_s::Opcode = "sqrt.s";
Sagar Thakur38dcb592016-05-09 11:57:59 -0700135template <> const char *InstMIPS32Sra::Opcode = "sra";
Srdjan Obucinac2ee36a2016-05-17 13:16:02 -0700136template <> const char *InstMIPS32Srav::Opcode = "srav";
137template <> const char *InstMIPS32Srl::Opcode = "srl";
138template <> const char *InstMIPS32Srlv::Opcode = "srlv";
Reed Kotler37af5b02015-11-05 17:07:19 -0800139template <> const char *InstMIPS32Sub::Opcode = "sub";
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700140template <> const char *InstMIPS32Sub_d::Opcode = "sub.d";
141template <> const char *InstMIPS32Sub_s::Opcode = "sub.s";
Reed Kotler00e36042016-02-01 20:52:19 -0800142template <> const char *InstMIPS32Subu::Opcode = "subu";
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700143template <> const char *InstMIPS32Sw::Opcode = "sw";
Srdjan Obucina418135a2016-06-02 06:47:06 -0700144template <> const char *InstMIPS32Swc1::Opcode = "swc1";
Jaydeep Patilcc6dea72016-09-19 16:48:34 -0700145template <> const char *InstMIPS32Teq::Opcode = "teq";
Srdjan Obucina418135a2016-06-02 06:47:06 -0700146template <> const char *InstMIPS32Trunc_l_d::Opcode = "trunc.l.d";
147template <> const char *InstMIPS32Trunc_l_s::Opcode = "trunc.l.s";
148template <> const char *InstMIPS32Trunc_w_d::Opcode = "trunc.w.d";
149template <> const char *InstMIPS32Trunc_w_s::Opcode = "trunc.w.s";
Reed Kotler37af5b02015-11-05 17:07:19 -0800150template <> const char *InstMIPS32Xor::Opcode = "xor";
Sagar Thakur1a478b12016-04-25 08:39:19 -0700151template <> const char *InstMIPS32Xori::Opcode = "xori";
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700152
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700153template <> void InstMIPS32Lui::emit(const Cfg *Func) const {
154 if (!BuildDefs::dump())
155 return;
156 Ostream &Str = Func->getContext()->getStrEmit();
157 assert(getSrcSize() == 1);
158 Str << "\t" << Opcode << "\t";
159 getDest()->emit(Func);
160 Str << ", ";
161 auto *Src0 = llvm::cast<Constant>(getSrc(0));
162 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
163 emitRelocOp(Str, Reloc);
164 Str << "(";
165 CR->emitWithoutPrefix(Func->getTarget());
166 Str << ")";
167 } else {
168 Src0->emit(Func);
169 }
170}
171
Reed Kotler3fe4b572016-02-23 18:59:43 -0800172InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
173 const CfgNode *TargetFalse,
Sagar Thakur5cce7612016-05-24 06:25:50 -0700174 const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
Reed Kotler3fe4b572016-02-23 18:59:43 -0800175 : InstMIPS32(Func, InstMIPS32::Br, 0, nullptr), TargetTrue(TargetTrue),
Sagar Thakur5cce7612016-05-24 06:25:50 -0700176 TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {}
177
178InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
179 const CfgNode *TargetFalse, Operand *Src0,
180 const InstMIPS32Label *Label, CondMIPS32::Cond Cond)
181 : InstMIPS32(Func, InstMIPS32::Br, 1, nullptr), TargetTrue(TargetTrue),
182 TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {
183 addSource(Src0);
184}
185
186InstMIPS32Br::InstMIPS32Br(Cfg *Func, const CfgNode *TargetTrue,
187 const CfgNode *TargetFalse, Operand *Src0,
188 Operand *Src1, const InstMIPS32Label *Label,
189 CondMIPS32::Cond Cond)
190 : InstMIPS32(Func, InstMIPS32::Br, 2, nullptr), TargetTrue(TargetTrue),
191 TargetFalse(TargetFalse), Label(Label), Predicate(Cond) {
192 addSource(Src0);
193 addSource(Src1);
194}
Reed Kotler3fe4b572016-02-23 18:59:43 -0800195
Jaydeep Patil13f0ca32016-08-26 13:27:40 -0700196CondMIPS32::Cond InstMIPS32::getOppositeCondition(CondMIPS32::Cond Cond) {
197 return InstMIPS32CondAttributes[Cond].Opposite;
198}
199
200bool InstMIPS32Br::optimizeBranch(const CfgNode *NextNode) {
201 // If there is no next block, then there can be no fallthrough to optimize.
202 if (NextNode == nullptr)
203 return false;
204 // Intra-block conditional branches can't be optimized.
205 if (Label != nullptr)
206 return false;
207 // Unconditional branch to the next node can be removed.
208 if (isUnconditionalBranch() && getTargetFalse() == NextNode) {
209 assert(getTargetTrue() == nullptr);
210 setDeleted();
211 return true;
212 }
213 // If there is no fallthrough node, such as a non-default case label for a
214 // switch instruction, then there is no opportunity to optimize.
215 if (getTargetTrue() == nullptr)
216 return false;
217 // If the fallthrough is to the next node, set fallthrough to nullptr to
218 // indicate.
219 if (getTargetTrue() == NextNode) {
220 TargetTrue = nullptr;
221 return true;
222 }
223 // If TargetFalse is the next node, and TargetTrue is not nullptr
224 // then invert the branch condition, swap the targets, and set new
225 // fallthrough to nullptr.
226 if (getTargetFalse() == NextNode) {
227 assert(Predicate != CondMIPS32::AL);
228 setPredicate(getOppositeCondition(getPredicate()));
229 TargetFalse = getTargetTrue();
230 TargetTrue = nullptr;
231 return true;
232 }
233 return false;
234}
235
Jaydeep Patil8b322412016-08-18 22:43:43 -0700236bool InstMIPS32Br::repointEdges(CfgNode *OldNode, CfgNode *NewNode) {
237 bool Found = false;
238 if (TargetFalse == OldNode) {
239 TargetFalse = NewNode;
240 Found = true;
241 }
242 if (TargetTrue == OldNode) {
243 TargetTrue = NewNode;
244 Found = true;
245 }
246 return Found;
247}
248
Reed Kotler3fe4b572016-02-23 18:59:43 -0800249InstMIPS32Label::InstMIPS32Label(Cfg *Func, TargetMIPS32 *Target)
250 : InstMIPS32(Func, InstMIPS32::Label, 0, nullptr),
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700251 Number(Target->makeNextLabelNumber()) {
252 if (BuildDefs::dump()) {
253 Name = GlobalString::createWithString(
254 Func->getContext(),
255 ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number));
256 } else {
257 Name = GlobalString::createWithoutString(Func->getContext());
258 }
Reed Kotler3fe4b572016-02-23 18:59:43 -0800259}
260
261void InstMIPS32Label::dump(const Cfg *Func) const {
262 if (!BuildDefs::dump())
263 return;
264 Ostream &Str = Func->getContext()->getStrDump();
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700265 Str << getLabelName() << ":";
Reed Kotler3fe4b572016-02-23 18:59:43 -0800266}
267
Jim Stichnoth09802a92016-02-24 07:05:12 -0800268void InstMIPS32Label::emit(const Cfg *Func) const {
269 if (!BuildDefs::dump())
270 return;
271 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700272 Str << getLabelName() << ":";
Jim Stichnoth09802a92016-02-24 07:05:12 -0800273}
274
Reed Kotler3fe4b572016-02-23 18:59:43 -0800275void InstMIPS32Label::emitIAS(const Cfg *Func) const {
276 (void)Func;
277 llvm_unreachable("Not yet implemented");
278}
279
Reed Kotler00e36042016-02-01 20:52:19 -0800280InstMIPS32Call::InstMIPS32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
281 : InstMIPS32(Func, InstMIPS32::Call, 1, Dest) {
282 HasSideEffects = true;
283 addSource(CallTarget);
284}
285
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700286InstMIPS32Mov::InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src)
287 : InstMIPS32(Func, InstMIPS32::Mov, 2, Dest) {
288 auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest);
289 auto *Src64 = llvm::dyn_cast<Variable64On32>(Src);
290
291 assert(Dest64 == nullptr || Src64 == nullptr);
292
293 if (Dest64 != nullptr) {
294 // this-> is needed below because there is a parameter named Dest.
295 this->Dest = Dest64->getLo();
296 DestHi = Dest64->getHi();
297 }
298
299 if (Src64 == nullptr) {
300 addSource(Src);
301 } else {
302 addSource(Src64->getLo());
303 addSource(Src64->getHi());
304 }
305}
306
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700307InstMIPS32Ret::InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source)
308 : InstMIPS32(Func, InstMIPS32::Ret, Source ? 2 : 1, nullptr) {
309 addSource(RA);
310 if (Source)
311 addSource(Source);
312}
313
Jan Voung3469b022015-07-09 10:32:31 -0700314// ======================== Dump routines ======================== //
315
316void InstMIPS32::dump(const Cfg *Func) const {
317 if (!BuildDefs::dump())
318 return;
319 Ostream &Str = Func->getContext()->getStrDump();
320 Str << "[MIPS32] ";
321 Inst::dump(Func);
322}
323
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700324void OperandMIPS32Mem::emit(const Cfg *Func) const {
325 if (!BuildDefs::dump())
326 return;
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700327 Ostream &Str = Func->getContext()->getStrEmit();
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700328 Operand *Offset = getOffset();
329 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
Mohit Bhakkad6a661ce2016-07-13 07:32:37 -0700330 Str << "(";
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700331 CR->emitWithoutPrefix(Func->getTarget());
Mohit Bhakkad6a661ce2016-07-13 07:32:37 -0700332 Str << ")";
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700333 } else
334 Offset->emit(Func);
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700335 Str << "(";
336 getBase()->emit(Func);
337 Str << ")";
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700338}
339
340void InstMIPS32::emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst,
341 const Cfg *Func) {
342 if (!BuildDefs::dump())
343 return;
344 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700345 Str << "\t" << Opcode << "\t";
346 Inst->getDest()->emit(Func);
347 Str << ", ";
348 Inst->getSrc(0)->emit(Func);
349}
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800350void InstMIPS32::emitUnaryopGPRFLoHi(const char *Opcode, const InstMIPS32 *Inst,
351 const Cfg *Func) {
352 if (!BuildDefs::dump())
353 return;
354 Ostream &Str = Func->getContext()->getStrEmit();
355 Str << "\t" << Opcode << "\t";
356 Inst->getDest()->emit(Func);
357}
358
359void InstMIPS32::emitUnaryopGPRTLoHi(const char *Opcode, const InstMIPS32 *Inst,
360 const Cfg *Func) {
361 if (!BuildDefs::dump())
362 return;
363 Ostream &Str = Func->getContext()->getStrEmit();
364 Str << "\t" << Opcode << "\t";
365 Inst->getSrc(0)->emit(Func);
366}
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700367
Reed Kotler37af5b02015-11-05 17:07:19 -0800368void InstMIPS32::emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
369 const Cfg *Func) {
370 if (!BuildDefs::dump())
371 return;
372 Ostream &Str = Func->getContext()->getStrEmit();
373 assert(Inst->getSrcSize() == 2);
374 Str << "\t" << Opcode << "\t";
375 Inst->getDest()->emit(Func);
376 Str << ", ";
377 Inst->getSrc(0)->emit(Func);
378 Str << ", ";
379 Inst->getSrc(1)->emit(Func);
380}
381
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700382void InstMIPS32::emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
383 const Cfg *Func) {
384 if (!BuildDefs::dump())
385 return;
386 Ostream &Str = Func->getContext()->getStrEmit();
387 assert(Inst->getSrcSize() == 1);
388 Str << "\t" << Opcode << "\t";
389 Inst->getDest()->emit(Func);
390 Str << ", ";
391 Inst->getSrc(0)->emit(Func);
392}
393
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800394void InstMIPS32::emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
395 const Cfg *Func) {
396 if (!BuildDefs::dump())
397 return;
398 Ostream &Str = Func->getContext()->getStrEmit();
399 assert(Inst->getSrcSize() == 2);
400 Str << "\t" << Opcode << "\t";
401 Inst->getSrc(0)->emit(Func);
402 Str << ", ";
403 Inst->getSrc(1)->emit(Func);
404}
405
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700406void InstMIPS32Ret::emit(const Cfg *Func) const {
Jan Voung3469b022015-07-09 10:32:31 -0700407 if (!BuildDefs::dump())
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700408 return;
409 assert(getSrcSize() > 0);
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800410 auto *RA = llvm::cast<Variable>(getSrc(0));
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700411 assert(RA->hasReg());
412 assert(RA->getRegNum() == RegMIPS32::Reg_RA);
413 Ostream &Str = Func->getContext()->getStrEmit();
414 Str << "\t"
Jim Stichnoth6106df82015-12-16 06:17:58 -0800415 "jr"
416 "\t";
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700417 RA->emit(Func);
418}
419
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700420void InstMIPS32Br::emitIAS(const Cfg *Func) const {
421 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
422 if (isUnconditionalBranch()) {
423 Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
424 } else {
425 switch (Predicate) {
426 default:
427 break;
428 case CondMIPS32::EQ:
429 case CondMIPS32::NE:
430 Asm->bcc(Predicate, getSrc(0), getSrc(1),
431 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
432 break;
433 case CondMIPS32::EQZ:
434 case CondMIPS32::NEZ:
435 case CondMIPS32::LEZ:
436 case CondMIPS32::LTZ:
437 case CondMIPS32::GEZ:
438 case CondMIPS32::GTZ:
439 Asm->bzc(Predicate, getSrc(0),
440 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
441 break;
442 }
443 }
444}
445
Reed Kotler3fe4b572016-02-23 18:59:43 -0800446void InstMIPS32Br::emit(const Cfg *Func) const {
447 if (!BuildDefs::dump())
448 return;
449 Ostream &Str = Func->getContext()->getStrEmit();
450 Str << "\t"
Sagar Thakur5cce7612016-05-24 06:25:50 -0700451 "b" << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
Jaydeep Patil29823f12016-08-31 05:10:03 -0700452 if (Label != nullptr) {
453 getSrc(0)->emit(Func);
454 Str << ", ";
455 getSrc(1)->emit(Func);
456 Str << ", " << Label->getLabelName();
Reed Kotler3fe4b572016-02-23 18:59:43 -0800457 } else {
458 if (isUnconditionalBranch()) {
459 Str << getTargetFalse()->getAsmName();
460 } else {
Sagar Thakur5cce7612016-05-24 06:25:50 -0700461 switch (Predicate) {
462 default:
463 break;
464 case CondMIPS32::EQ:
465 case CondMIPS32::NE: {
466 getSrc(0)->emit(Func);
467 Str << ", ";
468 getSrc(1)->emit(Func);
469 Str << ", ";
470 break;
471 }
472 case CondMIPS32::EQZ:
473 case CondMIPS32::NEZ:
474 case CondMIPS32::LEZ:
475 case CondMIPS32::LTZ:
476 case CondMIPS32::GEZ:
477 case CondMIPS32::GTZ: {
478 getSrc(0)->emit(Func);
479 Str << ", ";
480 break;
481 }
482 }
483 Str << getTargetFalse()->getAsmName();
Jaydeep Patil13f0ca32016-08-26 13:27:40 -0700484 if (getTargetTrue()) {
485 Str << "\n\t"
486 << "b"
487 << "\t" << getTargetTrue()->getAsmName();
488 }
Sagar Thakur5cce7612016-05-24 06:25:50 -0700489 }
490 }
491}
492
493void InstMIPS32Br::dump(const Cfg *Func) const {
494 if (!BuildDefs::dump())
495 return;
496 Ostream &Str = Func->getContext()->getStrDump();
497 Str << "\t"
498 "b" << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
499
Jaydeep Patil29823f12016-08-31 05:10:03 -0700500 if (Label != nullptr) {
501 getSrc(0)->dump(Func);
502 Str << ", ";
503 getSrc(1)->dump(Func);
504 Str << ", " << Label->getLabelName();
Sagar Thakur5cce7612016-05-24 06:25:50 -0700505 } else {
506 if (isUnconditionalBranch()) {
507 Str << getTargetFalse()->getAsmName();
508 } else {
509 dumpSources(Func);
510 Str << ", ";
511 Str << getTargetFalse()->getAsmName();
Jaydeep Patil13f0ca32016-08-26 13:27:40 -0700512 if (getTargetTrue()) {
513 Str << "\n\t"
514 << "b"
515 << "\t" << getTargetTrue()->getAsmName();
516 }
Reed Kotler3fe4b572016-02-23 18:59:43 -0800517 }
518 }
519}
520
Reed Kotler00e36042016-02-01 20:52:19 -0800521void InstMIPS32Call::emit(const Cfg *Func) const {
522 if (!BuildDefs::dump())
523 return;
524 Ostream &Str = Func->getContext()->getStrEmit();
525 assert(getSrcSize() == 1);
526 if (llvm::isa<ConstantInteger32>(getCallTarget())) {
527 // This shouldn't happen (typically have to copy the full 32-bits to a
528 // register and do an indirect jump).
529 llvm::report_fatal_error("MIPS2Call to ConstantInteger32");
530 } else if (const auto *CallTarget =
531 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
532 // Calls only have 24-bits, but the linker should insert veneers to extend
533 // the range if needed.
534 Str << "\t"
535 "jal"
536 "\t";
537 CallTarget->emitWithoutPrefix(Func->getTarget());
538 } else {
539 Str << "\t"
540 "jal"
541 "\t";
542 getCallTarget()->emit(Func);
543 }
544}
545
546void InstMIPS32Call::emitIAS(const Cfg *Func) const {
547 (void)Func;
548 llvm_unreachable("Not yet implemented");
549}
550
551void InstMIPS32Call::dump(const Cfg *Func) const {
552 if (!BuildDefs::dump())
553 return;
554 Ostream &Str = Func->getContext()->getStrDump();
555 if (getDest()) {
556 dumpDest(Func);
557 Str << " = ";
558 }
559 Str << "call ";
560 getCallTarget()->dump(Func);
561}
562
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700563void InstMIPS32Ret::emitIAS(const Cfg *Func) const {
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700564 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
565 auto *RA = llvm::cast<Variable>(getSrc(0));
566 assert(RA->hasReg());
567 assert(RA->getRegNum() == RegMIPS32::Reg_RA);
568 (void)RA;
569 Asm->ret();
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700570}
571
572void InstMIPS32Ret::dump(const Cfg *Func) const {
Jan Voung3469b022015-07-09 10:32:31 -0700573 if (!BuildDefs::dump())
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700574 return;
575 Ostream &Str = Func->getContext()->getStrDump();
576 Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
577 Str << "ret." << Ty << " ";
578 dumpSources(Func);
579}
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700580
581void InstMIPS32Mov::emit(const Cfg *Func) const {
582 if (!BuildDefs::dump())
583 return;
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700584 assert(!(isMultiDest() && isMultiSource()) && "Invalid mov type.");
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700585 if (isMultiDest()) {
586 emitMultiDestSingleSource(Func);
587 return;
588 }
589
590 if (isMultiSource()) {
591 emitSingleDestMultiSource(Func);
592 return;
593 }
594
595 emitSingleDestSingleSource(Func);
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700596}
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700597
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700598// TODO(jaydeep.patil) Handle all types of operands in mov
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700599void InstMIPS32Mov::emitIAS(const Cfg *Func) const {
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700600 assert(!(isMultiDest() && isMultiSource()) && "Invalid mov type.");
601
602 if (isMultiDest()) {
603 llvm_unreachable("Not yet implemented");
604 }
605 if (isMultiSource()) {
606 llvm_unreachable("Not yet implemented");
607 }
608
609 Variable *Dest = getDest();
610 Operand *Src = getSrc(0);
611 auto *SrcV = llvm::dyn_cast<Variable>(Src);
612 assert(!llvm::isa<Constant>(Src));
613 const bool DestIsReg = Dest->hasReg();
614 const bool SrcIsReg = (SrcV && SrcV->hasReg());
615
616 // reg to reg
617 if (DestIsReg && SrcIsReg) {
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700618 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
619 Asm->move(getDest(), getSrc(0));
620 return;
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700621 }
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700622 llvm_unreachable("Not yet implemented");
623}
624
625void InstMIPS32Mov::dump(const Cfg *Func) const {
626 if (!BuildDefs::dump())
627 return;
628 assert(getSrcSize() == 1 || getSrcSize() == 2);
629 Ostream &Str = Func->getContext()->getStrDump();
630 Variable *Dest = getDest();
631 Variable *DestHi = getDestHi();
632 Dest->dump(Func);
633 if (DestHi) {
634 Str << ", ";
635 DestHi->dump(Func);
636 }
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700637 dumpOpcode(Str, " = mov", getDest()->getType());
638 Str << " ";
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700639 dumpSources(Func);
640}
641
642void InstMIPS32Mov::emitMultiDestSingleSource(const Cfg *Func) const {
643 if (!BuildDefs::dump())
644 return;
645 Ostream &Str = Func->getContext()->getStrEmit();
646 Variable *DestLo = getDest();
647 Variable *DestHi = getDestHi();
648 auto *Src = llvm::cast<Variable>(getSrc(0));
649
650 assert(DestHi->hasReg());
651 assert(DestLo->hasReg());
652 assert(llvm::isa<Variable>(Src) && Src->hasReg());
653
654 // Str << "\t"
655 // << "vmov" << getPredicate() << "\t";
656 DestLo->emit(Func);
657 Str << ", ";
658 DestHi->emit(Func);
659 Str << ", ";
660 Src->emit(Func);
661}
662
663void InstMIPS32Mov::emitSingleDestMultiSource(const Cfg *Func) const {
664 if (!BuildDefs::dump())
665 return;
666 Ostream &Str = Func->getContext()->getStrEmit();
667 Variable *Dest = getDest();
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800668 auto *SrcLo = llvm::cast<Variable>(getSrc(0));
669 auto *SrcHi = llvm::cast<Variable>(getSrc(1));
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700670
671 assert(SrcHi->hasReg());
672 assert(SrcLo->hasReg());
673 assert(Dest->hasReg());
674 assert(getSrcSize() == 2);
675
676 // Str << "\t"
677 // << "vmov" << getPredicate() << "\t";
678 Dest->emit(Func);
679 Str << ", ";
680 SrcLo->emit(Func);
681 Str << ", ";
682 SrcHi->emit(Func);
683}
684
685void InstMIPS32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
Reed Kotler37af5b02015-11-05 17:07:19 -0800686 if (!BuildDefs::dump())
687 return;
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700688 Ostream &Str = Func->getContext()->getStrEmit();
Reed Kotler37af5b02015-11-05 17:07:19 -0800689 Variable *Dest = getDest();
690 Operand *Src = getSrc(0);
Srdjan Obucina36847bd2016-07-06 15:58:07 -0700691 auto *SrcV = llvm::dyn_cast<Variable>(Src);
692
693 assert(!llvm::isa<Constant>(Src));
694
695 const char *ActualOpcode = nullptr;
696 const bool DestIsReg = Dest->hasReg();
Srdjan Obucina36847bd2016-07-06 15:58:07 -0700697 const bool SrcIsReg = (SrcV && SrcV->hasReg());
Srdjan Obucina36847bd2016-07-06 15:58:07 -0700698
699 // reg to reg
700 if (DestIsReg && SrcIsReg) {
Jaydeep Patild3297662016-09-13 22:52:27 -0700701 const Type DstType = Dest->getType();
702 const Type SrcType = Src->getType();
703
704 // move GP to/from FP
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700705 if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
706 (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
Jaydeep Patild3297662016-09-13 22:52:27 -0700707 if (isScalarFloatingType(DstType)) {
708 Str << "\t"
709 "mtc1"
710 "\t";
711 getSrc(0)->emit(Func);
712 Str << ", ";
713 getDest()->emit(Func);
714 return;
715 }
716 ActualOpcode = "mfc1";
717 } else {
718 switch (Dest->getType()) {
719 case IceType_f32:
720 ActualOpcode = "mov.s";
721 break;
722 case IceType_f64:
723 ActualOpcode = "mov.d";
724 break;
725 case IceType_i1:
726 case IceType_i8:
727 case IceType_i16:
728 case IceType_i32:
729 ActualOpcode = "move";
730 break;
731 default:
732 UnimplementedError(getFlags());
733 return;
734 }
Srdjan Obucina36847bd2016-07-06 15:58:07 -0700735 }
736
737 assert(ActualOpcode);
738 Str << "\t" << ActualOpcode << "\t";
739 getDest()->emit(Func);
740 Str << ", ";
741 getSrc(0)->emit(Func);
742 return;
Reed Kotler37af5b02015-11-05 17:07:19 -0800743 }
744
Jaydeep Patil1d0690b2016-09-04 07:19:08 -0700745 llvm::report_fatal_error("Invalid mov instruction. Dest or Src is memory.");
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700746}
747
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700748template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const {
749 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
750 Asm->abs_d(getDest(), getSrc(0));
751}
752
753template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const {
754 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
755 Asm->abs_s(getDest(), getSrc(0));
756}
757
758template <> void InstMIPS32Add_d::emitIAS(const Cfg *Func) const {
759 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
760 Asm->add_d(getDest(), getSrc(0), getSrc(1));
761}
762
763template <> void InstMIPS32Add_s::emitIAS(const Cfg *Func) const {
764 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
765 Asm->add_s(getDest(), getSrc(0), getSrc(1));
766}
767
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700768template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const {
769 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
770 Asm->addiu(getDest(), getSrc(0), Imm);
771}
772
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700773template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const {
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700774 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700775 Asm->addu(getDest(), getSrc(0), getSrc(1));
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700776}
777
778template <> void InstMIPS32And::emitIAS(const Cfg *Func) const {
779 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
780 Asm->and_(getDest(), getSrc(0), getSrc(1));
781}
782
783template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const {
784 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
785 Asm->andi(getDest(), getSrc(0), Imm);
786}
787
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700788template <> void InstMIPS32C_eq_d::emitIAS(const Cfg *Func) const {
789 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
790 Asm->c_eq_d(getSrc(0), getSrc(1));
791}
792
793template <> void InstMIPS32C_eq_s::emitIAS(const Cfg *Func) const {
794 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
795 Asm->c_eq_s(getSrc(0), getSrc(1));
796}
797
798template <> void InstMIPS32C_ole_d::emitIAS(const Cfg *Func) const {
799 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
800 Asm->c_ole_d(getSrc(0), getSrc(1));
801}
802
803template <> void InstMIPS32C_ole_s::emitIAS(const Cfg *Func) const {
804 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
805 Asm->c_ole_s(getSrc(0), getSrc(1));
806}
807
808template <> void InstMIPS32C_olt_d::emitIAS(const Cfg *Func) const {
809 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
810 Asm->c_olt_d(getSrc(0), getSrc(1));
811}
812
813template <> void InstMIPS32C_olt_s::emitIAS(const Cfg *Func) const {
814 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
815 Asm->c_olt_s(getSrc(0), getSrc(1));
816}
817
818template <> void InstMIPS32C_ueq_d::emitIAS(const Cfg *Func) const {
819 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
820 Asm->c_ueq_d(getSrc(0), getSrc(1));
821}
822
823template <> void InstMIPS32C_ueq_s::emitIAS(const Cfg *Func) const {
824 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
825 Asm->c_ueq_s(getSrc(0), getSrc(1));
826}
827
828template <> void InstMIPS32C_ule_d::emitIAS(const Cfg *Func) const {
829 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
830 Asm->c_ule_d(getSrc(0), getSrc(1));
831}
832
833template <> void InstMIPS32C_ule_s::emitIAS(const Cfg *Func) const {
834 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
835 Asm->c_ule_s(getSrc(0), getSrc(1));
836}
837
838template <> void InstMIPS32C_ult_d::emitIAS(const Cfg *Func) const {
839 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
840 Asm->c_ult_d(getSrc(0), getSrc(1));
841}
842
843template <> void InstMIPS32C_ult_s::emitIAS(const Cfg *Func) const {
844 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
845 Asm->c_ult_s(getSrc(0), getSrc(1));
846}
847
848template <> void InstMIPS32C_un_d::emitIAS(const Cfg *Func) const {
849 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
850 Asm->c_un_d(getSrc(0), getSrc(1));
851}
852
853template <> void InstMIPS32C_un_s::emitIAS(const Cfg *Func) const {
854 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
855 Asm->c_un_s(getSrc(0), getSrc(1));
856}
857
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -0700858template <> void InstMIPS32Clz::emitIAS(const Cfg *Func) const {
859 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
860 Asm->clz(getDest(), getSrc(0));
861}
862
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700863template <> void InstMIPS32Cvt_d_l::emitIAS(const Cfg *Func) const {
864 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
865 Asm->cvt_d_l(getDest(), getSrc(0));
866}
867
868template <> void InstMIPS32Cvt_d_s::emitIAS(const Cfg *Func) const {
869 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
870 Asm->cvt_d_s(getDest(), getSrc(0));
871}
872
873template <> void InstMIPS32Cvt_d_w::emitIAS(const Cfg *Func) const {
874 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
875 Asm->cvt_d_w(getDest(), getSrc(0));
876}
877
878template <> void InstMIPS32Cvt_s_d::emitIAS(const Cfg *Func) const {
879 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
880 Asm->cvt_s_d(getDest(), getSrc(0));
881}
882
883template <> void InstMIPS32Cvt_s_l::emitIAS(const Cfg *Func) const {
884 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
885 Asm->cvt_s_l(getDest(), getSrc(0));
886}
887
888template <> void InstMIPS32Cvt_s_w::emitIAS(const Cfg *Func) const {
889 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
890 Asm->cvt_s_w(getDest(), getSrc(0));
891}
892
893template <> void InstMIPS32Div_d::emitIAS(const Cfg *Func) const {
894 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
895 Asm->div_d(getDest(), getSrc(0), getSrc(1));
896}
897
898template <> void InstMIPS32Div_s::emitIAS(const Cfg *Func) const {
899 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
900 Asm->div_s(getDest(), getSrc(0), getSrc(1));
901}
902
903template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const {
904 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
905 auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
906 ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
907 uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
908 Asm->lw(getDest(), Mem->getBase(), Imm);
909}
910
911template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const {
912 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
913 Asm->mfc1(getDest(), getSrc(0));
914}
915
916template <> void InstMIPS32Mflo::emit(const Cfg *Func) const {
917 if (!BuildDefs::dump())
918 return;
919 emitUnaryopGPRFLoHi(Opcode, this, Func);
920}
921
922template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const {
923 if (!BuildDefs::dump())
924 return;
925 emitUnaryopGPRFLoHi(Opcode, this, Func);
926}
927
928template <> void InstMIPS32Mov_d::emitIAS(const Cfg *Func) const {
929 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
930 Asm->mov_d(getDest(), getSrc(0));
931}
932
933template <> void InstMIPS32Mov_s::emitIAS(const Cfg *Func) const {
934 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
935 Asm->mov_s(getDest(), getSrc(0));
936}
937
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700938template <> void InstMIPS32Movf::emitIAS(const Cfg *Func) const {
939 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Jaydeep Patild8954472016-09-21 06:24:41 -0700940 Asm->movf(getDest(), getSrc(1), getSrc(2));
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700941}
942
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -0700943template <> void InstMIPS32Movn::emitIAS(const Cfg *Func) const {
944 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
945 Asm->movn(getDest(), getSrc(0), getSrc(1));
946}
947
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700948template <> void InstMIPS32Movn_d::emitIAS(const Cfg *Func) const {
949 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
950 Asm->movn_d(getDest(), getSrc(0), getSrc(1));
951}
952
953template <> void InstMIPS32Movn_s::emitIAS(const Cfg *Func) const {
954 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
955 Asm->movn_s(getDest(), getSrc(0), getSrc(1));
956}
957
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700958template <> void InstMIPS32Movt::emitIAS(const Cfg *Func) const {
959 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Jaydeep Patild8954472016-09-21 06:24:41 -0700960 Asm->movt(getDest(), getSrc(1), getSrc(2));
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700961}
962
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700963template <> void InstMIPS32Movz_d::emitIAS(const Cfg *Func) const {
964 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
965 Asm->movz_d(getDest(), getSrc(0), getSrc(1));
966}
967
968template <> void InstMIPS32Movz_s::emitIAS(const Cfg *Func) const {
969 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
970 Asm->movz_s(getDest(), getSrc(0), getSrc(1));
971}
972
973template <> void InstMIPS32Mtc1::emitIAS(const Cfg *Func) const {
974 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
975 Asm->mtc1(getDest(), getSrc(0));
976}
977
978template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const {
979 if (!BuildDefs::dump())
980 return;
981 emitUnaryopGPRTLoHi(Opcode, this, Func);
982}
983
984template <> void InstMIPS32Mthi::emit(const Cfg *Func) const {
985 if (!BuildDefs::dump())
986 return;
987 emitUnaryopGPRTLoHi(Opcode, this, Func);
988}
989
990template <> void InstMIPS32Mul_d::emitIAS(const Cfg *Func) const {
991 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
992 Asm->mul_d(getDest(), getSrc(0), getSrc(1));
993}
994
995template <> void InstMIPS32Mul_s::emitIAS(const Cfg *Func) const {
996 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
997 Asm->mul_s(getDest(), getSrc(0), getSrc(1));
998}
999
1000template <> void InstMIPS32Mult::emit(const Cfg *Func) const {
1001 if (!BuildDefs::dump())
1002 return;
1003 emitThreeAddrLoHi(Opcode, this, Func);
1004}
1005
1006template <> void InstMIPS32Multu::emit(const Cfg *Func) const {
1007 if (!BuildDefs::dump())
1008 return;
1009 emitThreeAddrLoHi(Opcode, this, Func);
1010}
1011
Srdjan Obucinacadda792016-09-22 11:24:44 -07001012template <> void InstMIPS32Nor::emitIAS(const Cfg *Func) const {
1013 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1014 Asm->nor(getDest(), getSrc(0), getSrc(1));
1015}
1016
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001017template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const {
1018 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1019 Asm->or_(getDest(), getSrc(0), getSrc(1));
1020}
1021
1022template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const {
1023 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1024 Asm->ori(getDest(), getSrc(0), Imm);
1025}
1026
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001027template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const {
1028 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1029 Asm->sll(getDest(), getSrc(0), Imm);
1030}
1031
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001032template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const {
1033 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1034 Asm->slt(getDest(), getSrc(0), getSrc(1));
1035}
1036
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001037template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const {
1038 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1039 Asm->slti(getDest(), getSrc(0), Imm);
1040}
1041
1042template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const {
1043 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1044 Asm->sltiu(getDest(), getSrc(0), Imm);
1045}
1046
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001047template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const {
1048 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1049 Asm->sltu(getDest(), getSrc(0), getSrc(1));
1050}
1051
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001052template <> void InstMIPS32Sqrt_d::emitIAS(const Cfg *Func) const {
1053 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1054 Asm->sqrt_d(getDest(), getSrc(0));
1055}
1056
1057template <> void InstMIPS32Sqrt_s::emitIAS(const Cfg *Func) const {
1058 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1059 Asm->sqrt_s(getDest(), getSrc(0));
1060}
1061
1062template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const {
1063 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1064 Asm->sra(getDest(), getSrc(0), Imm);
1065}
1066
1067template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const {
1068 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1069 Asm->srl(getDest(), getSrc(0), Imm);
1070}
1071
1072template <> void InstMIPS32Sub_d::emitIAS(const Cfg *Func) const {
1073 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1074 Asm->sub_d(getDest(), getSrc(0), getSrc(1));
1075}
1076
1077template <> void InstMIPS32Sub_s::emitIAS(const Cfg *Func) const {
1078 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1079 Asm->sub_s(getDest(), getSrc(0), getSrc(1));
1080}
1081
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001082template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const {
1083 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1084 auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(1));
1085 ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
1086 uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
1087 Asm->sw(getSrc(0), Mem->getBase(), Imm);
1088}
1089
Srdjan Obucina3b61d702016-09-20 06:49:52 -07001090template <> void InstMIPS32Teq::emitIAS(const Cfg *Func) const {
1091 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1092 Asm->teq(getSrc(0), getSrc(1), getTrapCode());
1093}
1094
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001095template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const {
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001096 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001097 Asm->trunc_l_d(getDest(), getSrc(0));
1098}
1099
1100template <> void InstMIPS32Trunc_l_s::emitIAS(const Cfg *Func) const {
1101 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1102 Asm->trunc_l_s(getDest(), getSrc(0));
1103}
1104
1105template <> void InstMIPS32Trunc_w_d::emitIAS(const Cfg *Func) const {
1106 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1107 Asm->trunc_w_d(getDest(), getSrc(0));
1108}
1109
1110template <> void InstMIPS32Trunc_w_s::emitIAS(const Cfg *Func) const {
1111 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1112 Asm->trunc_w_s(getDest(), getSrc(0));
1113}
1114
1115template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const {
1116 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1117 Asm->xor_(getDest(), getSrc(0), getSrc(1));
1118}
1119
1120template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const {
1121 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1122 Asm->xori(getDest(), getSrc(0), Imm);
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001123}
1124
John Porto4a566862016-01-04 09:33:41 -08001125} // end of namespace MIPS32
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001126} // end of namespace Ice