xref: /aosp_15_r20/external/capstone/arch/Sparc/SparcInstPrinter.c (revision 9a0e4156d50a75a99ec4f1653a0e9602a5d45c18)
1*9a0e4156SSadaf Ebrahimi //===-- SparcInstPrinter.cpp - Convert Sparc 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 Sparc 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_SPARC
18*9a0e4156SSadaf Ebrahimi 
19*9a0e4156SSadaf Ebrahimi #ifdef _MSC_VER
20*9a0e4156SSadaf Ebrahimi #define _CRT_SECURE_NO_WARNINGS
21*9a0e4156SSadaf Ebrahimi #endif
22*9a0e4156SSadaf Ebrahimi 
23*9a0e4156SSadaf Ebrahimi #if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)
24*9a0e4156SSadaf Ebrahimi #pragma warning(disable:28719)		// disable MSVC's warning on strncpy()
25*9a0e4156SSadaf Ebrahimi #endif
26*9a0e4156SSadaf Ebrahimi 
27*9a0e4156SSadaf Ebrahimi #include <stdio.h>
28*9a0e4156SSadaf Ebrahimi #include <stdlib.h>
29*9a0e4156SSadaf Ebrahimi #include <string.h>
30*9a0e4156SSadaf Ebrahimi #include <limits.h>
31*9a0e4156SSadaf Ebrahimi 
32*9a0e4156SSadaf Ebrahimi #include "SparcInstPrinter.h"
33*9a0e4156SSadaf Ebrahimi #include "../../MCInst.h"
34*9a0e4156SSadaf Ebrahimi #include "../../utils.h"
35*9a0e4156SSadaf Ebrahimi #include "../../SStream.h"
36*9a0e4156SSadaf Ebrahimi #include "../../MCRegisterInfo.h"
37*9a0e4156SSadaf Ebrahimi #include "../../MathExtras.h"
38*9a0e4156SSadaf Ebrahimi #include "SparcMapping.h"
39*9a0e4156SSadaf Ebrahimi 
40*9a0e4156SSadaf Ebrahimi #include "Sparc.h"
41*9a0e4156SSadaf Ebrahimi 
42*9a0e4156SSadaf Ebrahimi static const char *getRegisterName(unsigned RegNo);
43*9a0e4156SSadaf Ebrahimi static void printInstruction(MCInst *MI, SStream *O, const MCRegisterInfo *MRI);
44*9a0e4156SSadaf Ebrahimi static void printMemOperand(MCInst *MI, int opNum, SStream *O, const char *Modifier);
45*9a0e4156SSadaf Ebrahimi static void printOperand(MCInst *MI, int opNum, SStream *O);
46*9a0e4156SSadaf Ebrahimi 
Sparc_add_hint(MCInst * MI,unsigned int hint)47*9a0e4156SSadaf Ebrahimi static void Sparc_add_hint(MCInst *MI, unsigned int hint)
48*9a0e4156SSadaf Ebrahimi {
49*9a0e4156SSadaf Ebrahimi 	if (MI->csh->detail) {
50*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->sparc.hint = hint;
51*9a0e4156SSadaf Ebrahimi 	}
52*9a0e4156SSadaf Ebrahimi }
53*9a0e4156SSadaf Ebrahimi 
Sparc_add_reg(MCInst * MI,unsigned int reg)54*9a0e4156SSadaf Ebrahimi static void Sparc_add_reg(MCInst *MI, unsigned int reg)
55*9a0e4156SSadaf Ebrahimi {
56*9a0e4156SSadaf Ebrahimi 	if (MI->csh->detail) {
57*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].type = SPARC_OP_REG;
58*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].reg = reg;
59*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->sparc.op_count++;
60*9a0e4156SSadaf Ebrahimi 	}
61*9a0e4156SSadaf Ebrahimi }
62*9a0e4156SSadaf Ebrahimi 
set_mem_access(MCInst * MI,bool status)63*9a0e4156SSadaf Ebrahimi static void set_mem_access(MCInst *MI, bool status)
64*9a0e4156SSadaf Ebrahimi {
65*9a0e4156SSadaf Ebrahimi 	if (MI->csh->detail != CS_OPT_ON)
66*9a0e4156SSadaf Ebrahimi 		return;
67*9a0e4156SSadaf Ebrahimi 
68*9a0e4156SSadaf Ebrahimi 	MI->csh->doing_mem = status;
69*9a0e4156SSadaf Ebrahimi 
70*9a0e4156SSadaf Ebrahimi 	if (status) {
71*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].type = SPARC_OP_MEM;
72*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].mem.base = SPARC_REG_INVALID;
73*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].mem.disp = 0;
74*9a0e4156SSadaf Ebrahimi 	} else {
75*9a0e4156SSadaf Ebrahimi 		// done, create the next operand slot
76*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->sparc.op_count++;
77*9a0e4156SSadaf Ebrahimi 	}
78*9a0e4156SSadaf Ebrahimi }
79*9a0e4156SSadaf Ebrahimi 
Sparc_post_printer(csh ud,cs_insn * insn,char * insn_asm,MCInst * mci)80*9a0e4156SSadaf Ebrahimi void Sparc_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
81*9a0e4156SSadaf Ebrahimi {
82*9a0e4156SSadaf Ebrahimi 	if (((cs_struct *)ud)->detail != CS_OPT_ON)
83*9a0e4156SSadaf Ebrahimi 		return;
84*9a0e4156SSadaf Ebrahimi 
85*9a0e4156SSadaf Ebrahimi 	// fix up some instructions
86*9a0e4156SSadaf Ebrahimi 	if (insn->id == SPARC_INS_CASX) {
87*9a0e4156SSadaf Ebrahimi 		// first op is actually a memop, not regop
88*9a0e4156SSadaf Ebrahimi 		insn->detail->sparc.operands[0].type = SPARC_OP_MEM;
89*9a0e4156SSadaf Ebrahimi 		insn->detail->sparc.operands[0].mem.base = (uint8_t)insn->detail->sparc.operands[0].reg;
90*9a0e4156SSadaf Ebrahimi 		insn->detail->sparc.operands[0].mem.disp = 0;
91*9a0e4156SSadaf Ebrahimi 	}
92*9a0e4156SSadaf Ebrahimi }
93*9a0e4156SSadaf Ebrahimi 
printRegName(SStream * OS,unsigned RegNo)94*9a0e4156SSadaf Ebrahimi static void printRegName(SStream *OS, unsigned RegNo)
95*9a0e4156SSadaf Ebrahimi {
96*9a0e4156SSadaf Ebrahimi 	SStream_concat0(OS, "%");
97*9a0e4156SSadaf Ebrahimi 	SStream_concat0(OS, getRegisterName(RegNo));
98*9a0e4156SSadaf Ebrahimi }
99*9a0e4156SSadaf Ebrahimi 
100*9a0e4156SSadaf Ebrahimi #define GET_INSTRINFO_ENUM
101*9a0e4156SSadaf Ebrahimi #include "SparcGenInstrInfo.inc"
102*9a0e4156SSadaf Ebrahimi 
103*9a0e4156SSadaf Ebrahimi #define GET_REGINFO_ENUM
104*9a0e4156SSadaf Ebrahimi #include "SparcGenRegisterInfo.inc"
105*9a0e4156SSadaf Ebrahimi 
printSparcAliasInstr(MCInst * MI,SStream * O)106*9a0e4156SSadaf Ebrahimi static bool printSparcAliasInstr(MCInst *MI, SStream *O)
107*9a0e4156SSadaf Ebrahimi {
108*9a0e4156SSadaf Ebrahimi 	switch (MCInst_getOpcode(MI)) {
109*9a0e4156SSadaf Ebrahimi 		default: return false;
110*9a0e4156SSadaf Ebrahimi 		case SP_JMPLrr:
111*9a0e4156SSadaf Ebrahimi 		case SP_JMPLri:
112*9a0e4156SSadaf Ebrahimi 				 if (MCInst_getNumOperands(MI) != 3)
113*9a0e4156SSadaf Ebrahimi 					 return false;
114*9a0e4156SSadaf Ebrahimi 				 if (!MCOperand_isReg(MCInst_getOperand(MI, 0)))
115*9a0e4156SSadaf Ebrahimi 					 return false;
116*9a0e4156SSadaf Ebrahimi 
117*9a0e4156SSadaf Ebrahimi 				 switch (MCOperand_getReg(MCInst_getOperand(MI, 0))) {
118*9a0e4156SSadaf Ebrahimi 					 default: return false;
119*9a0e4156SSadaf Ebrahimi 					 case SP_G0: // jmp $addr | ret | retl
120*9a0e4156SSadaf Ebrahimi 							  if (MCOperand_isImm(MCInst_getOperand(MI, 2)) &&
121*9a0e4156SSadaf Ebrahimi 									MCOperand_getImm(MCInst_getOperand(MI, 2)) == 8) {
122*9a0e4156SSadaf Ebrahimi 								  switch(MCOperand_getReg(MCInst_getOperand(MI, 1))) {
123*9a0e4156SSadaf Ebrahimi 									  default: break;
124*9a0e4156SSadaf Ebrahimi 									  case SP_I7: SStream_concat0(O, "ret"); MCInst_setOpcodePub(MI, SPARC_INS_RET); return true;
125*9a0e4156SSadaf Ebrahimi 									  case SP_O7: SStream_concat0(O, "retl"); MCInst_setOpcodePub(MI, SPARC_INS_RETL); return true;
126*9a0e4156SSadaf Ebrahimi 								  }
127*9a0e4156SSadaf Ebrahimi 							  }
128*9a0e4156SSadaf Ebrahimi 
129*9a0e4156SSadaf Ebrahimi 							  SStream_concat0(O, "jmp\t");
130*9a0e4156SSadaf Ebrahimi 							  MCInst_setOpcodePub(MI, SPARC_INS_JMP);
131*9a0e4156SSadaf Ebrahimi 							  printMemOperand(MI, 1, O, NULL);
132*9a0e4156SSadaf Ebrahimi 							  return true;
133*9a0e4156SSadaf Ebrahimi 					 case SP_O7: // call $addr
134*9a0e4156SSadaf Ebrahimi 							  SStream_concat0(O, "call ");
135*9a0e4156SSadaf Ebrahimi 							  MCInst_setOpcodePub(MI, SPARC_INS_CALL);
136*9a0e4156SSadaf Ebrahimi 							  printMemOperand(MI, 1, O, NULL);
137*9a0e4156SSadaf Ebrahimi 							  return true;
138*9a0e4156SSadaf Ebrahimi 				 }
139*9a0e4156SSadaf Ebrahimi 		case SP_V9FCMPS:
140*9a0e4156SSadaf Ebrahimi 		case SP_V9FCMPD:
141*9a0e4156SSadaf Ebrahimi 		case SP_V9FCMPQ:
142*9a0e4156SSadaf Ebrahimi 		case SP_V9FCMPES:
143*9a0e4156SSadaf Ebrahimi 		case SP_V9FCMPED:
144*9a0e4156SSadaf Ebrahimi 		case SP_V9FCMPEQ:
145*9a0e4156SSadaf Ebrahimi 				 if (MI->csh->mode & CS_MODE_V9 || (MCInst_getNumOperands(MI) != 3) ||
146*9a0e4156SSadaf Ebrahimi 						 (!MCOperand_isReg(MCInst_getOperand(MI, 0))) ||
147*9a0e4156SSadaf Ebrahimi 						 (MCOperand_getReg(MCInst_getOperand(MI, 0)) != SP_FCC0))
148*9a0e4156SSadaf Ebrahimi 						 return false;
149*9a0e4156SSadaf Ebrahimi 				 // if V8, skip printing %fcc0.
150*9a0e4156SSadaf Ebrahimi 				 switch(MCInst_getOpcode(MI)) {
151*9a0e4156SSadaf Ebrahimi 					 default:
152*9a0e4156SSadaf Ebrahimi 					 case SP_V9FCMPS:  SStream_concat0(O, "fcmps\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPS); break;
153*9a0e4156SSadaf Ebrahimi 					 case SP_V9FCMPD:  SStream_concat0(O, "fcmpd\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPD); break;
154*9a0e4156SSadaf Ebrahimi 					 case SP_V9FCMPQ:  SStream_concat0(O, "fcmpq\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPQ); break;
155*9a0e4156SSadaf Ebrahimi 					 case SP_V9FCMPES: SStream_concat0(O, "fcmpes\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPES); break;
156*9a0e4156SSadaf Ebrahimi 					 case SP_V9FCMPED: SStream_concat0(O, "fcmped\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPED); break;
157*9a0e4156SSadaf Ebrahimi 					 case SP_V9FCMPEQ: SStream_concat0(O, "fcmpeq\t"); MCInst_setOpcodePub(MI, SPARC_INS_FCMPEQ); break;
158*9a0e4156SSadaf Ebrahimi 				 }
159*9a0e4156SSadaf Ebrahimi 				 printOperand(MI, 1, O);
160*9a0e4156SSadaf Ebrahimi 				 SStream_concat0(O, ", ");
161*9a0e4156SSadaf Ebrahimi 				 printOperand(MI, 2, O);
162*9a0e4156SSadaf Ebrahimi 				 return true;
163*9a0e4156SSadaf Ebrahimi 	}
164*9a0e4156SSadaf Ebrahimi }
165*9a0e4156SSadaf Ebrahimi 
printOperand(MCInst * MI,int opNum,SStream * O)166*9a0e4156SSadaf Ebrahimi static void printOperand(MCInst *MI, int opNum, SStream *O)
167*9a0e4156SSadaf Ebrahimi {
168*9a0e4156SSadaf Ebrahimi 	int64_t Imm;
169*9a0e4156SSadaf Ebrahimi 	unsigned reg;
170*9a0e4156SSadaf Ebrahimi 	MCOperand *MO = MCInst_getOperand(MI, opNum);
171*9a0e4156SSadaf Ebrahimi 
172*9a0e4156SSadaf Ebrahimi 	if (MCOperand_isReg(MO)) {
173*9a0e4156SSadaf Ebrahimi 		reg = MCOperand_getReg(MO);
174*9a0e4156SSadaf Ebrahimi 		printRegName(O, reg);
175*9a0e4156SSadaf Ebrahimi 		reg = Sparc_map_register(reg);
176*9a0e4156SSadaf Ebrahimi 
177*9a0e4156SSadaf Ebrahimi 		if (MI->csh->detail) {
178*9a0e4156SSadaf Ebrahimi 			if (MI->csh->doing_mem) {
179*9a0e4156SSadaf Ebrahimi 				if (MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].mem.base)
180*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].mem.index = (uint8_t)reg;
181*9a0e4156SSadaf Ebrahimi 				else
182*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].mem.base = (uint8_t)reg;
183*9a0e4156SSadaf Ebrahimi 			} else {
184*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].type = SPARC_OP_REG;
185*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].reg = reg;
186*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->sparc.op_count++;
187*9a0e4156SSadaf Ebrahimi 			}
188*9a0e4156SSadaf Ebrahimi 		}
189*9a0e4156SSadaf Ebrahimi 
190*9a0e4156SSadaf Ebrahimi 		return;
191*9a0e4156SSadaf Ebrahimi 	}
192*9a0e4156SSadaf Ebrahimi 
193*9a0e4156SSadaf Ebrahimi 	if (MCOperand_isImm(MO)) {
194*9a0e4156SSadaf Ebrahimi 		Imm = (int)MCOperand_getImm(MO);
195*9a0e4156SSadaf Ebrahimi 
196*9a0e4156SSadaf Ebrahimi 		// Conditional branches displacements needs to be signextended to be
197*9a0e4156SSadaf Ebrahimi 		// able to jump backwards.
198*9a0e4156SSadaf Ebrahimi 		//
199*9a0e4156SSadaf Ebrahimi 		// Displacements are measured as the number of instructions forward or
200*9a0e4156SSadaf Ebrahimi 		// backward, so they need to be multiplied by 4
201*9a0e4156SSadaf Ebrahimi 		switch (MI->Opcode) {
202*9a0e4156SSadaf Ebrahimi 			case SP_CALL:
203*9a0e4156SSadaf Ebrahimi 				// Imm = SignExtend32(Imm, 30);
204*9a0e4156SSadaf Ebrahimi 				Imm += MI->address;
205*9a0e4156SSadaf Ebrahimi 				break;
206*9a0e4156SSadaf Ebrahimi 
207*9a0e4156SSadaf Ebrahimi 			// Branch on integer condition with prediction (BPcc)
208*9a0e4156SSadaf Ebrahimi 			// Branch on floating point condition with prediction (FBPfcc)
209*9a0e4156SSadaf Ebrahimi 			case SP_BPICC:
210*9a0e4156SSadaf Ebrahimi 			case SP_BPICCA:
211*9a0e4156SSadaf Ebrahimi 			case SP_BPICCANT:
212*9a0e4156SSadaf Ebrahimi 			case SP_BPICCNT:
213*9a0e4156SSadaf Ebrahimi 			case SP_BPXCC:
214*9a0e4156SSadaf Ebrahimi 			case SP_BPXCCA:
215*9a0e4156SSadaf Ebrahimi 			case SP_BPXCCANT:
216*9a0e4156SSadaf Ebrahimi 			case SP_BPXCCNT:
217*9a0e4156SSadaf Ebrahimi 			case SP_BPFCC:
218*9a0e4156SSadaf Ebrahimi 			case SP_BPFCCA:
219*9a0e4156SSadaf Ebrahimi 			case SP_BPFCCANT:
220*9a0e4156SSadaf Ebrahimi 			case SP_BPFCCNT:
221*9a0e4156SSadaf Ebrahimi 				Imm = SignExtend32((uint32_t)Imm, 19);
222*9a0e4156SSadaf Ebrahimi 				Imm = MI->address + Imm * 4;
223*9a0e4156SSadaf Ebrahimi 				break;
224*9a0e4156SSadaf Ebrahimi 
225*9a0e4156SSadaf Ebrahimi 			// Branch on integer condition (Bicc)
226*9a0e4156SSadaf Ebrahimi 			// Branch on floating point condition (FBfcc)
227*9a0e4156SSadaf Ebrahimi 			case SP_BA:
228*9a0e4156SSadaf Ebrahimi 			case SP_BCOND:
229*9a0e4156SSadaf Ebrahimi 			case SP_BCONDA:
230*9a0e4156SSadaf Ebrahimi 			case SP_FBCOND:
231*9a0e4156SSadaf Ebrahimi 			case SP_FBCONDA:
232*9a0e4156SSadaf Ebrahimi 				Imm = SignExtend32((uint32_t)Imm, 22);
233*9a0e4156SSadaf Ebrahimi 				Imm = MI->address + Imm * 4;
234*9a0e4156SSadaf Ebrahimi 				break;
235*9a0e4156SSadaf Ebrahimi 
236*9a0e4156SSadaf Ebrahimi 			// Branch on integer register with prediction (BPr)
237*9a0e4156SSadaf Ebrahimi 			case SP_BPGEZapn:
238*9a0e4156SSadaf Ebrahimi 			case SP_BPGEZapt:
239*9a0e4156SSadaf Ebrahimi 			case SP_BPGEZnapn:
240*9a0e4156SSadaf Ebrahimi 			case SP_BPGEZnapt:
241*9a0e4156SSadaf Ebrahimi 			case SP_BPGZapn:
242*9a0e4156SSadaf Ebrahimi 			case SP_BPGZapt:
243*9a0e4156SSadaf Ebrahimi 			case SP_BPGZnapn:
244*9a0e4156SSadaf Ebrahimi 			case SP_BPGZnapt:
245*9a0e4156SSadaf Ebrahimi 			case SP_BPLEZapn:
246*9a0e4156SSadaf Ebrahimi 			case SP_BPLEZapt:
247*9a0e4156SSadaf Ebrahimi 			case SP_BPLEZnapn:
248*9a0e4156SSadaf Ebrahimi 			case SP_BPLEZnapt:
249*9a0e4156SSadaf Ebrahimi 			case SP_BPLZapn:
250*9a0e4156SSadaf Ebrahimi 			case SP_BPLZapt:
251*9a0e4156SSadaf Ebrahimi 			case SP_BPLZnapn:
252*9a0e4156SSadaf Ebrahimi 			case SP_BPLZnapt:
253*9a0e4156SSadaf Ebrahimi 			case SP_BPNZapn:
254*9a0e4156SSadaf Ebrahimi 			case SP_BPNZapt:
255*9a0e4156SSadaf Ebrahimi 			case SP_BPNZnapn:
256*9a0e4156SSadaf Ebrahimi 			case SP_BPNZnapt:
257*9a0e4156SSadaf Ebrahimi 			case SP_BPZapn:
258*9a0e4156SSadaf Ebrahimi 			case SP_BPZapt:
259*9a0e4156SSadaf Ebrahimi 			case SP_BPZnapn:
260*9a0e4156SSadaf Ebrahimi 			case SP_BPZnapt:
261*9a0e4156SSadaf Ebrahimi 				Imm = SignExtend32((uint32_t)Imm, 16);
262*9a0e4156SSadaf Ebrahimi 				Imm = MI->address + Imm * 4;
263*9a0e4156SSadaf Ebrahimi 				break;
264*9a0e4156SSadaf Ebrahimi 		}
265*9a0e4156SSadaf Ebrahimi 
266*9a0e4156SSadaf Ebrahimi 		printInt64(O, Imm);
267*9a0e4156SSadaf Ebrahimi 
268*9a0e4156SSadaf Ebrahimi 		if (MI->csh->detail) {
269*9a0e4156SSadaf Ebrahimi 			if (MI->csh->doing_mem) {
270*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].mem.disp = (uint32_t)Imm;
271*9a0e4156SSadaf Ebrahimi 			} else {
272*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].type = SPARC_OP_IMM;
273*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].imm = Imm;
274*9a0e4156SSadaf Ebrahimi 				MI->flat_insn->detail->sparc.op_count++;
275*9a0e4156SSadaf Ebrahimi 			}
276*9a0e4156SSadaf Ebrahimi 		}
277*9a0e4156SSadaf Ebrahimi 	}
278*9a0e4156SSadaf Ebrahimi 
279*9a0e4156SSadaf Ebrahimi 	return;
280*9a0e4156SSadaf Ebrahimi }
281*9a0e4156SSadaf Ebrahimi 
printMemOperand(MCInst * MI,int opNum,SStream * O,const char * Modifier)282*9a0e4156SSadaf Ebrahimi static void printMemOperand(MCInst *MI, int opNum, SStream *O, const char *Modifier)
283*9a0e4156SSadaf Ebrahimi {
284*9a0e4156SSadaf Ebrahimi 	MCOperand *MO;
285*9a0e4156SSadaf Ebrahimi 
286*9a0e4156SSadaf Ebrahimi 	set_mem_access(MI, true);
287*9a0e4156SSadaf Ebrahimi 	printOperand(MI, opNum, O);
288*9a0e4156SSadaf Ebrahimi 
289*9a0e4156SSadaf Ebrahimi 	// If this is an ADD operand, emit it like normal operands.
290*9a0e4156SSadaf Ebrahimi 	if (Modifier && !strcmp(Modifier, "arith")) {
291*9a0e4156SSadaf Ebrahimi 		SStream_concat0(O, ", ");
292*9a0e4156SSadaf Ebrahimi 		printOperand(MI, opNum + 1, O);
293*9a0e4156SSadaf Ebrahimi 		set_mem_access(MI, false);
294*9a0e4156SSadaf Ebrahimi 		return;
295*9a0e4156SSadaf Ebrahimi 	}
296*9a0e4156SSadaf Ebrahimi 
297*9a0e4156SSadaf Ebrahimi 	MO = MCInst_getOperand(MI, opNum + 1);
298*9a0e4156SSadaf Ebrahimi 
299*9a0e4156SSadaf Ebrahimi 	if (MCOperand_isReg(MO) && (MCOperand_getReg(MO) == SP_G0)) {
300*9a0e4156SSadaf Ebrahimi 		set_mem_access(MI, false);
301*9a0e4156SSadaf Ebrahimi 		return;   // don't print "+%g0"
302*9a0e4156SSadaf Ebrahimi 	}
303*9a0e4156SSadaf Ebrahimi 
304*9a0e4156SSadaf Ebrahimi 	if (MCOperand_isImm(MO) && (MCOperand_getImm(MO) == 0)) {
305*9a0e4156SSadaf Ebrahimi 		set_mem_access(MI, false);
306*9a0e4156SSadaf Ebrahimi 		return;   // don't print "+0"
307*9a0e4156SSadaf Ebrahimi 	}
308*9a0e4156SSadaf Ebrahimi 
309*9a0e4156SSadaf Ebrahimi 	SStream_concat0(O, "+");	// qq
310*9a0e4156SSadaf Ebrahimi 
311*9a0e4156SSadaf Ebrahimi 	printOperand(MI, opNum + 1, O);
312*9a0e4156SSadaf Ebrahimi 	set_mem_access(MI, false);
313*9a0e4156SSadaf Ebrahimi }
314*9a0e4156SSadaf Ebrahimi 
printCCOperand(MCInst * MI,int opNum,SStream * O)315*9a0e4156SSadaf Ebrahimi static void printCCOperand(MCInst *MI, int opNum, SStream *O)
316*9a0e4156SSadaf Ebrahimi {
317*9a0e4156SSadaf Ebrahimi 	int CC = (int)MCOperand_getImm(MCInst_getOperand(MI, opNum)) + 256;
318*9a0e4156SSadaf Ebrahimi 
319*9a0e4156SSadaf Ebrahimi 	switch (MCInst_getOpcode(MI)) {
320*9a0e4156SSadaf Ebrahimi 		default: break;
321*9a0e4156SSadaf Ebrahimi 		case SP_FBCOND:
322*9a0e4156SSadaf Ebrahimi 		case SP_FBCONDA:
323*9a0e4156SSadaf Ebrahimi 		case SP_BPFCC:
324*9a0e4156SSadaf Ebrahimi 		case SP_BPFCCA:
325*9a0e4156SSadaf Ebrahimi 		case SP_BPFCCNT:
326*9a0e4156SSadaf Ebrahimi 		case SP_BPFCCANT:
327*9a0e4156SSadaf Ebrahimi 		case SP_MOVFCCrr:  case SP_V9MOVFCCrr:
328*9a0e4156SSadaf Ebrahimi 		case SP_MOVFCCri:  case SP_V9MOVFCCri:
329*9a0e4156SSadaf Ebrahimi 		case SP_FMOVS_FCC: case SP_V9FMOVS_FCC:
330*9a0e4156SSadaf Ebrahimi 		case SP_FMOVD_FCC: case SP_V9FMOVD_FCC:
331*9a0e4156SSadaf Ebrahimi 		case SP_FMOVQ_FCC: case SP_V9FMOVQ_FCC:
332*9a0e4156SSadaf Ebrahimi 				 // Make sure CC is a fp conditional flag.
333*9a0e4156SSadaf Ebrahimi 				 CC = (CC < 16+256) ? (CC + 16) : CC;
334*9a0e4156SSadaf Ebrahimi 				 break;
335*9a0e4156SSadaf Ebrahimi 	}
336*9a0e4156SSadaf Ebrahimi 
337*9a0e4156SSadaf Ebrahimi 	SStream_concat0(O, SPARCCondCodeToString((sparc_cc)CC));
338*9a0e4156SSadaf Ebrahimi 
339*9a0e4156SSadaf Ebrahimi 	if (MI->csh->detail)
340*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->sparc.cc = (sparc_cc)CC;
341*9a0e4156SSadaf Ebrahimi }
342*9a0e4156SSadaf Ebrahimi 
343*9a0e4156SSadaf Ebrahimi 
printGetPCX(MCInst * MI,unsigned opNum,SStream * O)344*9a0e4156SSadaf Ebrahimi static bool printGetPCX(MCInst *MI, unsigned opNum, SStream *O)
345*9a0e4156SSadaf Ebrahimi {
346*9a0e4156SSadaf Ebrahimi 	return true;
347*9a0e4156SSadaf Ebrahimi }
348*9a0e4156SSadaf Ebrahimi 
349*9a0e4156SSadaf Ebrahimi 
350*9a0e4156SSadaf Ebrahimi #define PRINT_ALIAS_INSTR
351*9a0e4156SSadaf Ebrahimi #include "SparcGenAsmWriter.inc"
352*9a0e4156SSadaf Ebrahimi 
Sparc_printInst(MCInst * MI,SStream * O,void * Info)353*9a0e4156SSadaf Ebrahimi void Sparc_printInst(MCInst *MI, SStream *O, void *Info)
354*9a0e4156SSadaf Ebrahimi {
355*9a0e4156SSadaf Ebrahimi 	char *mnem, *p;
356*9a0e4156SSadaf Ebrahimi 	char instr[64];	// Sparc has no instruction this long
357*9a0e4156SSadaf Ebrahimi 
358*9a0e4156SSadaf Ebrahimi 	mnem = printAliasInstr(MI, O, Info);
359*9a0e4156SSadaf Ebrahimi 	if (mnem) {
360*9a0e4156SSadaf Ebrahimi 		// fixup instruction id due to the change in alias instruction
361*9a0e4156SSadaf Ebrahimi 		strncpy(instr, mnem, sizeof(instr));
362*9a0e4156SSadaf Ebrahimi 		instr[sizeof(instr) - 1] = '\0';
363*9a0e4156SSadaf Ebrahimi 		// does this contains hint with a coma?
364*9a0e4156SSadaf Ebrahimi 		p = strchr(instr, ',');
365*9a0e4156SSadaf Ebrahimi 		if (p)
366*9a0e4156SSadaf Ebrahimi 			*p = '\0';	// now instr only has instruction mnemonic
367*9a0e4156SSadaf Ebrahimi 		MCInst_setOpcodePub(MI, Sparc_map_insn(instr));
368*9a0e4156SSadaf Ebrahimi 		switch(MCInst_getOpcode(MI)) {
369*9a0e4156SSadaf Ebrahimi 			case SP_BCOND:
370*9a0e4156SSadaf Ebrahimi 			case SP_BCONDA:
371*9a0e4156SSadaf Ebrahimi 			case SP_BPICCANT:
372*9a0e4156SSadaf Ebrahimi 			case SP_BPICCNT:
373*9a0e4156SSadaf Ebrahimi 			case SP_BPXCCANT:
374*9a0e4156SSadaf Ebrahimi 			case SP_BPXCCNT:
375*9a0e4156SSadaf Ebrahimi 			case SP_TXCCri:
376*9a0e4156SSadaf Ebrahimi 			case SP_TXCCrr:
377*9a0e4156SSadaf Ebrahimi 				if (MI->csh->detail) {
378*9a0e4156SSadaf Ebrahimi 					// skip 'b', 't'
379*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.cc = Sparc_map_ICC(instr + 1);
380*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem);
381*9a0e4156SSadaf Ebrahimi 				}
382*9a0e4156SSadaf Ebrahimi 				break;
383*9a0e4156SSadaf Ebrahimi 			case SP_BPFCCANT:
384*9a0e4156SSadaf Ebrahimi 			case SP_BPFCCNT:
385*9a0e4156SSadaf Ebrahimi 				if (MI->csh->detail) {
386*9a0e4156SSadaf Ebrahimi 					// skip 'fb'
387*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.cc = Sparc_map_FCC(instr + 2);
388*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem);
389*9a0e4156SSadaf Ebrahimi 				}
390*9a0e4156SSadaf Ebrahimi 				break;
391*9a0e4156SSadaf Ebrahimi 			case SP_FMOVD_ICC:
392*9a0e4156SSadaf Ebrahimi 			case SP_FMOVD_XCC:
393*9a0e4156SSadaf Ebrahimi 			case SP_FMOVQ_ICC:
394*9a0e4156SSadaf Ebrahimi 			case SP_FMOVQ_XCC:
395*9a0e4156SSadaf Ebrahimi 			case SP_FMOVS_ICC:
396*9a0e4156SSadaf Ebrahimi 			case SP_FMOVS_XCC:
397*9a0e4156SSadaf Ebrahimi 				if (MI->csh->detail) {
398*9a0e4156SSadaf Ebrahimi 					// skip 'fmovd', 'fmovq', 'fmovs'
399*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.cc = Sparc_map_ICC(instr + 5);
400*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem);
401*9a0e4156SSadaf Ebrahimi 				}
402*9a0e4156SSadaf Ebrahimi 				break;
403*9a0e4156SSadaf Ebrahimi 			case SP_MOVICCri:
404*9a0e4156SSadaf Ebrahimi 			case SP_MOVICCrr:
405*9a0e4156SSadaf Ebrahimi 			case SP_MOVXCCri:
406*9a0e4156SSadaf Ebrahimi 			case SP_MOVXCCrr:
407*9a0e4156SSadaf Ebrahimi 				if (MI->csh->detail) {
408*9a0e4156SSadaf Ebrahimi 					// skip 'mov'
409*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.cc = Sparc_map_ICC(instr + 3);
410*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem);
411*9a0e4156SSadaf Ebrahimi 				}
412*9a0e4156SSadaf Ebrahimi 				break;
413*9a0e4156SSadaf Ebrahimi 			case SP_V9FMOVD_FCC:
414*9a0e4156SSadaf Ebrahimi 			case SP_V9FMOVQ_FCC:
415*9a0e4156SSadaf Ebrahimi 			case SP_V9FMOVS_FCC:
416*9a0e4156SSadaf Ebrahimi 				if (MI->csh->detail) {
417*9a0e4156SSadaf Ebrahimi 					// skip 'fmovd', 'fmovq', 'fmovs'
418*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.cc = Sparc_map_FCC(instr + 5);
419*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem);
420*9a0e4156SSadaf Ebrahimi 				}
421*9a0e4156SSadaf Ebrahimi 				break;
422*9a0e4156SSadaf Ebrahimi 			case SP_V9MOVFCCri:
423*9a0e4156SSadaf Ebrahimi 			case SP_V9MOVFCCrr:
424*9a0e4156SSadaf Ebrahimi 				if (MI->csh->detail) {
425*9a0e4156SSadaf Ebrahimi 					// skip 'mov'
426*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.cc = Sparc_map_FCC(instr + 3);
427*9a0e4156SSadaf Ebrahimi 					MI->flat_insn->detail->sparc.hint = Sparc_map_hint(mnem);
428*9a0e4156SSadaf Ebrahimi 				}
429*9a0e4156SSadaf Ebrahimi 				break;
430*9a0e4156SSadaf Ebrahimi 			default:
431*9a0e4156SSadaf Ebrahimi 				break;
432*9a0e4156SSadaf Ebrahimi 		}
433*9a0e4156SSadaf Ebrahimi 		cs_mem_free(mnem);
434*9a0e4156SSadaf Ebrahimi 	} else {
435*9a0e4156SSadaf Ebrahimi 		if (!printSparcAliasInstr(MI, O))
436*9a0e4156SSadaf Ebrahimi 			printInstruction(MI, O, NULL);
437*9a0e4156SSadaf Ebrahimi 	}
438*9a0e4156SSadaf Ebrahimi }
439*9a0e4156SSadaf Ebrahimi 
Sparc_addReg(MCInst * MI,int reg)440*9a0e4156SSadaf Ebrahimi void Sparc_addReg(MCInst *MI, int reg)
441*9a0e4156SSadaf Ebrahimi {
442*9a0e4156SSadaf Ebrahimi 	if (MI->csh->detail) {
443*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].type = SPARC_OP_REG;
444*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->sparc.operands[MI->flat_insn->detail->sparc.op_count].reg = reg;
445*9a0e4156SSadaf Ebrahimi 		MI->flat_insn->detail->sparc.op_count++;
446*9a0e4156SSadaf Ebrahimi 	}
447*9a0e4156SSadaf Ebrahimi }
448*9a0e4156SSadaf Ebrahimi 
449*9a0e4156SSadaf Ebrahimi #endif
450