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