blob: 938d388afd7d27f69006a41a23a0b6981f191adb [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 {
Jaydeep Patil58eeedf2016-09-26 20:48:18 -0700276 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
277 Asm->bindLocalLabel(this, Number);
Reed Kotler3fe4b572016-02-23 18:59:43 -0800278}
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
Sagar Thakurb001cc42016-10-11 23:36:01 -0700286InstMIPS32Mov::InstMIPS32Mov(Cfg *Func, Variable *Dest, Operand *Src,
287 Operand *Src2)
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700288 : InstMIPS32(Func, InstMIPS32::Mov, 2, Dest) {
289 auto *Dest64 = llvm::dyn_cast<Variable64On32>(Dest);
290 auto *Src64 = llvm::dyn_cast<Variable64On32>(Src);
291
292 assert(Dest64 == nullptr || Src64 == nullptr);
293
Sagar Thakurb001cc42016-10-11 23:36:01 -0700294 if (Dest->getType() == IceType_f64 && Src2 != nullptr) {
295 addSource(Src);
296 addSource(Src2);
297 return;
298 }
299
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700300 if (Dest64 != nullptr) {
301 // this-> is needed below because there is a parameter named Dest.
302 this->Dest = Dest64->getLo();
303 DestHi = Dest64->getHi();
304 }
305
306 if (Src64 == nullptr) {
307 addSource(Src);
308 } else {
309 addSource(Src64->getLo());
310 addSource(Src64->getHi());
311 }
312}
313
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700314InstMIPS32Ret::InstMIPS32Ret(Cfg *Func, Variable *RA, Variable *Source)
315 : InstMIPS32(Func, InstMIPS32::Ret, Source ? 2 : 1, nullptr) {
316 addSource(RA);
317 if (Source)
318 addSource(Source);
319}
320
Jan Voung3469b022015-07-09 10:32:31 -0700321// ======================== Dump routines ======================== //
322
323void InstMIPS32::dump(const Cfg *Func) const {
324 if (!BuildDefs::dump())
325 return;
326 Ostream &Str = Func->getContext()->getStrDump();
327 Str << "[MIPS32] ";
328 Inst::dump(Func);
329}
330
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700331void OperandMIPS32Mem::emit(const Cfg *Func) const {
332 if (!BuildDefs::dump())
333 return;
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700334 Ostream &Str = Func->getContext()->getStrEmit();
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700335 Operand *Offset = getOffset();
336 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) {
Mohit Bhakkad6a661ce2016-07-13 07:32:37 -0700337 Str << "(";
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700338 CR->emitWithoutPrefix(Func->getTarget());
Mohit Bhakkad6a661ce2016-07-13 07:32:37 -0700339 Str << ")";
Mohit Bhakkadd1e97772016-07-07 05:07:35 -0700340 } else
341 Offset->emit(Func);
Mohit Bhakkadf3bc5cf2016-05-31 11:19:03 -0700342 Str << "(";
343 getBase()->emit(Func);
344 Str << ")";
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700345}
346
347void InstMIPS32::emitUnaryopGPR(const char *Opcode, const InstMIPS32 *Inst,
348 const Cfg *Func) {
349 if (!BuildDefs::dump())
350 return;
351 Ostream &Str = Func->getContext()->getStrEmit();
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700352 Str << "\t" << Opcode << "\t";
353 Inst->getDest()->emit(Func);
354 Str << ", ";
355 Inst->getSrc(0)->emit(Func);
356}
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800357void InstMIPS32::emitUnaryopGPRFLoHi(const char *Opcode, const InstMIPS32 *Inst,
358 const Cfg *Func) {
359 if (!BuildDefs::dump())
360 return;
361 Ostream &Str = Func->getContext()->getStrEmit();
362 Str << "\t" << Opcode << "\t";
363 Inst->getDest()->emit(Func);
364}
365
366void InstMIPS32::emitUnaryopGPRTLoHi(const char *Opcode, const InstMIPS32 *Inst,
367 const Cfg *Func) {
368 if (!BuildDefs::dump())
369 return;
370 Ostream &Str = Func->getContext()->getStrEmit();
371 Str << "\t" << Opcode << "\t";
372 Inst->getSrc(0)->emit(Func);
373}
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700374
Reed Kotler37af5b02015-11-05 17:07:19 -0800375void InstMIPS32::emitThreeAddr(const char *Opcode, const InstMIPS32 *Inst,
376 const Cfg *Func) {
377 if (!BuildDefs::dump())
378 return;
379 Ostream &Str = Func->getContext()->getStrEmit();
380 assert(Inst->getSrcSize() == 2);
381 Str << "\t" << Opcode << "\t";
382 Inst->getDest()->emit(Func);
383 Str << ", ";
384 Inst->getSrc(0)->emit(Func);
385 Str << ", ";
386 Inst->getSrc(1)->emit(Func);
387}
388
Srdjan Obucina2f593bb2016-05-27 14:40:32 -0700389void InstMIPS32::emitTwoAddr(const char *Opcode, const InstMIPS32 *Inst,
390 const Cfg *Func) {
391 if (!BuildDefs::dump())
392 return;
393 Ostream &Str = Func->getContext()->getStrEmit();
394 assert(Inst->getSrcSize() == 1);
395 Str << "\t" << Opcode << "\t";
396 Inst->getDest()->emit(Func);
397 Str << ", ";
398 Inst->getSrc(0)->emit(Func);
399}
400
Reed Kotlera80cdbc2016-02-19 22:03:29 -0800401void InstMIPS32::emitThreeAddrLoHi(const char *Opcode, const InstMIPS32 *Inst,
402 const Cfg *Func) {
403 if (!BuildDefs::dump())
404 return;
405 Ostream &Str = Func->getContext()->getStrEmit();
406 assert(Inst->getSrcSize() == 2);
407 Str << "\t" << Opcode << "\t";
408 Inst->getSrc(0)->emit(Func);
409 Str << ", ";
410 Inst->getSrc(1)->emit(Func);
411}
412
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700413void InstMIPS32Ret::emit(const Cfg *Func) const {
Jan Voung3469b022015-07-09 10:32:31 -0700414 if (!BuildDefs::dump())
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700415 return;
416 assert(getSrcSize() > 0);
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800417 auto *RA = llvm::cast<Variable>(getSrc(0));
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700418 assert(RA->hasReg());
419 assert(RA->getRegNum() == RegMIPS32::Reg_RA);
420 Ostream &Str = Func->getContext()->getStrEmit();
421 Str << "\t"
Jim Stichnoth6106df82015-12-16 06:17:58 -0800422 "jr"
423 "\t";
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700424 RA->emit(Func);
425}
426
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700427void InstMIPS32Br::emitIAS(const Cfg *Func) const {
428 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Jaydeep Patil58eeedf2016-09-26 20:48:18 -0700429 if (Label != nullptr) {
430 // Intra-block branches are of kind bcc
431 Asm->bcc(Predicate, getSrc(0), getSrc(1),
432 Asm->getOrCreateLocalLabel(Label->getNumber()));
433 } else if (isUnconditionalBranch()) {
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700434 Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
435 } else {
436 switch (Predicate) {
437 default:
438 break;
439 case CondMIPS32::EQ:
440 case CondMIPS32::NE:
441 Asm->bcc(Predicate, getSrc(0), getSrc(1),
442 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
443 break;
444 case CondMIPS32::EQZ:
445 case CondMIPS32::NEZ:
446 case CondMIPS32::LEZ:
447 case CondMIPS32::LTZ:
448 case CondMIPS32::GEZ:
449 case CondMIPS32::GTZ:
450 Asm->bzc(Predicate, getSrc(0),
451 Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()));
452 break;
453 }
Jaydeep Patil58eeedf2016-09-26 20:48:18 -0700454 if (getTargetTrue()) {
455 Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex()));
456 }
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700457 }
458}
459
Reed Kotler3fe4b572016-02-23 18:59:43 -0800460void InstMIPS32Br::emit(const Cfg *Func) const {
461 if (!BuildDefs::dump())
462 return;
463 Ostream &Str = Func->getContext()->getStrEmit();
464 Str << "\t"
Sagar Thakur5cce7612016-05-24 06:25:50 -0700465 "b" << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
Jaydeep Patil29823f12016-08-31 05:10:03 -0700466 if (Label != nullptr) {
467 getSrc(0)->emit(Func);
468 Str << ", ";
469 getSrc(1)->emit(Func);
470 Str << ", " << Label->getLabelName();
Reed Kotler3fe4b572016-02-23 18:59:43 -0800471 } else {
472 if (isUnconditionalBranch()) {
473 Str << getTargetFalse()->getAsmName();
474 } else {
Sagar Thakur5cce7612016-05-24 06:25:50 -0700475 switch (Predicate) {
476 default:
477 break;
478 case CondMIPS32::EQ:
479 case CondMIPS32::NE: {
480 getSrc(0)->emit(Func);
481 Str << ", ";
482 getSrc(1)->emit(Func);
483 Str << ", ";
484 break;
485 }
486 case CondMIPS32::EQZ:
487 case CondMIPS32::NEZ:
488 case CondMIPS32::LEZ:
489 case CondMIPS32::LTZ:
490 case CondMIPS32::GEZ:
491 case CondMIPS32::GTZ: {
492 getSrc(0)->emit(Func);
493 Str << ", ";
494 break;
495 }
496 }
497 Str << getTargetFalse()->getAsmName();
Jaydeep Patil13f0ca32016-08-26 13:27:40 -0700498 if (getTargetTrue()) {
499 Str << "\n\t"
500 << "b"
501 << "\t" << getTargetTrue()->getAsmName();
502 }
Sagar Thakur5cce7612016-05-24 06:25:50 -0700503 }
504 }
505}
506
507void InstMIPS32Br::dump(const Cfg *Func) const {
508 if (!BuildDefs::dump())
509 return;
510 Ostream &Str = Func->getContext()->getStrDump();
511 Str << "\t"
512 "b" << InstMIPS32CondAttributes[Predicate].EmitString << "\t";
513
Jaydeep Patil29823f12016-08-31 05:10:03 -0700514 if (Label != nullptr) {
515 getSrc(0)->dump(Func);
516 Str << ", ";
517 getSrc(1)->dump(Func);
518 Str << ", " << Label->getLabelName();
Sagar Thakur5cce7612016-05-24 06:25:50 -0700519 } else {
520 if (isUnconditionalBranch()) {
521 Str << getTargetFalse()->getAsmName();
522 } else {
523 dumpSources(Func);
524 Str << ", ";
525 Str << getTargetFalse()->getAsmName();
Jaydeep Patil13f0ca32016-08-26 13:27:40 -0700526 if (getTargetTrue()) {
527 Str << "\n\t"
528 << "b"
529 << "\t" << getTargetTrue()->getAsmName();
530 }
Reed Kotler3fe4b572016-02-23 18:59:43 -0800531 }
532 }
533}
534
Reed Kotler00e36042016-02-01 20:52:19 -0800535void InstMIPS32Call::emit(const Cfg *Func) const {
536 if (!BuildDefs::dump())
537 return;
538 Ostream &Str = Func->getContext()->getStrEmit();
539 assert(getSrcSize() == 1);
540 if (llvm::isa<ConstantInteger32>(getCallTarget())) {
541 // This shouldn't happen (typically have to copy the full 32-bits to a
542 // register and do an indirect jump).
543 llvm::report_fatal_error("MIPS2Call to ConstantInteger32");
544 } else if (const auto *CallTarget =
545 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) {
546 // Calls only have 24-bits, but the linker should insert veneers to extend
547 // the range if needed.
548 Str << "\t"
549 "jal"
550 "\t";
551 CallTarget->emitWithoutPrefix(Func->getTarget());
552 } else {
553 Str << "\t"
554 "jal"
555 "\t";
556 getCallTarget()->emit(Func);
557 }
558}
559
560void InstMIPS32Call::emitIAS(const Cfg *Func) const {
561 (void)Func;
562 llvm_unreachable("Not yet implemented");
563}
564
565void InstMIPS32Call::dump(const Cfg *Func) const {
566 if (!BuildDefs::dump())
567 return;
568 Ostream &Str = Func->getContext()->getStrDump();
569 if (getDest()) {
570 dumpDest(Func);
571 Str << " = ";
572 }
573 Str << "call ";
574 getCallTarget()->dump(Func);
575}
576
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700577void InstMIPS32Ret::emitIAS(const Cfg *Func) const {
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700578 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
579 auto *RA = llvm::cast<Variable>(getSrc(0));
580 assert(RA->hasReg());
581 assert(RA->getRegNum() == RegMIPS32::Reg_RA);
582 (void)RA;
583 Asm->ret();
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700584}
585
586void InstMIPS32Ret::dump(const Cfg *Func) const {
Jan Voung3469b022015-07-09 10:32:31 -0700587 if (!BuildDefs::dump())
Reed Kotlerd00d48d2015-07-08 09:49:07 -0700588 return;
589 Ostream &Str = Func->getContext()->getStrDump();
590 Type Ty = (getSrcSize() == 1 ? IceType_void : getSrc(0)->getType());
591 Str << "ret." << Ty << " ";
592 dumpSources(Func);
593}
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700594
595void InstMIPS32Mov::emit(const Cfg *Func) const {
596 if (!BuildDefs::dump())
597 return;
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700598
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700599 Ostream &Str = Func->getContext()->getStrEmit();
Reed Kotler37af5b02015-11-05 17:07:19 -0800600 Variable *Dest = getDest();
601 Operand *Src = getSrc(0);
Srdjan Obucina36847bd2016-07-06 15:58:07 -0700602 auto *SrcV = llvm::dyn_cast<Variable>(Src);
603
604 assert(!llvm::isa<Constant>(Src));
605
606 const char *ActualOpcode = nullptr;
607 const bool DestIsReg = Dest->hasReg();
Srdjan Obucina36847bd2016-07-06 15:58:07 -0700608 const bool SrcIsReg = (SrcV && SrcV->hasReg());
Srdjan Obucina36847bd2016-07-06 15:58:07 -0700609
610 // reg to reg
611 if (DestIsReg && SrcIsReg) {
Jaydeep Patild3297662016-09-13 22:52:27 -0700612 const Type DstType = Dest->getType();
613 const Type SrcType = Src->getType();
614
615 // move GP to/from FP
Srdjan Obucinad57ed5f2016-09-14 06:06:24 -0700616 if ((isScalarIntegerType(DstType) && isScalarFloatingType(SrcType)) ||
617 (isScalarFloatingType(DstType) && isScalarIntegerType(SrcType))) {
Jaydeep Patild3297662016-09-13 22:52:27 -0700618 if (isScalarFloatingType(DstType)) {
619 Str << "\t"
620 "mtc1"
621 "\t";
622 getSrc(0)->emit(Func);
623 Str << ", ";
624 getDest()->emit(Func);
625 return;
626 }
627 ActualOpcode = "mfc1";
628 } else {
629 switch (Dest->getType()) {
630 case IceType_f32:
631 ActualOpcode = "mov.s";
632 break;
633 case IceType_f64:
634 ActualOpcode = "mov.d";
635 break;
636 case IceType_i1:
637 case IceType_i8:
638 case IceType_i16:
639 case IceType_i32:
640 ActualOpcode = "move";
641 break;
642 default:
643 UnimplementedError(getFlags());
644 return;
645 }
Srdjan Obucina36847bd2016-07-06 15:58:07 -0700646 }
647
648 assert(ActualOpcode);
649 Str << "\t" << ActualOpcode << "\t";
650 getDest()->emit(Func);
651 Str << ", ";
652 getSrc(0)->emit(Func);
653 return;
Reed Kotler37af5b02015-11-05 17:07:19 -0800654 }
655
Jaydeep Patil1d0690b2016-09-04 07:19:08 -0700656 llvm::report_fatal_error("Invalid mov instruction. Dest or Src is memory.");
Jim Stichnothac8da5c2015-10-21 06:57:46 -0700657}
658
Sagar Thakurb001cc42016-10-11 23:36:01 -0700659// TODO(jaydeep.patil) Handle all types of operands in mov
660void InstMIPS32Mov::emitIAS(const Cfg *Func) const {
661 Variable *Dest = getDest();
662 Operand *Src = getSrc(0);
663 auto *SrcV = llvm::dyn_cast<Variable>(Src);
664 assert(!llvm::isa<Constant>(Src));
665 const bool DestIsReg = Dest->hasReg();
666 const bool SrcIsReg = (SrcV && SrcV->hasReg());
667
668 // reg to reg
669 if (DestIsReg && SrcIsReg) {
670 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
671 Asm->move(getDest(), getSrc(0));
672 return;
673 }
674 llvm_unreachable("Not yet implemented");
675}
676
677void InstMIPS32Mov::dump(const Cfg *Func) const {
678 if (!BuildDefs::dump())
679 return;
680 assert(getSrcSize() == 1 || getSrcSize() == 2);
681 Ostream &Str = Func->getContext()->getStrDump();
682 Variable *Dest = getDest();
683 Variable *DestHi = getDestHi();
684 Dest->dump(Func);
685 if (DestHi) {
686 Str << ", ";
687 DestHi->dump(Func);
688 }
689 dumpOpcode(Str, " = mov", getDest()->getType());
690 Str << " ";
691 dumpSources(Func);
692}
693
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700694template <> void InstMIPS32Abs_d::emitIAS(const Cfg *Func) const {
695 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
696 Asm->abs_d(getDest(), getSrc(0));
697}
698
699template <> void InstMIPS32Abs_s::emitIAS(const Cfg *Func) const {
700 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
701 Asm->abs_s(getDest(), getSrc(0));
702}
703
704template <> void InstMIPS32Add_d::emitIAS(const Cfg *Func) const {
705 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
706 Asm->add_d(getDest(), getSrc(0), getSrc(1));
707}
708
709template <> void InstMIPS32Add_s::emitIAS(const Cfg *Func) const {
710 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
711 Asm->add_s(getDest(), getSrc(0), getSrc(1));
712}
713
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700714template <> void InstMIPS32Addiu::emitIAS(const Cfg *Func) const {
715 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
716 Asm->addiu(getDest(), getSrc(0), Imm);
717}
718
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700719template <> void InstMIPS32Addu::emitIAS(const Cfg *Func) const {
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700720 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700721 Asm->addu(getDest(), getSrc(0), getSrc(1));
Jaydeep Patil135f5db2016-08-29 05:14:05 -0700722}
723
724template <> void InstMIPS32And::emitIAS(const Cfg *Func) const {
725 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
726 Asm->and_(getDest(), getSrc(0), getSrc(1));
727}
728
729template <> void InstMIPS32Andi::emitIAS(const Cfg *Func) const {
730 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
731 Asm->andi(getDest(), getSrc(0), Imm);
732}
733
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700734template <> void InstMIPS32C_eq_d::emitIAS(const Cfg *Func) const {
735 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
736 Asm->c_eq_d(getSrc(0), getSrc(1));
737}
738
739template <> void InstMIPS32C_eq_s::emitIAS(const Cfg *Func) const {
740 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
741 Asm->c_eq_s(getSrc(0), getSrc(1));
742}
743
744template <> void InstMIPS32C_ole_d::emitIAS(const Cfg *Func) const {
745 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
746 Asm->c_ole_d(getSrc(0), getSrc(1));
747}
748
749template <> void InstMIPS32C_ole_s::emitIAS(const Cfg *Func) const {
750 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
751 Asm->c_ole_s(getSrc(0), getSrc(1));
752}
753
754template <> void InstMIPS32C_olt_d::emitIAS(const Cfg *Func) const {
755 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
756 Asm->c_olt_d(getSrc(0), getSrc(1));
757}
758
759template <> void InstMIPS32C_olt_s::emitIAS(const Cfg *Func) const {
760 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
761 Asm->c_olt_s(getSrc(0), getSrc(1));
762}
763
764template <> void InstMIPS32C_ueq_d::emitIAS(const Cfg *Func) const {
765 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
766 Asm->c_ueq_d(getSrc(0), getSrc(1));
767}
768
769template <> void InstMIPS32C_ueq_s::emitIAS(const Cfg *Func) const {
770 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
771 Asm->c_ueq_s(getSrc(0), getSrc(1));
772}
773
774template <> void InstMIPS32C_ule_d::emitIAS(const Cfg *Func) const {
775 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
776 Asm->c_ule_d(getSrc(0), getSrc(1));
777}
778
779template <> void InstMIPS32C_ule_s::emitIAS(const Cfg *Func) const {
780 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
781 Asm->c_ule_s(getSrc(0), getSrc(1));
782}
783
784template <> void InstMIPS32C_ult_d::emitIAS(const Cfg *Func) const {
785 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
786 Asm->c_ult_d(getSrc(0), getSrc(1));
787}
788
789template <> void InstMIPS32C_ult_s::emitIAS(const Cfg *Func) const {
790 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
791 Asm->c_ult_s(getSrc(0), getSrc(1));
792}
793
794template <> void InstMIPS32C_un_d::emitIAS(const Cfg *Func) const {
795 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
796 Asm->c_un_d(getSrc(0), getSrc(1));
797}
798
799template <> void InstMIPS32C_un_s::emitIAS(const Cfg *Func) const {
800 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
801 Asm->c_un_s(getSrc(0), getSrc(1));
802}
803
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -0700804template <> void InstMIPS32Clz::emitIAS(const Cfg *Func) const {
805 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
806 Asm->clz(getDest(), getSrc(0));
807}
808
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700809template <> void InstMIPS32Cvt_d_l::emitIAS(const Cfg *Func) const {
810 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
811 Asm->cvt_d_l(getDest(), getSrc(0));
812}
813
814template <> void InstMIPS32Cvt_d_s::emitIAS(const Cfg *Func) const {
815 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
816 Asm->cvt_d_s(getDest(), getSrc(0));
817}
818
819template <> void InstMIPS32Cvt_d_w::emitIAS(const Cfg *Func) const {
820 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
821 Asm->cvt_d_w(getDest(), getSrc(0));
822}
823
824template <> void InstMIPS32Cvt_s_d::emitIAS(const Cfg *Func) const {
825 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
826 Asm->cvt_s_d(getDest(), getSrc(0));
827}
828
829template <> void InstMIPS32Cvt_s_l::emitIAS(const Cfg *Func) const {
830 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
831 Asm->cvt_s_l(getDest(), getSrc(0));
832}
833
834template <> void InstMIPS32Cvt_s_w::emitIAS(const Cfg *Func) const {
835 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
836 Asm->cvt_s_w(getDest(), getSrc(0));
837}
838
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700839template <> void InstMIPS32Div::emitIAS(const Cfg *Func) const {
840 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
841 Asm->div(getDest(), getSrc(0));
842}
843
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700844template <> void InstMIPS32Div_d::emitIAS(const Cfg *Func) const {
845 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
846 Asm->div_d(getDest(), getSrc(0), getSrc(1));
847}
848
849template <> void InstMIPS32Div_s::emitIAS(const Cfg *Func) const {
850 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
851 Asm->div_s(getDest(), getSrc(0), getSrc(1));
852}
853
Srdjan Obucina6163c622016-09-27 20:38:30 -0700854template <> void InstMIPS32Divu::emitIAS(const Cfg *Func) const {
855 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
856 Asm->divu(getDest(), getSrc(0));
857}
858
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700859template <> void InstMIPS32Lui::emitIAS(const Cfg *Func) const {
860 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
861 auto *C32 = llvm::dyn_cast<ConstantInteger32>(getSrc(0));
862 uint16_t Imm = static_cast<uint16_t>(C32->getValue());
863 Asm->lui(getDest(), Imm);
864}
865
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700866template <> void InstMIPS32Lw::emitIAS(const Cfg *Func) const {
867 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
868 auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(0));
869 ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
870 uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
871 Asm->lw(getDest(), Mem->getBase(), Imm);
872}
873
874template <> void InstMIPS32Mfc1::emitIAS(const Cfg *Func) const {
875 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
876 Asm->mfc1(getDest(), getSrc(0));
877}
878
879template <> void InstMIPS32Mflo::emit(const Cfg *Func) const {
880 if (!BuildDefs::dump())
881 return;
882 emitUnaryopGPRFLoHi(Opcode, this, Func);
883}
884
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700885template <> void InstMIPS32Mflo::emitIAS(const Cfg *Func) const {
886 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
887 Asm->mflo(getDest());
888}
889
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700890template <> void InstMIPS32Mfhi::emit(const Cfg *Func) const {
891 if (!BuildDefs::dump())
892 return;
893 emitUnaryopGPRFLoHi(Opcode, this, Func);
894}
895
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700896template <> void InstMIPS32Mfhi::emitIAS(const Cfg *Func) const {
897 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
898 Asm->mfhi(getDest());
899}
900
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700901template <> void InstMIPS32Mov_d::emitIAS(const Cfg *Func) const {
902 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
903 Asm->mov_d(getDest(), getSrc(0));
904}
905
906template <> void InstMIPS32Mov_s::emitIAS(const Cfg *Func) const {
907 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
908 Asm->mov_s(getDest(), getSrc(0));
909}
910
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700911template <> void InstMIPS32Movf::emitIAS(const Cfg *Func) const {
912 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700913 Asm->movf(getDest(), getSrc(0), getSrc(1));
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700914}
915
Srdjan Obucinad27ce3d2016-09-22 12:56:12 -0700916template <> void InstMIPS32Movn::emitIAS(const Cfg *Func) const {
917 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
918 Asm->movn(getDest(), getSrc(0), getSrc(1));
919}
920
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700921template <> void InstMIPS32Movn_d::emitIAS(const Cfg *Func) const {
922 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
923 Asm->movn_d(getDest(), getSrc(0), getSrc(1));
924}
925
926template <> void InstMIPS32Movn_s::emitIAS(const Cfg *Func) const {
927 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
928 Asm->movn_s(getDest(), getSrc(0), getSrc(1));
929}
930
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700931template <> void InstMIPS32Movt::emitIAS(const Cfg *Func) const {
932 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Stefan Maksimovicafe5fe22016-10-05 10:45:19 -0700933 Asm->movt(getDest(), getSrc(0), getSrc(1));
Srdjan Obucina8d16c1d2016-09-20 08:44:44 -0700934}
935
Srdjan Obucinab0f09fc2016-09-27 20:43:11 -0700936template <> void InstMIPS32Movz::emitIAS(const Cfg *Func) const {
937 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
938 Asm->movz(getDest(), getSrc(0), getSrc(1));
939}
940
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700941template <> void InstMIPS32Movz_d::emitIAS(const Cfg *Func) const {
942 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
943 Asm->movz_d(getDest(), getSrc(0), getSrc(1));
944}
945
946template <> void InstMIPS32Movz_s::emitIAS(const Cfg *Func) const {
947 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
948 Asm->movz_s(getDest(), getSrc(0), getSrc(1));
949}
950
Srdjan Obucina4c49b102016-09-26 20:12:17 -0700951template <> void InstMIPS32Mtc1::emit(const Cfg *Func) const {
952 if (!BuildDefs::dump())
953 return;
954 Ostream &Str = Func->getContext()->getStrEmit();
955 assert(getSrcSize() == 1);
956 Str << "\t" << Opcode << "\t";
957 getSrc(0)->emit(Func);
958 Str << ", ";
959 getDest()->emit(Func);
960}
961
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700962template <> void InstMIPS32Mtc1::emitIAS(const Cfg *Func) const {
963 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
964 Asm->mtc1(getDest(), getSrc(0));
965}
966
967template <> void InstMIPS32Mtlo::emit(const Cfg *Func) const {
968 if (!BuildDefs::dump())
969 return;
970 emitUnaryopGPRTLoHi(Opcode, this, Func);
971}
972
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700973template <> void InstMIPS32Mtlo::emitIAS(const Cfg *Func) const {
974 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
975 Asm->mtlo(getDest());
976}
977
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700978template <> void InstMIPS32Mthi::emit(const Cfg *Func) const {
979 if (!BuildDefs::dump())
980 return;
981 emitUnaryopGPRTLoHi(Opcode, this, Func);
982}
983
Srdjan Obucina623f8ce2016-09-26 20:03:20 -0700984template <> void InstMIPS32Mthi::emitIAS(const Cfg *Func) const {
985 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
986 Asm->mthi(getDest());
987}
988
989template <> void InstMIPS32Mul::emitIAS(const Cfg *Func) const {
990 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
991 Asm->mul(getDest(), getSrc(0), getSrc(1));
992}
993
Srdjan Obucina132ea7a2016-09-18 07:30:19 -0700994template <> void InstMIPS32Mul_d::emitIAS(const Cfg *Func) const {
995 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
996 Asm->mul_d(getDest(), getSrc(0), getSrc(1));
997}
998
999template <> void InstMIPS32Mul_s::emitIAS(const Cfg *Func) const {
1000 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1001 Asm->mul_s(getDest(), getSrc(0), getSrc(1));
1002}
1003
1004template <> void InstMIPS32Mult::emit(const Cfg *Func) const {
1005 if (!BuildDefs::dump())
1006 return;
1007 emitThreeAddrLoHi(Opcode, this, Func);
1008}
1009
1010template <> void InstMIPS32Multu::emit(const Cfg *Func) const {
1011 if (!BuildDefs::dump())
1012 return;
1013 emitThreeAddrLoHi(Opcode, this, Func);
1014}
1015
Srdjan Obucina623f8ce2016-09-26 20:03:20 -07001016template <> void InstMIPS32Multu::emitIAS(const Cfg *Func) const {
1017 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1018 Asm->multu(getDest(), getSrc(0));
1019}
1020
Srdjan Obucinacadda792016-09-22 11:24:44 -07001021template <> void InstMIPS32Nor::emitIAS(const Cfg *Func) const {
1022 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1023 Asm->nor(getDest(), getSrc(0), getSrc(1));
1024}
1025
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001026template <> void InstMIPS32Or::emitIAS(const Cfg *Func) const {
1027 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1028 Asm->or_(getDest(), getSrc(0), getSrc(1));
1029}
1030
1031template <> void InstMIPS32Ori::emitIAS(const Cfg *Func) const {
1032 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1033 Asm->ori(getDest(), getSrc(0), Imm);
1034}
1035
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001036template <> void InstMIPS32Sll::emitIAS(const Cfg *Func) const {
1037 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1038 Asm->sll(getDest(), getSrc(0), Imm);
1039}
1040
Srdjan Obucina623f8ce2016-09-26 20:03:20 -07001041template <> void InstMIPS32Sllv::emitIAS(const Cfg *Func) const {
1042 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1043 Asm->sllv(getDest(), getSrc(0), getSrc(1));
1044}
1045
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001046template <> void InstMIPS32Slt::emitIAS(const Cfg *Func) const {
1047 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1048 Asm->slt(getDest(), getSrc(0), getSrc(1));
1049}
1050
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001051template <> void InstMIPS32Slti::emitIAS(const Cfg *Func) const {
1052 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1053 Asm->slti(getDest(), getSrc(0), Imm);
1054}
1055
1056template <> void InstMIPS32Sltiu::emitIAS(const Cfg *Func) const {
1057 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1058 Asm->sltiu(getDest(), getSrc(0), Imm);
1059}
1060
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001061template <> void InstMIPS32Sltu::emitIAS(const Cfg *Func) const {
1062 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1063 Asm->sltu(getDest(), getSrc(0), getSrc(1));
1064}
1065
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001066template <> void InstMIPS32Sqrt_d::emitIAS(const Cfg *Func) const {
1067 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1068 Asm->sqrt_d(getDest(), getSrc(0));
1069}
1070
1071template <> void InstMIPS32Sqrt_s::emitIAS(const Cfg *Func) const {
1072 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1073 Asm->sqrt_s(getDest(), getSrc(0));
1074}
1075
1076template <> void InstMIPS32Sra::emitIAS(const Cfg *Func) const {
1077 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1078 Asm->sra(getDest(), getSrc(0), Imm);
1079}
1080
Srdjan Obucinafe93fdd2016-09-28 06:38:44 -07001081template <> void InstMIPS32Srav::emitIAS(const Cfg *Func) const {
1082 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1083 Asm->srav(getDest(), getSrc(0), getSrc(1));
1084}
1085
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001086template <> void InstMIPS32Srl::emitIAS(const Cfg *Func) const {
1087 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1088 Asm->srl(getDest(), getSrc(0), Imm);
1089}
1090
Srdjan Obucina623f8ce2016-09-26 20:03:20 -07001091template <> void InstMIPS32Srlv::emitIAS(const Cfg *Func) const {
1092 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1093 Asm->srlv(getDest(), getSrc(0), getSrc(1));
1094}
1095
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001096template <> void InstMIPS32Sub_d::emitIAS(const Cfg *Func) const {
1097 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1098 Asm->sub_d(getDest(), getSrc(0), getSrc(1));
1099}
1100
1101template <> void InstMIPS32Sub_s::emitIAS(const Cfg *Func) const {
1102 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1103 Asm->sub_s(getDest(), getSrc(0), getSrc(1));
1104}
1105
Srdjan Obucina0a7f99d2016-09-23 06:59:50 -07001106template <> void InstMIPS32Subu::emitIAS(const Cfg *Func) const {
1107 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1108 Asm->subu(getDest(), getSrc(0), getSrc(1));
1109}
1110
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001111template <> void InstMIPS32Sw::emitIAS(const Cfg *Func) const {
1112 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1113 auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(getSrc(1));
1114 ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset());
1115 uint32_t Imm = static_cast<uint32_t>(Offset->getValue());
1116 Asm->sw(getSrc(0), Mem->getBase(), Imm);
1117}
1118
Srdjan Obucina3b61d702016-09-20 06:49:52 -07001119template <> void InstMIPS32Teq::emitIAS(const Cfg *Func) const {
1120 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1121 Asm->teq(getSrc(0), getSrc(1), getTrapCode());
1122}
1123
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001124template <> void InstMIPS32Trunc_l_d::emitIAS(const Cfg *Func) const {
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001125 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
Srdjan Obucina132ea7a2016-09-18 07:30:19 -07001126 Asm->trunc_l_d(getDest(), getSrc(0));
1127}
1128
1129template <> void InstMIPS32Trunc_l_s::emitIAS(const Cfg *Func) const {
1130 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1131 Asm->trunc_l_s(getDest(), getSrc(0));
1132}
1133
1134template <> void InstMIPS32Trunc_w_d::emitIAS(const Cfg *Func) const {
1135 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1136 Asm->trunc_w_d(getDest(), getSrc(0));
1137}
1138
1139template <> void InstMIPS32Trunc_w_s::emitIAS(const Cfg *Func) const {
1140 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1141 Asm->trunc_w_s(getDest(), getSrc(0));
1142}
1143
1144template <> void InstMIPS32Xor::emitIAS(const Cfg *Func) const {
1145 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1146 Asm->xor_(getDest(), getSrc(0), getSrc(1));
1147}
1148
1149template <> void InstMIPS32Xori::emitIAS(const Cfg *Func) const {
1150 auto *Asm = Func->getAssembler<MIPS32::AssemblerMIPS32>();
1151 Asm->xori(getDest(), getSrc(0), Imm);
Jaydeep Patil135f5db2016-08-29 05:14:05 -07001152}
1153
John Porto4a566862016-01-04 09:33:41 -08001154} // end of namespace MIPS32
Jim Stichnothac8da5c2015-10-21 06:57:46 -07001155} // end of namespace Ice