Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/xmon/ppc-dis.c
10817 views
1
/* ppc-dis.c -- Disassemble PowerPC instructions
2
Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006
3
Free Software Foundation, Inc.
4
Written by Ian Lance Taylor, Cygnus Support
5
6
This file is part of GDB, GAS, and the GNU binutils.
7
8
GDB, GAS, and the GNU binutils are free software; you can redistribute
9
them and/or modify them under the terms of the GNU General Public
10
License as published by the Free Software Foundation; either version
11
2, or (at your option) any later version.
12
13
GDB, GAS, and the GNU binutils are distributed in the hope that they
14
will be useful, but WITHOUT ANY WARRANTY; without even the implied
15
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
16
the 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 file; see the file COPYING. If not, write to the Free
20
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
21
22
#include <asm/cputable.h>
23
#include "nonstdio.h"
24
#include "ansidecl.h"
25
#include "ppc.h"
26
#include "dis-asm.h"
27
28
/* Print a PowerPC or POWER instruction. */
29
30
int
31
print_insn_powerpc (unsigned long insn, unsigned long memaddr)
32
{
33
const struct powerpc_opcode *opcode;
34
const struct powerpc_opcode *opcode_end;
35
unsigned long op;
36
int dialect;
37
38
dialect = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON
39
| PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_ALTIVEC;
40
41
if (cpu_has_feature(CPU_FTRS_POWER5))
42
dialect |= PPC_OPCODE_POWER5;
43
44
if (cpu_has_feature(CPU_FTRS_CELL))
45
dialect |= PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC;
46
47
if (cpu_has_feature(CPU_FTRS_POWER6))
48
dialect |= PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC;
49
50
/* Get the major opcode of the instruction. */
51
op = PPC_OP (insn);
52
53
/* Find the first match in the opcode table. We could speed this up
54
a bit by doing a binary search on the major opcode. */
55
opcode_end = powerpc_opcodes + powerpc_num_opcodes;
56
again:
57
for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
58
{
59
unsigned long table_op;
60
const unsigned char *opindex;
61
const struct powerpc_operand *operand;
62
int invalid;
63
int need_comma;
64
int need_paren;
65
66
table_op = PPC_OP (opcode->opcode);
67
if (op < table_op)
68
break;
69
if (op > table_op)
70
continue;
71
72
if ((insn & opcode->mask) != opcode->opcode
73
|| (opcode->flags & dialect) == 0)
74
continue;
75
76
/* Make two passes over the operands. First see if any of them
77
have extraction functions, and, if they do, make sure the
78
instruction is valid. */
79
invalid = 0;
80
for (opindex = opcode->operands; *opindex != 0; opindex++)
81
{
82
operand = powerpc_operands + *opindex;
83
if (operand->extract)
84
(*operand->extract) (insn, dialect, &invalid);
85
}
86
if (invalid)
87
continue;
88
89
/* The instruction is valid. */
90
printf("%s", opcode->name);
91
if (opcode->operands[0] != 0)
92
printf("\t");
93
94
/* Now extract and print the operands. */
95
need_comma = 0;
96
need_paren = 0;
97
for (opindex = opcode->operands; *opindex != 0; opindex++)
98
{
99
long value;
100
101
operand = powerpc_operands + *opindex;
102
103
/* Operands that are marked FAKE are simply ignored. We
104
already made sure that the extract function considered
105
the instruction to be valid. */
106
if ((operand->flags & PPC_OPERAND_FAKE) != 0)
107
continue;
108
109
/* Extract the value from the instruction. */
110
if (operand->extract)
111
value = (*operand->extract) (insn, dialect, &invalid);
112
else
113
{
114
value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
115
if ((operand->flags & PPC_OPERAND_SIGNED) != 0
116
&& (value & (1 << (operand->bits - 1))) != 0)
117
value -= 1 << operand->bits;
118
}
119
120
/* If the operand is optional, and the value is zero, don't
121
print anything. */
122
if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
123
&& (operand->flags & PPC_OPERAND_NEXT) == 0
124
&& value == 0)
125
continue;
126
127
if (need_comma)
128
{
129
printf(",");
130
need_comma = 0;
131
}
132
133
/* Print the operand as directed by the flags. */
134
if ((operand->flags & PPC_OPERAND_GPR) != 0
135
|| ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
136
printf("r%ld", value);
137
else if ((operand->flags & PPC_OPERAND_FPR) != 0)
138
printf("f%ld", value);
139
else if ((operand->flags & PPC_OPERAND_VR) != 0)
140
printf("v%ld", value);
141
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
142
print_address (memaddr + value);
143
else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
144
print_address (value & 0xffffffff);
145
else if ((operand->flags & PPC_OPERAND_CR) == 0
146
|| (dialect & PPC_OPCODE_PPC) == 0)
147
printf("%ld", value);
148
else
149
{
150
if (operand->bits == 3)
151
printf("cr%ld", value);
152
else
153
{
154
static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
155
int cr;
156
int cc;
157
158
cr = value >> 2;
159
if (cr != 0)
160
printf("4*cr%d+", cr);
161
cc = value & 3;
162
printf("%s", cbnames[cc]);
163
}
164
}
165
166
if (need_paren)
167
{
168
printf(")");
169
need_paren = 0;
170
}
171
172
if ((operand->flags & PPC_OPERAND_PARENS) == 0)
173
need_comma = 1;
174
else
175
{
176
printf("(");
177
need_paren = 1;
178
}
179
}
180
181
/* We have found and printed an instruction; return. */
182
return 4;
183
}
184
185
if ((dialect & PPC_OPCODE_ANY) != 0)
186
{
187
dialect = ~PPC_OPCODE_ANY;
188
goto again;
189
}
190
191
/* We could not find a match. */
192
printf(".long 0x%lx", insn);
193
194
return 4;
195
}
196
197