/[pearpc]/src/debug/ppcdis.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /src/debug/ppcdis.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 8 months ago) by dpavlin
File size: 9200 byte(s)
import upstream CVS
1 dpavlin 1 /*
2     * HT Editor
3     * ppcdis.cc
4     *
5     * Copyright (C) 1999-2002 Sebastian Biallas (sb@web-productions.de)
6     * Copyright 1994 Free Software Foundation, Inc.
7     * Written by Ian Lance Taylor, Cygnus Support
8     *
9     * This program is free software; you can redistribute it and/or modify
10     * it under the terms of the GNU General Public License version 2 as
11     * published by the Free Software Foundation.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21     */
22    
23     #include <cstdlib>
24     #include <cstring>
25    
26     #include "tools/endianess.h"
27     #include "tools/snprintf.h"
28     #include "ppcdis.h"
29     #include "ppcopc.h"
30    
31     PPCDisassembler::PPCDisassembler()
32     {
33     }
34    
35     dis_insn *PPCDisassembler::decode(const byte *code, int maxlen, CPU_ADDR addr)
36     {
37     const struct powerpc_opcode *opcode;
38     const struct powerpc_opcode *opcode_end;
39     uint32 op;
40     int dialect = -1;
41    
42     insn.data = createHostInt(code, 4, little_endian);
43    
44     if (maxlen<4) {
45     insn.valid = false;
46     insn.size = maxlen;
47     return &insn;
48     }
49    
50     insn.size = 4;
51    
52     /* Get the major opcode of the instruction. */
53     op = PPC_OP(insn.data);
54    
55     /* Find the first match in the opcode table. We could speed this up
56     a bit by doing a binary search on the major opcode. */
57     opcode_end = powerpc_opcodes + powerpc_num_opcodes;
58    
59     for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++) {
60     uint32 table_op;
61     const byte *opindex;
62     const struct powerpc_operand *operand;
63     bool invalid;
64     bool need_comma;
65     bool need_paren;
66    
67     table_op = PPC_OP (opcode->opcode);
68     if (op < table_op) break;
69     if (op > table_op) continue;
70    
71     if ((insn.data & opcode->mask) != opcode->opcode || (opcode->flags & dialect) == 0) {
72     continue;
73     }
74    
75     /* Make two passes over the operands. First see if any of them
76     have extraction functions, and, if they do, make sure the
77     instruction is valid. */
78     invalid = false;
79     for (opindex = opcode->operands; *opindex != 0; opindex++) {
80     operand = powerpc_operands + *opindex;
81     if (operand->extract) (*operand->extract)(insn.data, &invalid);
82     }
83     if (invalid) continue;
84    
85     /* The instruction is valid. */
86     // fprintf(out, "%s", opcode->name);
87     insn.name = opcode->name;
88     // if (opcode->operands[0] != 0) fprintf(out, "\t");
89    
90     /* Now extract and print the operands. */
91     need_comma = false;
92     need_paren = false;
93     int opidx = 0;
94     for (opindex = opcode->operands; *opindex != 0; opindex++) {
95     uint32 value;
96    
97     operand = powerpc_operands + *opindex;
98    
99     /* Operands that are marked FAKE are simply ignored. We
100     already made sure that the extract function considered
101     the instruction to be valid. */
102     if ((operand->flags & PPC_OPERAND_FAKE) != 0) continue;
103    
104     insn.op[opidx].op = operand;
105     insn.op[opidx].flags = operand->flags;
106     /* Extract the value from the instruction. */
107     if (operand->extract) {
108     value = (*operand->extract)(insn.data, NULL);
109     } else {
110     value = (insn.data >> operand->shift) & ((1 << operand->bits) - 1);
111     if ((operand->flags & PPC_OPERAND_SIGNED) != 0 && (value & (1 << (operand->bits - 1))) != 0) {
112     value -= 1 << operand->bits;
113     }
114     }
115    
116     /* If the operand is optional, and the value is zero, don't
117     print anything. */
118     if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 && (operand->flags & PPC_OPERAND_NEXT) == 0 && value == 0) {
119     insn.op[opidx++].imm = 0;
120     continue;
121     }
122    
123     if (need_comma) {
124     // fprintf(out, ", ");
125     need_comma = false;
126     }
127    
128     /* Print the operand as directed by the flags. */
129     if ((operand->flags & PPC_OPERAND_GPR) != 0) {
130     insn.op[opidx++].reg = value;
131     } else if ((operand->flags & PPC_OPERAND_FPR) != 0) {
132     insn.op[opidx++].freg = value;
133     } else if ((operand->flags & PPC_OPERAND_VR) != 0) {
134     insn.op[opidx++].vreg = value;
135     } else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0) {
136     insn.op[opidx++].rel.mem = addr.addr32.offset + value;
137     } else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) {
138     insn.op[opidx++].abs.mem = value;
139     } else if ((operand->flags & PPC_OPERAND_CR) == 0 || (dialect & PPC_OPCODE_PPC) == 0) {
140     insn.op[opidx++].imm = value;
141     } else {
142     insn.op[opidx++].creg = value;
143     if (operand->bits == 3) {
144     // fprintf(out, "cr%d", value);
145     } else {
146    
147     // static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
148     int cr;
149     int cc;
150     cr = value >> 2;
151     // if (cr != 0) fprintf(out, "4*cr%d", cr);
152     cc = value & 3;
153     if (cc != 0) {
154     // if (cr != 0) fprintf(out, "+");
155     // fprintf(out, "%s", cbnames[cc]);
156     }
157     }
158     }
159    
160     if (need_paren) {
161     // fprintf(out, ")");
162     need_paren = false;
163     }
164    
165     if ((operand->flags & PPC_OPERAND_PARENS) == 0) {
166     need_comma = true;
167     } else {
168     // fprintf(out, "(");
169     need_paren = true;
170     }
171     }
172     insn.ops = opidx;
173    
174     /* We have found and printed an instruction; return. */
175     insn.valid = true;
176     return &insn;
177     }
178    
179     insn.valid = false;
180     return &insn;
181     }
182    
183     dis_insn *PPCDisassembler::duplicateInsn(dis_insn *disasm_insn)
184     {
185     ppcdis_insn *insn = (ppcdis_insn *)malloc(sizeof (ppcdis_insn));
186     *insn = *(ppcdis_insn *)disasm_insn;
187     return insn;
188     }
189    
190     void PPCDisassembler::getOpcodeMetrics(int &min_length, int &max_length, int &min_look_ahead, int &avg_look_ahead, int &addr_align)
191     {
192     min_length = max_length = min_look_ahead = avg_look_ahead = addr_align = 4;
193     }
194    
195     byte PPCDisassembler::getSize(dis_insn *disasm_insn)
196     {
197     return ((ppcdis_insn*)disasm_insn)->size;
198     }
199    
200     char *PPCDisassembler::getName()
201     {
202     return "PPC/Disassembler";
203     }
204    
205     char *PPCDisassembler::str(dis_insn *disasm_insn, int style)
206     {
207     return strf(disasm_insn, style, "");
208     }
209    
210     char *PPCDisassembler::strf(dis_insn *disasm_insn, int style, char *format)
211     {
212     if (style & DIS_STYLE_HIGHLIGHT) enable_highlighting();
213    
214     const char *cs_default = get_cs(e_cs_default);
215     const char *cs_number = get_cs(e_cs_number);
216     const char *cs_symbol = get_cs(e_cs_symbol);
217    
218     ppcdis_insn *ppc_insn = (ppcdis_insn *) disasm_insn;
219     if (!ppc_insn->valid) {
220     switch (ppc_insn->size) {
221     case 1:
222     strcpy(insnstr, "db ?");
223     break;
224     case 2:
225     strcpy(insnstr, "dw ?");
226     break;
227     case 3:
228     strcpy(insnstr, "db ? * 3");
229     break;
230     case 4:
231     ht_snprintf(insnstr, sizeof insnstr, "dd %s0x%08x", cs_number, ppc_insn->data);
232     break;
233     default: { /* braces for empty assert */
234     }
235     }
236     } else {
237     char *is = insnstr+sprintf(insnstr, "%-10s", ppc_insn->name);
238     int dialect=-1;
239    
240     bool need_comma = false;
241     bool need_paren = false;
242     for (int opidx = 0; opidx < ppc_insn->ops; opidx++) {
243     int flags = ppc_insn->op[opidx].flags;
244     /* if ((flags & PPC_OPERAND_OPTIONAL) != 0 && (flags & PPC_OPERAND_NEXT) == 0 && ppc_insn->op[opidx].imm == 0) {
245     continue;
246     }*/
247     if (need_comma) {
248     is += sprintf(is, "%s, ", cs_symbol);
249     need_comma = false;
250     }
251     if ((flags & PPC_OPERAND_GPR) != 0) {
252     is += sprintf(is, "%sr%d", cs_default, ppc_insn->op[opidx].reg);
253     } else if ((flags & PPC_OPERAND_FPR) != 0) {
254     is += sprintf(is, "%sf%d", cs_default, ppc_insn->op[opidx].freg);
255     } else if ((flags & PPC_OPERAND_VR) != 0) {
256     is += sprintf(is, "%svr%d", cs_default, ppc_insn->op[opidx].vreg);
257     } else if ((flags & PPC_OPERAND_RELATIVE) != 0) {
258     CPU_ADDR caddr;
259     caddr.addr32.offset = (uint32)ppc_insn->op[opidx].mem.disp;
260     int slen;
261     char *s = (addr_sym_func) ? addr_sym_func(caddr, &slen, addr_sym_func_context) : 0;
262     if (s) {
263     is += sprintf(is, "%s", cs_default);
264     memmove(is, s, slen);
265     is[slen] = 0;
266     is += slen;
267     } else {
268     is += sprintf(is, "%s0x%x", cs_number, ppc_insn->op[opidx].rel.mem);
269     }
270     } else if ((flags & PPC_OPERAND_ABSOLUTE) != 0) {
271     is += sprintf(is, "%s0x%x", cs_number, ppc_insn->op[opidx].abs.mem);
272     } else if ((flags & PPC_OPERAND_CR) == 0 || (dialect & PPC_OPCODE_PPC) == 0) {
273     is += sprintf(is, "%s%d", cs_number, ppc_insn->op[opidx].imm);
274     } else if (ppc_insn->op[opidx].op->bits == 3) {
275     is += sprintf(is, "%scr%d", cs_default, ppc_insn->op[opidx].creg);
276     } else {
277     static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
278     int cr;
279     int cc;
280     cr = ppc_insn->op[opidx].creg >> 2;
281     if (cr != 0) is += sprintf(is, "%s4%s*%scr%d", cs_number, cs_symbol, cs_default, cr);
282     cc = ppc_insn->op[opidx].creg & 3;
283     if (cc != 0) {
284     if (cr != 0) is += sprintf(is, "%s+", cs_symbol);
285     is += sprintf(is, "%s%s", cs_default, cbnames[cc]);
286     }
287     }
288    
289     if (need_paren) {
290     is += sprintf(is, "%s)", cs_symbol);
291     need_paren = false;
292     }
293    
294     if ((flags & PPC_OPERAND_PARENS) == 0) {
295     need_comma = true;
296     } else {
297     is += sprintf(is, "%s(", cs_symbol);
298     need_paren = true;
299     }
300     }
301     }
302     disable_highlighting();
303     return insnstr;
304     }
305    
306     ObjectID PPCDisassembler::getObjectID() const
307     {
308     return 0;
309     }
310    
311     bool PPCDisassembler::validInsn(dis_insn *disasm_insn)
312     {
313     return ((ppcdis_insn*)disasm_insn)->valid;
314     }
315    
316    

  ViewVC Help
Powered by ViewVC 1.1.26