• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- XCoreInstPrinter.cpp - Convert XCore MCInst to assembly syntax --------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This class prints an XCore MCInst to a .s file.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 /* Capstone Disassembly Engine */
15 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
16 
17 #ifdef CAPSTONE_HAS_XCORE
18 
19 #if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)
20 #pragma warning(disable : 4996)			// disable MSVC's warning on strcpy()
21 #pragma warning(disable : 28719)		// disable MSVC's warning on strcpy()
22 #endif
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <platform.h>
28 
29 #include "XCoreInstPrinter.h"
30 #include "../../MCInst.h"
31 #include "../../utils.h"
32 #include "../../SStream.h"
33 #include "../../MCRegisterInfo.h"
34 #include "../../MathExtras.h"
35 #include "XCoreMapping.h"
36 
37 static char *getRegisterName(unsigned RegNo);
38 
XCore_post_printer(csh ud,cs_insn * insn,char * insn_asm,MCInst * mci)39 void XCore_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
40 {
41 	/*
42 	   if (((cs_struct *)ud)->detail != CS_OPT_ON)
43 	   return;
44 	 */
45 }
46 
47 // stw sed, sp[3]
XCore_insn_extract(MCInst * MI,const char * code)48 void XCore_insn_extract(MCInst *MI, const char *code)
49 {
50 	int id;
51 	char *p, *p2;
52 	char tmp[128];
53 
54 	strcpy(tmp, code); // safe because code is way shorter than 128 bytes
55 
56 	// find the first space
57 	p = strchr(tmp, ' ');
58 	if (p) {
59 		p++;
60 		// find the next ','
61 		p2 = strchr(p, ',');
62 		if (p2) {
63 			*p2 = '\0';
64 			id = XCore_reg_id(p);
65 			if (id) {
66 				// register
67 				if (MI->csh->detail) {
68 					MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
69 					MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id;
70 					MI->flat_insn->detail->xcore.op_count++;
71 				}
72 			}
73 			// next should be register, or memory?
74 			// skip space
75 			p2++;
76 			while(*p2 && *p2 == ' ')
77 				p2++;
78 			if (*p2) {
79 				// find '['
80 				p = p2;
81 				while(*p && *p != '[')
82 					p++;
83 				if (*p) {
84 					// this is '['
85 					*p = '\0';
86 					id = XCore_reg_id(p2);
87 					if (id) {
88 						// base register
89 						if (MI->csh->detail) {
90 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM;
91 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)id;
92 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID;
93 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0;
94 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1;
95 						}
96 
97 						p++;
98 						p2 = p;
99 						// until ']'
100 						while(*p && *p != ']')
101 							p++;
102 						if (*p) {
103 							*p = '\0';
104 							// p2 is either index, or disp
105 							id = XCore_reg_id(p2);
106 							if (id) {
107 								// index register
108 								if (MI->csh->detail) {
109 									MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)id;
110 								}
111 							} else {
112 								// a number means disp
113 								if (MI->csh->detail) {
114 									MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = atoi(p2);
115 								}
116 							}
117 						}
118 
119 						if (MI->csh->detail) {
120 							MI->flat_insn->detail->xcore.op_count++;
121 						}
122 					}
123 				} else {
124 					// a register?
125 					id = XCore_reg_id(p2);
126 					if (id) {
127 						// register
128 						if (MI->csh->detail) {
129 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
130 							MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id;
131 							MI->flat_insn->detail->xcore.op_count++;
132 						}
133 					}
134 				}
135 			}
136 		} else {
137 			id = XCore_reg_id(p);
138 			if (id) {
139 				// register
140 				if (MI->csh->detail) {
141 					MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
142 					MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = id;
143 					MI->flat_insn->detail->xcore.op_count++;
144 				}
145 			}
146 		}
147 	}
148 }
149 
set_mem_access(MCInst * MI,bool status,int reg)150 static void set_mem_access(MCInst *MI, bool status, int reg)
151 {
152 	if (MI->csh->detail != CS_OPT_ON)
153 		return;
154 
155 	MI->csh->doing_mem = status;
156 	if (status) {
157 		if (reg != 0xffff && reg != -0xffff) {
158 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM;
159 			if (reg) {
160 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)reg;
161 			} else {
162 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = XCORE_REG_INVALID;
163 			}
164 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID;
165 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0;
166 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1;
167 		} else {
168 			// the last op should be the memory base
169 			MI->flat_insn->detail->xcore.op_count--;
170 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_MEM;
171 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg;
172 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = XCORE_REG_INVALID;
173 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = 0;
174 			if (reg > 0)
175 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = 1;
176 			else
177 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.direct = -1;
178 		}
179 	} else {
180 		if (reg) {
181 			MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)reg;
182 			// done, create the next operand slot
183 			MI->flat_insn->detail->xcore.op_count++;
184 		}
185 	}
186 }
187 
_printOperand(MCInst * MI,MCOperand * MO,SStream * O)188 static void _printOperand(MCInst *MI, MCOperand *MO, SStream *O)
189 {
190 	if (MCOperand_isReg(MO)) {
191 		unsigned reg;
192 
193 		reg = MCOperand_getReg(MO);
194 		SStream_concat0(O, getRegisterName(reg));
195 
196 		if (MI->csh->detail) {
197 			if (MI->csh->doing_mem) {
198 				if (MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base == ARM_REG_INVALID)
199 					MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.base = (uint8_t)reg;
200 				else
201 					MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.index = (uint8_t)reg;
202 			} else {
203 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_REG;
204 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].reg = reg;
205 				MI->flat_insn->detail->xcore.op_count++;
206 			}
207 		}
208 	} else if (MCOperand_isImm(MO)) {
209 		int32_t Imm = (int32_t)MCOperand_getImm(MO);
210 
211 		if (Imm >= 0) {
212 			if (Imm > HEX_THRESHOLD)
213 				SStream_concat(O, "0x%x", Imm);
214 			else
215 				SStream_concat(O, "%u", Imm);
216 		} else {
217 			if (Imm < -HEX_THRESHOLD)
218 				SStream_concat(O, "-0x%x", -Imm);
219 			else
220 				SStream_concat(O, "-%u", -Imm);
221 		}
222 
223 		if (MI->csh->detail) {
224 			if (MI->csh->doing_mem) {
225 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].mem.disp = Imm;
226 			} else {
227 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].type = XCORE_OP_IMM;
228 				MI->flat_insn->detail->xcore.operands[MI->flat_insn->detail->xcore.op_count].imm = Imm;
229 				MI->flat_insn->detail->xcore.op_count++;
230 			}
231 		}
232 	}
233 }
234 
printOperand(MCInst * MI,int OpNum,SStream * O)235 static void printOperand(MCInst *MI, int OpNum, SStream *O)
236 {
237 	if (OpNum >= MI->size)
238 		return;
239 
240 	_printOperand(MI, MCInst_getOperand(MI, OpNum), O);
241 }
242 
printInlineJT(MCInst * MI,int OpNum,SStream * O)243 static void printInlineJT(MCInst *MI, int OpNum, SStream *O)
244 {
245 }
246 
printInlineJT32(MCInst * MI,int OpNum,SStream * O)247 static void printInlineJT32(MCInst *MI, int OpNum, SStream *O)
248 {
249 }
250 
251 #define PRINT_ALIAS_INSTR
252 #include "XCoreGenAsmWriter.inc"
253 
XCore_printInst(MCInst * MI,SStream * O,void * Info)254 void XCore_printInst(MCInst *MI, SStream *O, void *Info)
255 {
256 	printInstruction(MI, O, Info);
257 	set_mem_access(MI, false, 0);
258 }
259 
260 #endif
261