xref: /aosp_15_r20/external/capstone/arch/Mips/MipsInstPrinter.c (revision 9a0e4156d50a75a99ec4f1653a0e9602a5d45c18)
1*9a0e4156SSadaf Ebrahimi //===-- MipsInstPrinter.cpp - Convert Mips MCInst to assembly syntax ------===//
2*9a0e4156SSadaf Ebrahimi //
3*9a0e4156SSadaf Ebrahimi //                     The LLVM Compiler Infrastructure
4*9a0e4156SSadaf Ebrahimi //
5*9a0e4156SSadaf Ebrahimi // This file is distributed under the University of Illinois Open Source
6*9a0e4156SSadaf Ebrahimi // License. See LICENSE.TXT for details.
7*9a0e4156SSadaf Ebrahimi //
8*9a0e4156SSadaf Ebrahimi //===----------------------------------------------------------------------===//
9*9a0e4156SSadaf Ebrahimi //
10*9a0e4156SSadaf Ebrahimi // This class prints an Mips MCInst to a .s file.
11*9a0e4156SSadaf Ebrahimi //
12*9a0e4156SSadaf Ebrahimi //===----------------------------------------------------------------------===//
13*9a0e4156SSadaf Ebrahimi 
14*9a0e4156SSadaf Ebrahimi /* Capstone Disassembly Engine */
15*9a0e4156SSadaf Ebrahimi /* By Nguyen Anh Quynh <[email protected]>, 2013-2015 */
16*9a0e4156SSadaf Ebrahimi 
17*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_MIPS
18*9a0e4156SSadaf Ebrahimi 
19*9a0e4156SSadaf Ebrahimi #include <capstone/platform.h>
20*9a0e4156SSadaf Ebrahimi #include <stdlib.h>
21*9a0e4156SSadaf Ebrahimi #include <stdio.h>	// debug
22*9a0e4156SSadaf Ebrahimi #include <string.h>
23*9a0e4156SSadaf Ebrahimi 
24*9a0e4156SSadaf Ebrahimi #include "MipsInstPrinter.h"
25*9a0e4156SSadaf Ebrahimi #include "../../MCInst.h"
26*9a0e4156SSadaf Ebrahimi #include "../../utils.h"
27*9a0e4156SSadaf Ebrahimi #include "../../SStream.h"
28*9a0e4156SSadaf Ebrahimi #include "../../MCRegisterInfo.h"
29*9a0e4156SSadaf Ebrahimi #include "MipsMapping.h"
30*9a0e4156SSadaf Ebrahimi 
31*9a0e4156SSadaf Ebrahimi #include "MipsInstPrinter.h"
32*9a0e4156SSadaf Ebrahimi 
33*9a0e4156SSadaf Ebrahimi static void printUnsignedImm(MCInst *MI, int opNum, SStream *O);
34*9a0e4156SSadaf Ebrahimi static char *printAliasInstr(MCInst *MI, SStream *O, void *info);
35*9a0e4156SSadaf Ebrahimi static char *printAlias(MCInst *MI, SStream *OS);
36*9a0e4156SSadaf Ebrahimi 
37*9a0e4156SSadaf Ebrahimi // These enumeration declarations were originally in MipsInstrInfo.h but
38*9a0e4156SSadaf Ebrahimi // had to be moved here to avoid circular dependencies between
39*9a0e4156SSadaf Ebrahimi // LLVMMipsCodeGen and LLVMMipsAsmPrinter.
40*9a0e4156SSadaf Ebrahimi 
41*9a0e4156SSadaf Ebrahimi // Mips Condition Codes
42*9a0e4156SSadaf Ebrahimi typedef enum Mips_CondCode {
43*9a0e4156SSadaf Ebrahimi 	// To be used with float branch True
44*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_F,
45*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_UN,
46*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_OEQ,
47*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_UEQ,
48*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_OLT,
49*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_ULT,
50*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_OLE,
51*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_ULE,
52*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_SF,
53*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_NGLE,
54*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_SEQ,
55*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_NGL,
56*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_LT,
57*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_NGE,
58*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_LE,
59*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_NGT,
60*9a0e4156SSadaf Ebrahimi 
61*9a0e4156SSadaf Ebrahimi 	// To be used with float branch False
62*9a0e4156SSadaf Ebrahimi 	// This conditions have the same mnemonic as the
63*9a0e4156SSadaf Ebrahimi 	// above ones, but are used with a branch False;
64*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_T,
65*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_OR,
66*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_UNE,
67*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_ONE,
68*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_UGE,
69*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_OGE,
70*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_UGT,
71*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_OGT,
72*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_ST,
73*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_GLE,
74*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_SNE,
75*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_GL,
76*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_NLT,
77*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_GE,
78*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_NLE,
79*9a0e4156SSadaf Ebrahimi 	Mips_FCOND_GT
80*9a0e4156SSadaf Ebrahimi } Mips_CondCode;
81*9a0e4156SSadaf Ebrahimi 
82*9a0e4156SSadaf Ebrahimi #define GET_INSTRINFO_ENUM
83*9a0e4156SSadaf Ebrahimi #include "MipsGenInstrInfo.inc"
84*9a0e4156SSadaf Ebrahimi 
85*9a0e4156SSadaf Ebrahimi static const char *getRegisterName(unsigned RegNo);
86*9a0e4156SSadaf Ebrahimi static void printInstruction(MCInst *MI, SStream *O, const MCRegisterInfo *MRI);
87*9a0e4156SSadaf Ebrahimi 
set_mem_access(MCInst * MI,bool status)88*9a0e4156SSadaf Ebrahimi static void set_mem_access(MCInst *MI, bool status)
89*9a0e4156SSadaf Ebrahimi {
90*9a0e4156SSadaf Ebrahimi 	MI->csh->doing_mem = status;
91*9a0e4156SSadaf Ebrahimi 
92*9a0e4156SSadaf Ebrahimi 	if (MI->csh->detail != CS_OPT_ON)
93*9a0e4156SSadaf Ebrahimi 		return;
94*9a0e4156SSadaf Ebrahimi 
95*9a0e4156SSadaf Ebrahimi 	if (status) {
96*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].type = MIPS_OP_MEM;
97*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].mem.base = MIPS_REG_INVALID;
98*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].mem.disp = 0;
99*9a0e4156SSadaf Ebrahimi 	} else {
100*9a0e4156SSadaf Ebrahimi 		// done, create the next operand slot
101*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->mips.op_count++;
102*9a0e4156SSadaf Ebrahimi 	}
103*9a0e4156SSadaf Ebrahimi }
104*9a0e4156SSadaf Ebrahimi 
isReg(MCInst * MI,unsigned OpNo,unsigned R)105*9a0e4156SSadaf Ebrahimi static bool isReg(MCInst *MI, unsigned OpNo, unsigned R)
106*9a0e4156SSadaf Ebrahimi {
107*9a0e4156SSadaf Ebrahimi 	return (MCOperand_isReg(MCInst_getOperand(MI, OpNo)) &&
108*9a0e4156SSadaf Ebrahimi 			MCOperand_getReg(MCInst_getOperand(MI, OpNo)) == R);
109*9a0e4156SSadaf Ebrahimi }
110*9a0e4156SSadaf Ebrahimi 
MipsFCCToString(Mips_CondCode CC)111*9a0e4156SSadaf Ebrahimi static const char* MipsFCCToString(Mips_CondCode CC)
112*9a0e4156SSadaf Ebrahimi {
113*9a0e4156SSadaf Ebrahimi 	switch (CC) {
114*9a0e4156SSadaf Ebrahimi 		default: return 0;	// never reach
115*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_F:
116*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_T:   return "f";
117*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_UN:
118*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_OR:  return "un";
119*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_OEQ:
120*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_UNE: return "eq";
121*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_UEQ:
122*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_ONE: return "ueq";
123*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_OLT:
124*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_UGE: return "olt";
125*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_ULT:
126*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_OGE: return "ult";
127*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_OLE:
128*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_UGT: return "ole";
129*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_ULE:
130*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_OGT: return "ule";
131*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_SF:
132*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_ST:  return "sf";
133*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_NGLE:
134*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_GLE: return "ngle";
135*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_SEQ:
136*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_SNE: return "seq";
137*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_NGL:
138*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_GL:  return "ngl";
139*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_LT:
140*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_NLT: return "lt";
141*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_NGE:
142*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_GE:  return "nge";
143*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_LE:
144*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_NLE: return "le";
145*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_NGT:
146*9a0e4156SSadaf Ebrahimi 		case Mips_FCOND_GT:  return "ngt";
147*9a0e4156SSadaf Ebrahimi 	}
148*9a0e4156SSadaf Ebrahimi }
149*9a0e4156SSadaf Ebrahimi 
printRegName(SStream * OS,unsigned RegNo)150*9a0e4156SSadaf Ebrahimi static void printRegName(SStream *OS, unsigned RegNo)
151*9a0e4156SSadaf Ebrahimi {
152*9a0e4156SSadaf Ebrahimi 	SStream_concat(OS, "$%s", getRegisterName(RegNo));
153*9a0e4156SSadaf Ebrahimi }
154*9a0e4156SSadaf Ebrahimi 
Mips_printInst(MCInst * MI,SStream * O,void * info)155*9a0e4156SSadaf Ebrahimi void Mips_printInst(MCInst *MI, SStream *O, void *info)
156*9a0e4156SSadaf Ebrahimi {
157*9a0e4156SSadaf Ebrahimi 	char *mnem;
158*9a0e4156SSadaf Ebrahimi 
159*9a0e4156SSadaf Ebrahimi 	switch (MCInst_getOpcode(MI)) {
160*9a0e4156SSadaf Ebrahimi 		default: break;
161*9a0e4156SSadaf Ebrahimi 		case Mips_Save16:
162*9a0e4156SSadaf Ebrahimi 		case Mips_SaveX16:
163*9a0e4156SSadaf Ebrahimi 		case Mips_Restore16:
164*9a0e4156SSadaf Ebrahimi 		case Mips_RestoreX16:
165*9a0e4156SSadaf Ebrahimi 			return;
166*9a0e4156SSadaf Ebrahimi 	}
167*9a0e4156SSadaf Ebrahimi 
168*9a0e4156SSadaf Ebrahimi 	// Try to print any aliases first.
169*9a0e4156SSadaf Ebrahimi 	mnem = printAliasInstr(MI, O, info);
170*9a0e4156SSadaf Ebrahimi 	if (!mnem) {
171*9a0e4156SSadaf Ebrahimi 		mnem = printAlias(MI, O);
172*9a0e4156SSadaf Ebrahimi 		if (!mnem) {
173*9a0e4156SSadaf Ebrahimi 			printInstruction(MI, O, NULL);
174*9a0e4156SSadaf Ebrahimi 		}
175*9a0e4156SSadaf Ebrahimi 	}
176*9a0e4156SSadaf Ebrahimi 
177*9a0e4156SSadaf Ebrahimi 	if (mnem) {
178*9a0e4156SSadaf Ebrahimi 		// fixup instruction id due to the change in alias instruction
179*9a0e4156SSadaf Ebrahimi 		MCInst_setOpcodePub(MI, Mips_map_insn(mnem));
180*9a0e4156SSadaf Ebrahimi 		cs_mem_free(mnem);
181*9a0e4156SSadaf Ebrahimi 	}
182*9a0e4156SSadaf Ebrahimi }
183*9a0e4156SSadaf Ebrahimi 
printOperand(MCInst * MI,unsigned OpNo,SStream * O)184*9a0e4156SSadaf Ebrahimi static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
185*9a0e4156SSadaf Ebrahimi {
186*9a0e4156SSadaf Ebrahimi 	MCOperand *Op;
187*9a0e4156SSadaf Ebrahimi 
188*9a0e4156SSadaf Ebrahimi 	if (OpNo >= MI->size)
189*9a0e4156SSadaf Ebrahimi 		return;
190*9a0e4156SSadaf Ebrahimi 
191*9a0e4156SSadaf Ebrahimi 	Op = MCInst_getOperand(MI, OpNo);
192*9a0e4156SSadaf Ebrahimi 	if (MCOperand_isReg(Op)) {
193*9a0e4156SSadaf Ebrahimi 		unsigned int reg = MCOperand_getReg(Op);
194*9a0e4156SSadaf Ebrahimi 		printRegName(O, reg);
195*9a0e4156SSadaf Ebrahimi 		reg = Mips_map_register(reg);
196*9a0e4156SSadaf Ebrahimi 		if (MI->csh->detail) {
197*9a0e4156SSadaf Ebrahimi 			if (MI->csh->doing_mem) {
198*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].mem.base = reg;
199*9a0e4156SSadaf Ebrahimi 			} else {
200*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].type = MIPS_OP_REG;
201*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].reg = reg;
202*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->mips.op_count++;
203*9a0e4156SSadaf Ebrahimi 			}
204*9a0e4156SSadaf Ebrahimi 		}
205*9a0e4156SSadaf Ebrahimi 	} else if (MCOperand_isImm(Op)) {
206*9a0e4156SSadaf Ebrahimi 		int64_t imm = MCOperand_getImm(Op);
207*9a0e4156SSadaf Ebrahimi 		if (MI->csh->doing_mem) {
208*9a0e4156SSadaf Ebrahimi 			if (imm) {	// only print Imm offset if it is not 0
209*9a0e4156SSadaf Ebrahimi 				printInt64(O, imm);
210*9a0e4156SSadaf Ebrahimi 			}
211*9a0e4156SSadaf Ebrahimi 			if (MI->csh->detail)
212*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].mem.disp = imm;
213*9a0e4156SSadaf Ebrahimi 		} else {
214*9a0e4156SSadaf Ebrahimi 			printInt64(O, imm);
215*9a0e4156SSadaf Ebrahimi 
216*9a0e4156SSadaf Ebrahimi 			if (MI->csh->detail) {
217*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].type = MIPS_OP_IMM;
218*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].imm = imm;
219*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->mips.op_count++;
220*9a0e4156SSadaf Ebrahimi 			}
221*9a0e4156SSadaf Ebrahimi 		}
222*9a0e4156SSadaf Ebrahimi 	}
223*9a0e4156SSadaf Ebrahimi }
224*9a0e4156SSadaf Ebrahimi 
printUnsignedImm(MCInst * MI,int opNum,SStream * O)225*9a0e4156SSadaf Ebrahimi static void printUnsignedImm(MCInst *MI, int opNum, SStream *O)
226*9a0e4156SSadaf Ebrahimi {
227*9a0e4156SSadaf Ebrahimi 	MCOperand *MO = MCInst_getOperand(MI, opNum);
228*9a0e4156SSadaf Ebrahimi 	if (MCOperand_isImm(MO)) {
229*9a0e4156SSadaf Ebrahimi 		int64_t imm = MCOperand_getImm(MO);
230*9a0e4156SSadaf Ebrahimi 		printInt64(O, imm);
231*9a0e4156SSadaf Ebrahimi 
232*9a0e4156SSadaf Ebrahimi 		if (MI->csh->detail) {
233*9a0e4156SSadaf Ebrahimi 			MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].type = MIPS_OP_IMM;
234*9a0e4156SSadaf Ebrahimi 			MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].imm = (unsigned short int)imm;
235*9a0e4156SSadaf Ebrahimi 			MI->flat_insn->detail->mips.op_count++;
236*9a0e4156SSadaf Ebrahimi 		}
237*9a0e4156SSadaf Ebrahimi 	} else
238*9a0e4156SSadaf Ebrahimi 		printOperand(MI, opNum, O);
239*9a0e4156SSadaf Ebrahimi }
240*9a0e4156SSadaf Ebrahimi 
printUnsignedImm8(MCInst * MI,int opNum,SStream * O)241*9a0e4156SSadaf Ebrahimi static void printUnsignedImm8(MCInst *MI, int opNum, SStream *O)
242*9a0e4156SSadaf Ebrahimi {
243*9a0e4156SSadaf Ebrahimi 	MCOperand *MO = MCInst_getOperand(MI, opNum);
244*9a0e4156SSadaf Ebrahimi 	if (MCOperand_isImm(MO)) {
245*9a0e4156SSadaf Ebrahimi 		uint8_t imm = (uint8_t)MCOperand_getImm(MO);
246*9a0e4156SSadaf Ebrahimi 		if (imm > HEX_THRESHOLD)
247*9a0e4156SSadaf Ebrahimi 			SStream_concat(O, "0x%x", imm);
248*9a0e4156SSadaf Ebrahimi 		else
249*9a0e4156SSadaf Ebrahimi 			SStream_concat(O, "%u", imm);
250*9a0e4156SSadaf Ebrahimi 		if (MI->csh->detail) {
251*9a0e4156SSadaf Ebrahimi 			MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].type = MIPS_OP_IMM;
252*9a0e4156SSadaf Ebrahimi 			MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].imm = imm;
253*9a0e4156SSadaf Ebrahimi 			MI->flat_insn->detail->mips.op_count++;
254*9a0e4156SSadaf Ebrahimi 		}
255*9a0e4156SSadaf Ebrahimi 	} else
256*9a0e4156SSadaf Ebrahimi 		printOperand(MI, opNum, O);
257*9a0e4156SSadaf Ebrahimi }
258*9a0e4156SSadaf Ebrahimi 
printMemOperand(MCInst * MI,int opNum,SStream * O)259*9a0e4156SSadaf Ebrahimi static void printMemOperand(MCInst *MI, int opNum, SStream *O)
260*9a0e4156SSadaf Ebrahimi {
261*9a0e4156SSadaf Ebrahimi 	// Load/Store memory operands -- imm($reg)
262*9a0e4156SSadaf Ebrahimi 	// If PIC target the target is loaded as the
263*9a0e4156SSadaf Ebrahimi 	// pattern lw $25,%call16($28)
264*9a0e4156SSadaf Ebrahimi 
265*9a0e4156SSadaf Ebrahimi 	// opNum can be invalid if instruction had reglist as operand.
266*9a0e4156SSadaf Ebrahimi 	// MemOperand is always last operand of instruction (base + offset).
267*9a0e4156SSadaf Ebrahimi 	switch (MCInst_getOpcode(MI)) {
268*9a0e4156SSadaf Ebrahimi 		default:
269*9a0e4156SSadaf Ebrahimi 			break;
270*9a0e4156SSadaf Ebrahimi 		case Mips_SWM32_MM:
271*9a0e4156SSadaf Ebrahimi 		case Mips_LWM32_MM:
272*9a0e4156SSadaf Ebrahimi 		case Mips_SWM16_MM:
273*9a0e4156SSadaf Ebrahimi 		case Mips_LWM16_MM:
274*9a0e4156SSadaf Ebrahimi 			opNum = MCInst_getNumOperands(MI) - 2;
275*9a0e4156SSadaf Ebrahimi 			break;
276*9a0e4156SSadaf Ebrahimi 	}
277*9a0e4156SSadaf Ebrahimi 
278*9a0e4156SSadaf Ebrahimi 	set_mem_access(MI, true);
279*9a0e4156SSadaf Ebrahimi 	printOperand(MI, opNum + 1, O);
280*9a0e4156SSadaf Ebrahimi 	SStream_concat0(O, "(");
281*9a0e4156SSadaf Ebrahimi 	printOperand(MI, opNum, O);
282*9a0e4156SSadaf Ebrahimi 	SStream_concat0(O, ")");
283*9a0e4156SSadaf Ebrahimi 	set_mem_access(MI, false);
284*9a0e4156SSadaf Ebrahimi }
285*9a0e4156SSadaf Ebrahimi 
286*9a0e4156SSadaf Ebrahimi // TODO???
printMemOperandEA(MCInst * MI,int opNum,SStream * O)287*9a0e4156SSadaf Ebrahimi static void printMemOperandEA(MCInst *MI, int opNum, SStream *O)
288*9a0e4156SSadaf Ebrahimi {
289*9a0e4156SSadaf Ebrahimi 	// when using stack locations for not load/store instructions
290*9a0e4156SSadaf Ebrahimi 	// print the same way as all normal 3 operand instructions.
291*9a0e4156SSadaf Ebrahimi 	printOperand(MI, opNum, O);
292*9a0e4156SSadaf Ebrahimi 	SStream_concat0(O, ", ");
293*9a0e4156SSadaf Ebrahimi 	printOperand(MI, opNum + 1, O);
294*9a0e4156SSadaf Ebrahimi 	return;
295*9a0e4156SSadaf Ebrahimi }
296*9a0e4156SSadaf Ebrahimi 
printFCCOperand(MCInst * MI,int opNum,SStream * O)297*9a0e4156SSadaf Ebrahimi static void printFCCOperand(MCInst *MI, int opNum, SStream *O)
298*9a0e4156SSadaf Ebrahimi {
299*9a0e4156SSadaf Ebrahimi 	MCOperand *MO = MCInst_getOperand(MI, opNum);
300*9a0e4156SSadaf Ebrahimi 	SStream_concat0(O, MipsFCCToString((Mips_CondCode)MCOperand_getImm(MO)));
301*9a0e4156SSadaf Ebrahimi }
302*9a0e4156SSadaf Ebrahimi 
printRegisterPair(MCInst * MI,int opNum,SStream * O)303*9a0e4156SSadaf Ebrahimi static void printRegisterPair(MCInst *MI, int opNum, SStream *O)
304*9a0e4156SSadaf Ebrahimi {
305*9a0e4156SSadaf Ebrahimi 	printRegName(O, MCOperand_getReg(MCInst_getOperand(MI, opNum)));
306*9a0e4156SSadaf Ebrahimi }
307*9a0e4156SSadaf Ebrahimi 
printAlias1(const char * Str,MCInst * MI,unsigned OpNo,SStream * OS)308*9a0e4156SSadaf Ebrahimi static char *printAlias1(const char *Str, MCInst *MI, unsigned OpNo, SStream *OS)
309*9a0e4156SSadaf Ebrahimi {
310*9a0e4156SSadaf Ebrahimi 	SStream_concat(OS, "%s\t", Str);
311*9a0e4156SSadaf Ebrahimi 	printOperand(MI, OpNo, OS);
312*9a0e4156SSadaf Ebrahimi 	return cs_strdup(Str);
313*9a0e4156SSadaf Ebrahimi }
314*9a0e4156SSadaf Ebrahimi 
printAlias2(const char * Str,MCInst * MI,unsigned OpNo0,unsigned OpNo1,SStream * OS)315*9a0e4156SSadaf Ebrahimi static char *printAlias2(const char *Str, MCInst *MI,
316*9a0e4156SSadaf Ebrahimi 		unsigned OpNo0, unsigned OpNo1, SStream *OS)
317*9a0e4156SSadaf Ebrahimi {
318*9a0e4156SSadaf Ebrahimi 	char *tmp;
319*9a0e4156SSadaf Ebrahimi 
320*9a0e4156SSadaf Ebrahimi 	tmp = printAlias1(Str, MI, OpNo0, OS);
321*9a0e4156SSadaf Ebrahimi 	SStream_concat0(OS, ", ");
322*9a0e4156SSadaf Ebrahimi 	printOperand(MI, OpNo1, OS);
323*9a0e4156SSadaf Ebrahimi 
324*9a0e4156SSadaf Ebrahimi 	return tmp;
325*9a0e4156SSadaf Ebrahimi }
326*9a0e4156SSadaf Ebrahimi 
327*9a0e4156SSadaf Ebrahimi #define GET_REGINFO_ENUM
328*9a0e4156SSadaf Ebrahimi #include "MipsGenRegisterInfo.inc"
329*9a0e4156SSadaf Ebrahimi 
printAlias(MCInst * MI,SStream * OS)330*9a0e4156SSadaf Ebrahimi static char *printAlias(MCInst *MI, SStream *OS)
331*9a0e4156SSadaf Ebrahimi {
332*9a0e4156SSadaf Ebrahimi 	switch (MCInst_getOpcode(MI)) {
333*9a0e4156SSadaf Ebrahimi 		case Mips_BEQ:
334*9a0e4156SSadaf Ebrahimi 		case Mips_BEQ_MM:
335*9a0e4156SSadaf Ebrahimi 			// beq $zero, $zero, $L2 => b $L2
336*9a0e4156SSadaf Ebrahimi 			// beq $r0, $zero, $L2 => beqz $r0, $L2
337*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 0, Mips_ZERO) && isReg(MI, 1, Mips_ZERO))
338*9a0e4156SSadaf Ebrahimi 				return printAlias1("b", MI, 2, OS);
339*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 1, Mips_ZERO))
340*9a0e4156SSadaf Ebrahimi 				return printAlias2("beqz", MI, 0, 2, OS);
341*9a0e4156SSadaf Ebrahimi 			return NULL;
342*9a0e4156SSadaf Ebrahimi 		case Mips_BEQ64:
343*9a0e4156SSadaf Ebrahimi 			// beq $r0, $zero, $L2 => beqz $r0, $L2
344*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 1, Mips_ZERO_64))
345*9a0e4156SSadaf Ebrahimi 				return printAlias2("beqz", MI, 0, 2, OS);
346*9a0e4156SSadaf Ebrahimi 			return NULL;
347*9a0e4156SSadaf Ebrahimi 		case Mips_BNE:
348*9a0e4156SSadaf Ebrahimi 			// bne $r0, $zero, $L2 => bnez $r0, $L2
349*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 1, Mips_ZERO))
350*9a0e4156SSadaf Ebrahimi 				return printAlias2("bnez", MI, 0, 2, OS);
351*9a0e4156SSadaf Ebrahimi 			return NULL;
352*9a0e4156SSadaf Ebrahimi 		case Mips_BNE64:
353*9a0e4156SSadaf Ebrahimi 			// bne $r0, $zero, $L2 => bnez $r0, $L2
354*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 1, Mips_ZERO_64))
355*9a0e4156SSadaf Ebrahimi 				return printAlias2("bnez", MI, 0, 2, OS);
356*9a0e4156SSadaf Ebrahimi 			return NULL;
357*9a0e4156SSadaf Ebrahimi 		case Mips_BGEZAL:
358*9a0e4156SSadaf Ebrahimi 			// bgezal $zero, $L1 => bal $L1
359*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 0, Mips_ZERO))
360*9a0e4156SSadaf Ebrahimi 				return printAlias1("bal", MI, 1, OS);
361*9a0e4156SSadaf Ebrahimi 			return NULL;
362*9a0e4156SSadaf Ebrahimi 		case Mips_BC1T:
363*9a0e4156SSadaf Ebrahimi 			// bc1t $fcc0, $L1 => bc1t $L1
364*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 0, Mips_FCC0))
365*9a0e4156SSadaf Ebrahimi 				return printAlias1("bc1t", MI, 1, OS);
366*9a0e4156SSadaf Ebrahimi 			return NULL;
367*9a0e4156SSadaf Ebrahimi 		case Mips_BC1F:
368*9a0e4156SSadaf Ebrahimi 			// bc1f $fcc0, $L1 => bc1f $L1
369*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 0, Mips_FCC0))
370*9a0e4156SSadaf Ebrahimi 				return printAlias1("bc1f", MI, 1, OS);
371*9a0e4156SSadaf Ebrahimi 			return NULL;
372*9a0e4156SSadaf Ebrahimi 		case Mips_JALR:
373*9a0e4156SSadaf Ebrahimi 			// jalr $ra, $r1 => jalr $r1
374*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 0, Mips_RA))
375*9a0e4156SSadaf Ebrahimi 				return printAlias1("jalr", MI, 1, OS);
376*9a0e4156SSadaf Ebrahimi 			return NULL;
377*9a0e4156SSadaf Ebrahimi 		case Mips_JALR64:
378*9a0e4156SSadaf Ebrahimi 			// jalr $ra, $r1 => jalr $r1
379*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 0, Mips_RA_64))
380*9a0e4156SSadaf Ebrahimi 				return printAlias1("jalr", MI, 1, OS);
381*9a0e4156SSadaf Ebrahimi 			return NULL;
382*9a0e4156SSadaf Ebrahimi 		case Mips_NOR:
383*9a0e4156SSadaf Ebrahimi 		case Mips_NOR_MM:
384*9a0e4156SSadaf Ebrahimi 			// nor $r0, $r1, $zero => not $r0, $r1
385*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 2, Mips_ZERO))
386*9a0e4156SSadaf Ebrahimi 				return printAlias2("not", MI, 0, 1, OS);
387*9a0e4156SSadaf Ebrahimi 			return NULL;
388*9a0e4156SSadaf Ebrahimi 		case Mips_NOR64:
389*9a0e4156SSadaf Ebrahimi 			// nor $r0, $r1, $zero => not $r0, $r1
390*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 2, Mips_ZERO_64))
391*9a0e4156SSadaf Ebrahimi 				return printAlias2("not", MI, 0, 1, OS);
392*9a0e4156SSadaf Ebrahimi 			return NULL;
393*9a0e4156SSadaf Ebrahimi 		case Mips_OR:
394*9a0e4156SSadaf Ebrahimi 			// or $r0, $r1, $zero => move $r0, $r1
395*9a0e4156SSadaf Ebrahimi 			if (isReg(MI, 2, Mips_ZERO))
396*9a0e4156SSadaf Ebrahimi 				return printAlias2("move", MI, 0, 1, OS);
397*9a0e4156SSadaf Ebrahimi 			return NULL;
398*9a0e4156SSadaf Ebrahimi 		default: return NULL;
399*9a0e4156SSadaf Ebrahimi 	}
400*9a0e4156SSadaf Ebrahimi }
401*9a0e4156SSadaf Ebrahimi 
printRegisterList(MCInst * MI,int opNum,SStream * O)402*9a0e4156SSadaf Ebrahimi static void printRegisterList(MCInst *MI, int opNum, SStream *O)
403*9a0e4156SSadaf Ebrahimi {
404*9a0e4156SSadaf Ebrahimi 	int i, e, reg;
405*9a0e4156SSadaf Ebrahimi 
406*9a0e4156SSadaf Ebrahimi 	// - 2 because register List is always first operand of instruction and it is
407*9a0e4156SSadaf Ebrahimi 	// always followed by memory operand (base + offset).
408*9a0e4156SSadaf Ebrahimi 	for (i = opNum, e = MCInst_getNumOperands(MI) - 2; i != e; ++i) {
409*9a0e4156SSadaf Ebrahimi 		if (i != opNum)
410*9a0e4156SSadaf Ebrahimi 			SStream_concat0(O, ", ");
411*9a0e4156SSadaf Ebrahimi 		reg = MCOperand_getReg(MCInst_getOperand(MI, i));
412*9a0e4156SSadaf Ebrahimi 		printRegName(O, reg);
413*9a0e4156SSadaf Ebrahimi 		if (MI->csh->detail) {
414*9a0e4156SSadaf Ebrahimi 			MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].type = MIPS_OP_REG;
415*9a0e4156SSadaf Ebrahimi 			MI->flat_insn->detail->mips.operands[MI->flat_insn->detail->mips.op_count].reg = reg;
416*9a0e4156SSadaf Ebrahimi 			MI->flat_insn->detail->mips.op_count++;
417*9a0e4156SSadaf Ebrahimi 		}
418*9a0e4156SSadaf Ebrahimi 	}
419*9a0e4156SSadaf Ebrahimi }
420*9a0e4156SSadaf Ebrahimi 
421*9a0e4156SSadaf Ebrahimi #define PRINT_ALIAS_INSTR
422*9a0e4156SSadaf Ebrahimi #include "MipsGenAsmWriter.inc"
423*9a0e4156SSadaf Ebrahimi 
424*9a0e4156SSadaf Ebrahimi #endif
425