1 /*
2  *	HT Editor
3  *	asm.cc
4  *
5  *	Copyright (C) 1999-2002 Stefan Weyergraf
6  *
7  *	This program is free software; you can redistribute it and/or modify
8  *	it under the terms of the GNU General Public License version 2 as
9  *	published by the Free Software Foundation.
10  *
11  *	This program is distributed in the hope that it will be useful,
12  *	but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *	GNU General Public License for more details.
15  *
16  *	You should have received a copy of the GNU General Public License
17  *	along with this program; if not, write to the Free Software
18  *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 #include <cstring>
22 #include <cstdio>
23 #include <stdarg.h>
24 #include <limits.h>
25 
26 #include "asm.h"
27 #include "data.h"
28 #include "atom.h"
29 #include "htdebug.h"
30 #include "snprintf.h"
31 
32 #include "alphadis.h"
33 #include "ildis.h"
34 #include "javadis.h"
35 #include "x86dis.h"
36 #include "ppcdis.h"
37 #include "armdis.h"
38 #include "avrdis.h"
39 
40 /*
41  *	CLASS Assembler
42  */
43 
Assembler(bool b)44 Assembler::Assembler(bool b)
45 {
46 	codes = 0;
47 	bigendian = b;
48 }
49 
~Assembler()50 Assembler::~Assembler()
51 {
52 	free_asm_codes();
53 }
54 
alloc_insn()55 asm_insn *Assembler::alloc_insn()
56 {
57 	return NULL;
58 }
59 
deletecode(asm_code * code)60 void Assembler::deletecode(asm_code *code)
61 {
62 	asm_code **p=&codes, *c=codes;
63 	while (c) {
64 		if (c == code) {
65 			*p = c->next;
66 			delete c;
67 			return;
68 		}
69 		c = c->next;
70 		p = &(*p)->next;
71 	}
72 }
73 
encode(asm_insn * asm_insn,int _options,CPU_ADDR cur_address)74 asm_code *Assembler::encode(asm_insn *asm_insn, int _options, CPU_ADDR cur_address)
75 {
76 	free_asm_codes();
77 	error = 0;
78 	options = _options;
79 	return 0;
80 }
81 
clearcode()82 void Assembler::clearcode()
83 {
84 	code.size = 0;
85 }
86 
emitbyte(byte b)87 void Assembler::emitbyte(byte b)
88 {
89 	code.data[code.size] = b;
90 	code.size++;
91 }
92 
emitword(uint16 w)93 void Assembler::emitword(uint16 w)
94 {
95 	if (bigendian) {
96 		code.data[code.size+1] = (byte)w;
97 		code.data[code.size+0] = (byte)(w>>8);
98 	} else {
99 		code.data[code.size+0] = (byte)w;
100 		code.data[code.size+1] = (byte)(w>>8);
101 	}
102 	code.size += 2;
103 }
104 
emitdword(uint32 d)105 void Assembler::emitdword(uint32 d)
106 {
107 	if (bigendian) {
108 		code.data[code.size+3] = (byte)d;
109 		code.data[code.size+2] = (byte)(d>>8);
110 		code.data[code.size+1] = (byte)(d>>16);
111 		code.data[code.size+0] = (byte)(d>>24);
112 	} else {
113 		code.data[code.size+0] = (byte)d;
114 		code.data[code.size+1] = (byte)(d>>8);
115 		code.data[code.size+2] = (byte)(d>>16);
116 		code.data[code.size+3] = (byte)(d>>24);
117 	}
118 	code.size += 4;
119 }
120 
emitqword(uint64 q)121 void Assembler::emitqword(uint64 q)
122 {
123 	if (bigendian) {
124 		code.data[code.size+7] = (byte)q;
125 		code.data[code.size+6] = (byte)(q>>8);
126 		code.data[code.size+5] = (byte)(q>>16);
127 		code.data[code.size+4] = (byte)(q>>24);
128 		code.data[code.size+3] = (byte)(q>>32);
129 		code.data[code.size+2] = (byte)(q>>40);
130 		code.data[code.size+1] = (byte)(q>>48);
131 		code.data[code.size+0] = (byte)(q>>56);
132 	} else {
133 		code.data[code.size+0] = (byte)q;
134 		code.data[code.size+1] = (byte)(q>>8);
135 		code.data[code.size+2] = (byte)(q>>16);
136 		code.data[code.size+3] = (byte)(q>>24);
137 		code.data[code.size+4] = (byte)(q>>32);
138 		code.data[code.size+5] = (byte)(q>>40);
139 		code.data[code.size+6] = (byte)(q>>48);
140 		code.data[code.size+7] = (byte)(q>>56);
141 	}
142 	code.size += 8;
143 }
144 
free_asm_codes()145 void Assembler::free_asm_codes()
146 {
147 	while (codes) {
148 		asm_code *t = codes->next;
149 		delete codes;
150 		codes = t;
151 	}
152 }
153 
get_error_msg()154 const char *Assembler::get_error_msg()
155 {
156 	return error_msg;
157 }
158 
get_name()159 const char *Assembler::get_name()
160 {
161 	return "generic asm";
162 }
163 
newcode()164 void Assembler::newcode()
165 {
166 	code.size = 0;
167 }
168 
shortest(asm_code * codes)169 asm_code *Assembler::shortest(asm_code *codes)
170 {
171 	asm_code *best = NULL;
172 	int bestv = INT_MAX;
173 	while (codes) {
174 		if (codes->size < bestv) {
175 			best = codes;
176 			bestv = codes->size;
177 		}
178 		codes = codes->next;
179 	}
180 	return best;
181 }
182 
pushcode()183 void Assembler::pushcode()
184 {
185 	asm_code **t=&codes;
186 	while (*t) {
187 		t = &(*t)->next;
188 	}
189 	*t = new asm_code;
190 
191 	memcpy(*t, &code, sizeof code);
192 	(*t)->next = NULL;
193 }
194 
set_error_msg(const char * format,...)195 void Assembler::set_error_msg(const char *format, ...)
196 {
197 	va_list arg;
198 	va_start(arg, format);
199 	vsprintf(error_msg, format, arg);
200 	va_end(arg);
201 	error=1;
202 }
203 
set_imm_eval_proc(int (* p)(void * context,const char * s,uint64 & v),void * c)204 void Assembler::set_imm_eval_proc(int (*p)(void *context, const char *s, uint64 &v), void *c)
205 {
206 	imm_eval_proc = p;
207 	imm_eval_context = c;
208 }
209 
210 /*
211  *	CLASS disassembler
212  */
213 
Disassembler()214 Disassembler::Disassembler()
215 {
216 	disable_highlighting();
217 }
218 
load(ObjectStream & f)219 void Disassembler::load(ObjectStream &f)
220 {
221 	disable_highlighting();
222 }
223 
224 char* (*addr_sym_func)(CPU_ADDR addr, int *symstrlen, void *context) = NULL;
225 void* addr_sym_func_context = NULL;
226 
createInvalidInsn()227 dis_insn *Disassembler::createInvalidInsn()
228 {
229 	return NULL;
230 }
231 
hexd(char ** s,int size,int options,uint32 imm)232 void Disassembler::hexd(char **s, int size, int options, uint32 imm)
233 {
234 	char ff[16];
235 	char *f = (char*)&ff;
236 	char *t = *s;
237 	*f++ = '%';
238 	if (imm >= 0 && imm <= 9) {
239 		*s += sprintf(*s, "%d", imm);
240 	} else if (options & DIS_STYLE_SIGNED) {
241 		if (!(options & DIS_STYLE_HEX_NOZEROPAD)) f += sprintf(f, "0%d", size);
242 		*f++ = 'd';
243 		*f = 0;
244 		*s += sprintf(*s, ff, imm);
245 	} else {
246 		if (options & DIS_STYLE_HEX_CSTYLE) *f++ = '#';
247 		if (!(options & DIS_STYLE_HEX_NOZEROPAD)) f += sprintf(f, "0%d", size);
248 		if (options & DIS_STYLE_HEX_UPPERCASE) *f++ = 'X'; else
249 			*f++ = 'x';
250 		if (options & DIS_STYLE_HEX_ASMSTYLE) *f++ = 'h';
251 		*f = 0;
252 		*s += sprintf(*s, ff, imm);
253 		if ((options & DIS_STYLE_HEX_NOZEROPAD) && (*t-'0'>9)) {
254 			memmove(t+1, t, strlen(t)+1);
255 			*t = '0';
256 			(*s)++;
257 		}
258 	}
259 }
260 
hexq(char ** s,int size,int options,uint64 imm)261 void Disassembler::hexq(char **s, int size, int options, uint64 imm)
262 {
263 	char ff[32];
264 	char *f = (char*)&ff;
265 	char *t = *s;
266 	*f++ = '%';
267 	if (imm >= 0 && imm <= 9) {
268 		*s += ht_snprintf(*s, 32, "%qd", imm);
269 	} else if (options & DIS_STYLE_SIGNED) {
270 		if (!(options & DIS_STYLE_HEX_NOZEROPAD)) f += sprintf(f, "0%d", size);
271 		*f++ = 'q';
272 		*f++ = 'd';
273 		*f = 0;
274 		*s += ht_snprintf(*s, 32, ff, imm);
275 	} else {
276 		if (options & DIS_STYLE_HEX_CSTYLE) *f++ = '#';
277 		if (!(options & DIS_STYLE_HEX_NOZEROPAD)) f += sprintf(f, "0%d", size);
278 		if (options & DIS_STYLE_HEX_UPPERCASE) *f++ = 'X'; else
279 		*f++ = 'q';
280 		*f++ = 'x';
281 		if (options & DIS_STYLE_HEX_ASMSTYLE) *f++ = 'h';
282 		*f = 0;
283 		*s += ht_snprintf(*s, 32, ff, imm);
284 		if ((options & DIS_STYLE_HEX_NOZEROPAD) && (*t-'0'>9)) {
285 			memmove(t+1, t, strlen(t)+1);
286 			*t = '0';
287 			(*s)++;
288 		}
289 	}
290 }
291 
selectNext(dis_insn * disasm_insn)292 bool Disassembler::selectNext(dis_insn *disasm_insn)
293 {
294 	return false;
295 }
296 
str(dis_insn * disasm_insn,int style)297 const char *Disassembler::str(dis_insn *disasm_insn, int style)
298 {
299 	return strf(disasm_insn, style, DISASM_STRF_DEFAULT_FORMAT);
300 }
301 
get_cs(AsmSyntaxHighlightEnum style)302 const char *Disassembler::get_cs(AsmSyntaxHighlightEnum style)
303 {
304 	const char *highlights[] = {
305 		ASM_SYNTAX_DEFAULT,
306 		ASM_SYNTAX_COMMENT,
307 		ASM_SYNTAX_NUMBER,
308 		ASM_SYNTAX_SYMBOL,
309 		ASM_SYNTAX_STRING
310 	};
311 	return highlight ? highlights[(int)style] : "";
312 }
313 
enable_highlighting()314 void Disassembler::enable_highlighting()
315 {
316 	highlight = true;
317 }
318 
disable_highlighting()319 void Disassembler::disable_highlighting()
320 {
321 	highlight = false;
322 }
323 
BUILDER(ATOM_DISASM_X86,x86dis,Disassembler)324 BUILDER(ATOM_DISASM_X86, x86dis, Disassembler)
325 BUILDER(ATOM_DISASM_X86_64, x86_64dis, x86dis)
326 BUILDER(ATOM_DISASM_X86_VXD, x86dis_vxd, x86dis)
327 BUILDER(ATOM_DISASM_ALPHA, Alphadis, Disassembler)
328 BUILDER(ATOM_DISASM_JAVA, javadis, Disassembler)
329 BUILDER(ATOM_DISASM_PPC, PPCDisassembler, Disassembler)
330 BUILDER(ATOM_DISASM_IL, ILDisassembler, Disassembler)
331 BUILDER(ATOM_DISASM_ARM, ArmDisassembler, Disassembler)
332 BUILDER(ATOM_DISASM_AVR, AVRDisassembler, Disassembler)
333 
334 bool init_asm()
335 {
336 	REGISTER(ATOM_DISASM_X86, x86dis)
337 	REGISTER(ATOM_DISASM_X86_VXD, x86dis_vxd)
338 	REGISTER(ATOM_DISASM_ALPHA, Alphadis)
339 	REGISTER(ATOM_DISASM_JAVA, javadis)
340 	REGISTER(ATOM_DISASM_PPC, PPCDisassembler)
341 	REGISTER(ATOM_DISASM_IL, ILDisassembler)
342 	REGISTER(ATOM_DISASM_X86_64, x86_64dis)
343 	REGISTER(ATOM_DISASM_ARM, ArmDisassembler)
344 	REGISTER(ATOM_DISASM_AVR, AVRDisassembler)
345 	return true;
346 }
347 
done_asm()348 void done_asm()
349 {
350 	UNREGISTER(ATOM_DISASM_ARM, ArmDisassembler)
351 	UNREGISTER(ATOM_DISASM_X86_64, x86dis)
352 	UNREGISTER(ATOM_DISASM_IL, ILDisassembler)
353 	UNREGISTER(ATOM_DISASM_PPC, PPCDisassembler)
354 	UNREGISTER(ATOM_DISASM_JAVA, javadis)
355 	UNREGISTER(ATOM_DISASM_ALPHA, Alphadis)
356 	UNREGISTER(ATOM_DISASM_X86_VXD, x86dis_vxd)
357 	UNREGISTER(ATOM_DISASM_X86, x86dis)
358 	UNREGISTER(ATOM_DISASM_AVR, AVRDisassembler)
359 }
360 
361