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