ppc-dis.c revision 1.6.4.1 1 1.1 christos /* ppc-dis.c -- Disassemble PowerPC instructions
2 1.6.4.1 christos Copyright (C) 1994-2017 Free Software Foundation, Inc.
3 1.1 christos Written by Ian Lance Taylor, Cygnus Support
4 1.1 christos
5 1.1 christos This file is part of the GNU opcodes library.
6 1.1 christos
7 1.1 christos This library is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3, or (at your option)
10 1.1 christos any later version.
11 1.1 christos
12 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT
13 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 1.1 christos License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this file; see the file COPYING. If not, write to the
19 1.1 christos Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 1.1 christos MA 02110-1301, USA. */
21 1.1 christos
22 1.1 christos #include "sysdep.h"
23 1.1 christos #include <stdio.h>
24 1.1 christos #include "dis-asm.h"
25 1.1 christos #include "elf-bfd.h"
26 1.1 christos #include "elf/ppc.h"
27 1.1 christos #include "opintl.h"
28 1.1 christos #include "opcode/ppc.h"
29 1.6.4.1 christos #include "libiberty.h"
30 1.1 christos
31 1.1 christos /* This file provides several disassembler functions, all of which use
32 1.1 christos the disassembler interface defined in dis-asm.h. Several functions
33 1.1 christos are provided because this file handles disassembly for the PowerPC
34 1.1 christos in both big and little endian mode and also for the POWER (RS/6000)
35 1.1 christos chip. */
36 1.1 christos static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int,
37 1.1 christos ppc_cpu_t);
38 1.1 christos
39 1.1 christos struct dis_private
40 1.1 christos {
41 1.1 christos /* Stash the result of parsing disassembler_options here. */
42 1.1 christos ppc_cpu_t dialect;
43 1.1 christos } private;
44 1.1 christos
45 1.1 christos #define POWERPC_DIALECT(INFO) \
46 1.1 christos (((struct dis_private *) ((INFO)->private_data))->dialect)
47 1.1 christos
48 1.1 christos struct ppc_mopt {
49 1.6.4.1 christos /* Option string, without -m or -M prefix. */
50 1.1 christos const char *opt;
51 1.6.4.1 christos /* CPU option flags. */
52 1.1 christos ppc_cpu_t cpu;
53 1.6.4.1 christos /* Flags that should stay on, even when combined with another cpu
54 1.6.4.1 christos option. This should only be used for generic options like
55 1.6.4.1 christos "-many" or "-maltivec" where it is reasonable to add some
56 1.6.4.1 christos capability to another cpu selection. The added flags are sticky
57 1.6.4.1 christos so that, for example, "-many -me500" and "-me500 -many" result in
58 1.6.4.1 christos the same assembler or disassembler behaviour. Do not use
59 1.6.4.1 christos "sticky" for specific cpus, as this will prevent that cpu's flags
60 1.6.4.1 christos from overriding the defaults set in powerpc_init_dialect or a
61 1.6.4.1 christos prior -m option. */
62 1.1 christos ppc_cpu_t sticky;
63 1.1 christos };
64 1.1 christos
65 1.1 christos struct ppc_mopt ppc_opts[] = {
66 1.6 christos { "403", PPC_OPCODE_PPC | PPC_OPCODE_403,
67 1.1 christos 0 },
68 1.6 christos { "405", PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_405,
69 1.1 christos 0 },
70 1.1 christos { "440", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
71 1.1 christos | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
72 1.1 christos 0 },
73 1.1 christos { "464", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_440
74 1.1 christos | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
75 1.1 christos 0 },
76 1.6.4.1 christos { "476", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_476
77 1.6.4.1 christos | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
78 1.1 christos 0 },
79 1.6 christos { "601", PPC_OPCODE_PPC | PPC_OPCODE_601,
80 1.1 christos 0 },
81 1.6 christos { "603", PPC_OPCODE_PPC,
82 1.1 christos 0 },
83 1.6 christos { "604", PPC_OPCODE_PPC,
84 1.1 christos 0 },
85 1.6 christos { "620", PPC_OPCODE_PPC | PPC_OPCODE_64,
86 1.1 christos 0 },
87 1.6 christos { "7400", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
88 1.1 christos 0 },
89 1.6 christos { "7410", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
90 1.1 christos 0 },
91 1.6 christos { "7450", PPC_OPCODE_PPC | PPC_OPCODE_7450 | PPC_OPCODE_ALTIVEC,
92 1.1 christos 0 },
93 1.6 christos { "7455", PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC,
94 1.1 christos 0 },
95 1.6 christos { "750cl", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
96 1.1 christos , 0 },
97 1.6 christos { "821", PPC_OPCODE_PPC | PPC_OPCODE_860,
98 1.5 christos 0 },
99 1.6 christos { "850", PPC_OPCODE_PPC | PPC_OPCODE_860,
100 1.5 christos 0 },
101 1.6 christos { "860", PPC_OPCODE_PPC | PPC_OPCODE_860,
102 1.5 christos 0 },
103 1.1 christos { "a2", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_POWER4
104 1.1 christos | PPC_OPCODE_POWER5 | PPC_OPCODE_CACHELCK | PPC_OPCODE_64
105 1.1 christos | PPC_OPCODE_A2),
106 1.1 christos 0 },
107 1.6 christos { "altivec", PPC_OPCODE_PPC,
108 1.6.4.1 christos PPC_OPCODE_ALTIVEC },
109 1.6.4.1 christos { "any", PPC_OPCODE_PPC,
110 1.1 christos PPC_OPCODE_ANY },
111 1.6 christos { "booke", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
112 1.1 christos 0 },
113 1.6 christos { "booke32", PPC_OPCODE_PPC | PPC_OPCODE_BOOKE,
114 1.1 christos 0 },
115 1.1 christos { "cell", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
116 1.1 christos | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC),
117 1.1 christos 0 },
118 1.6 christos { "com", PPC_OPCODE_COMMON,
119 1.1 christos 0 },
120 1.6.4.1 christos { "e200z4", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
121 1.6.4.1 christos | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
122 1.6.4.1 christos | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
123 1.6.4.1 christos | PPC_OPCODE_E500 | PPC_OPCODE_VLE | PPC_OPCODE_E200Z4),
124 1.6.4.1 christos 0 },
125 1.6 christos { "e300", PPC_OPCODE_PPC | PPC_OPCODE_E300,
126 1.1 christos 0 },
127 1.1 christos { "e500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
128 1.1 christos | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
129 1.1 christos | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
130 1.1 christos | PPC_OPCODE_E500),
131 1.1 christos 0 },
132 1.1 christos { "e500mc", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
133 1.1 christos | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
134 1.1 christos | PPC_OPCODE_E500MC),
135 1.1 christos 0 },
136 1.1 christos { "e500mc64", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
137 1.1 christos | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
138 1.1 christos | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
139 1.1 christos | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
140 1.1 christos 0 },
141 1.1 christos { "e5500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
142 1.1 christos | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
143 1.1 christos | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
144 1.6.4.1 christos | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
145 1.1 christos 0 },
146 1.1 christos { "e6500", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
147 1.1 christos | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
148 1.1 christos | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_ALTIVEC
149 1.6.4.1 christos | PPC_OPCODE_E6500 | PPC_OPCODE_TMR | PPC_OPCODE_POWER4
150 1.1 christos | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
151 1.1 christos 0 },
152 1.1 christos { "e500x2", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
153 1.1 christos | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
154 1.1 christos | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
155 1.1 christos | PPC_OPCODE_E500),
156 1.1 christos 0 },
157 1.6 christos { "efs", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
158 1.1 christos 0 },
159 1.6 christos { "power4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
160 1.1 christos 0 },
161 1.1 christos { "power5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
162 1.1 christos | PPC_OPCODE_POWER5),
163 1.1 christos 0 },
164 1.1 christos { "power6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
165 1.1 christos | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
166 1.1 christos 0 },
167 1.1 christos { "power7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
168 1.1 christos | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
169 1.1 christos | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
170 1.1 christos 0 },
171 1.1 christos { "power8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
172 1.1 christos | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
173 1.6.4.1 christos | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
174 1.6.4.1 christos | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
175 1.1 christos 0 },
176 1.6 christos { "power9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
177 1.6 christos | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
178 1.6 christos | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
179 1.6.4.1 christos | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
180 1.6 christos 0 },
181 1.6 christos { "ppc", PPC_OPCODE_PPC,
182 1.1 christos 0 },
183 1.6 christos { "ppc32", PPC_OPCODE_PPC,
184 1.1 christos 0 },
185 1.6.4.1 christos { "32", PPC_OPCODE_PPC,
186 1.6.4.1 christos 0 },
187 1.6 christos { "ppc64", PPC_OPCODE_PPC | PPC_OPCODE_64,
188 1.1 christos 0 },
189 1.6.4.1 christos { "64", PPC_OPCODE_PPC | PPC_OPCODE_64,
190 1.6.4.1 christos 0 },
191 1.6 christos { "ppc64bridge", PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE,
192 1.1 christos 0 },
193 1.6 christos { "ppcps", PPC_OPCODE_PPC | PPC_OPCODE_PPCPS,
194 1.1 christos 0 },
195 1.6 christos { "pwr", PPC_OPCODE_POWER,
196 1.1 christos 0 },
197 1.6 christos { "pwr2", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
198 1.1 christos 0 },
199 1.6 christos { "pwr4", PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4,
200 1.1 christos 0 },
201 1.1 christos { "pwr5", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
202 1.1 christos | PPC_OPCODE_POWER5),
203 1.1 christos 0 },
204 1.1 christos { "pwr5x", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
205 1.1 christos | PPC_OPCODE_POWER5),
206 1.1 christos 0 },
207 1.1 christos { "pwr6", (PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4
208 1.1 christos | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC),
209 1.1 christos 0 },
210 1.1 christos { "pwr7", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
211 1.1 christos | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
212 1.1 christos | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
213 1.1 christos 0 },
214 1.1 christos { "pwr8", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
215 1.1 christos | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
216 1.6.4.1 christos | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8
217 1.6.4.1 christos | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
218 1.1 christos 0 },
219 1.6 christos { "pwr9", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
220 1.6 christos | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
221 1.6 christos | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
222 1.6.4.1 christos | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
223 1.6 christos 0 },
224 1.6 christos { "pwrx", PPC_OPCODE_POWER | PPC_OPCODE_POWER2,
225 1.1 christos 0 },
226 1.6.4.1 christos { "raw", PPC_OPCODE_PPC,
227 1.6.4.1 christos PPC_OPCODE_RAW },
228 1.6 christos { "spe", PPC_OPCODE_PPC | PPC_OPCODE_EFS,
229 1.1 christos PPC_OPCODE_SPE },
230 1.1 christos { "titan", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
231 1.1 christos | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
232 1.1 christos 0 },
233 1.6 christos { "vle", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE| PPC_OPCODE_SPE
234 1.6 christos | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
235 1.6 christos | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
236 1.6 christos | PPC_OPCODE_E500),
237 1.1 christos PPC_OPCODE_VLE },
238 1.6 christos { "vsx", PPC_OPCODE_PPC,
239 1.6.4.1 christos PPC_OPCODE_VSX },
240 1.1 christos };
241 1.1 christos
242 1.1 christos /* Switch between Booke and VLE dialects for interlinked dumps. */
243 1.1 christos static ppc_cpu_t
244 1.1 christos get_powerpc_dialect (struct disassemble_info *info)
245 1.1 christos {
246 1.1 christos ppc_cpu_t dialect = 0;
247 1.1 christos
248 1.1 christos dialect = POWERPC_DIALECT (info);
249 1.1 christos
250 1.1 christos /* Disassemble according to the section headers flags for VLE-mode. */
251 1.1 christos if (dialect & PPC_OPCODE_VLE
252 1.6.4.1 christos && info->section != NULL && info->section->owner != NULL
253 1.1 christos && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour
254 1.1 christos && elf_object_id (info->section->owner) == PPC32_ELF_DATA
255 1.1 christos && (elf_section_flags (info->section) & SHF_PPC_VLE) != 0)
256 1.1 christos return dialect;
257 1.1 christos else
258 1.1 christos return dialect & ~ PPC_OPCODE_VLE;
259 1.1 christos }
260 1.1 christos
261 1.1 christos /* Handle -m and -M options that set cpu type, and .machine arg. */
262 1.1 christos
263 1.1 christos ppc_cpu_t
264 1.1 christos ppc_parse_cpu (ppc_cpu_t ppc_cpu, ppc_cpu_t *sticky, const char *arg)
265 1.1 christos {
266 1.1 christos unsigned int i;
267 1.1 christos
268 1.6.4.1 christos for (i = 0; i < ARRAY_SIZE (ppc_opts); i++)
269 1.6.4.1 christos if (disassembler_options_cmp (ppc_opts[i].opt, arg) == 0)
270 1.1 christos {
271 1.1 christos if (ppc_opts[i].sticky)
272 1.1 christos {
273 1.1 christos *sticky |= ppc_opts[i].sticky;
274 1.1 christos if ((ppc_cpu & ~*sticky) != 0)
275 1.1 christos break;
276 1.1 christos }
277 1.1 christos ppc_cpu = ppc_opts[i].cpu;
278 1.1 christos break;
279 1.1 christos }
280 1.6.4.1 christos if (i >= ARRAY_SIZE (ppc_opts))
281 1.1 christos return 0;
282 1.1 christos
283 1.1 christos ppc_cpu |= *sticky;
284 1.1 christos return ppc_cpu;
285 1.1 christos }
286 1.1 christos
287 1.1 christos /* Determine which set of machines to disassemble for. */
288 1.1 christos
289 1.1 christos static void
290 1.1 christos powerpc_init_dialect (struct disassemble_info *info)
291 1.1 christos {
292 1.1 christos ppc_cpu_t dialect = 0;
293 1.1 christos ppc_cpu_t sticky = 0;
294 1.1 christos struct dis_private *priv = calloc (sizeof (*priv), 1);
295 1.1 christos
296 1.1 christos if (priv == NULL)
297 1.1 christos priv = &private;
298 1.1 christos
299 1.1 christos switch (info->mach)
300 1.1 christos {
301 1.1 christos case bfd_mach_ppc_403:
302 1.1 christos case bfd_mach_ppc_403gc:
303 1.1 christos dialect = ppc_parse_cpu (dialect, &sticky, "403");
304 1.1 christos break;
305 1.1 christos case bfd_mach_ppc_405:
306 1.1 christos dialect = ppc_parse_cpu (dialect, &sticky, "405");
307 1.1 christos break;
308 1.1 christos case bfd_mach_ppc_601:
309 1.1 christos dialect = ppc_parse_cpu (dialect, &sticky, "601");
310 1.1 christos break;
311 1.1 christos case bfd_mach_ppc_a35:
312 1.1 christos case bfd_mach_ppc_rs64ii:
313 1.1 christos case bfd_mach_ppc_rs64iii:
314 1.1 christos dialect = ppc_parse_cpu (dialect, &sticky, "pwr2") | PPC_OPCODE_64;
315 1.1 christos break;
316 1.1 christos case bfd_mach_ppc_e500:
317 1.1 christos dialect = ppc_parse_cpu (dialect, &sticky, "e500");
318 1.1 christos break;
319 1.1 christos case bfd_mach_ppc_e500mc:
320 1.1 christos dialect = ppc_parse_cpu (dialect, &sticky, "e500mc");
321 1.1 christos break;
322 1.1 christos case bfd_mach_ppc_e500mc64:
323 1.1 christos dialect = ppc_parse_cpu (dialect, &sticky, "e500mc64");
324 1.1 christos break;
325 1.1 christos case bfd_mach_ppc_e5500:
326 1.1 christos dialect = ppc_parse_cpu (dialect, &sticky, "e5500");
327 1.1 christos break;
328 1.1 christos case bfd_mach_ppc_e6500:
329 1.1 christos dialect = ppc_parse_cpu (dialect, &sticky, "e6500");
330 1.1 christos break;
331 1.1 christos case bfd_mach_ppc_titan:
332 1.1 christos dialect = ppc_parse_cpu (dialect, &sticky, "titan");
333 1.1 christos break;
334 1.1 christos case bfd_mach_ppc_vle:
335 1.1 christos dialect = ppc_parse_cpu (dialect, &sticky, "vle");
336 1.1 christos break;
337 1.1 christos default:
338 1.6 christos dialect = ppc_parse_cpu (dialect, &sticky, "power9") | PPC_OPCODE_ANY;
339 1.6.4.1 christos break;
340 1.1 christos }
341 1.1 christos
342 1.6.4.1 christos const char *opt;
343 1.6.4.1 christos FOR_EACH_DISASSEMBLER_OPTION (opt, info->disassembler_options)
344 1.1 christos {
345 1.1 christos ppc_cpu_t new_cpu = 0;
346 1.1 christos
347 1.6.4.1 christos if (disassembler_options_cmp (opt, "32") == 0)
348 1.1 christos dialect &= ~(ppc_cpu_t) PPC_OPCODE_64;
349 1.6.4.1 christos else if (disassembler_options_cmp (opt, "64") == 0)
350 1.1 christos dialect |= PPC_OPCODE_64;
351 1.6.4.1 christos else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0)
352 1.6.4.1 christos dialect = new_cpu;
353 1.1 christos else
354 1.6.4.1 christos fprintf (stderr, _("warning: ignoring unknown -M%s option\n"), opt);
355 1.1 christos }
356 1.1 christos
357 1.1 christos info->private_data = priv;
358 1.1 christos POWERPC_DIALECT(info) = dialect;
359 1.1 christos }
360 1.1 christos
361 1.1 christos #define PPC_OPCD_SEGS 64
362 1.1 christos static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS+1];
363 1.1 christos #define VLE_OPCD_SEGS 32
364 1.1 christos static unsigned short vle_opcd_indices[VLE_OPCD_SEGS+1];
365 1.1 christos
366 1.1 christos /* Calculate opcode table indices to speed up disassembly,
367 1.1 christos and init dialect. */
368 1.1 christos
369 1.1 christos void
370 1.1 christos disassemble_init_powerpc (struct disassemble_info *info)
371 1.1 christos {
372 1.1 christos int i;
373 1.1 christos unsigned short last;
374 1.1 christos
375 1.5 christos if (powerpc_opcd_indices[PPC_OPCD_SEGS] == 0)
376 1.1 christos {
377 1.1 christos
378 1.5 christos i = powerpc_num_opcodes;
379 1.5 christos while (--i >= 0)
380 1.5 christos {
381 1.5 christos unsigned op = PPC_OP (powerpc_opcodes[i].opcode);
382 1.5 christos
383 1.5 christos powerpc_opcd_indices[op] = i;
384 1.5 christos }
385 1.1 christos
386 1.5 christos last = powerpc_num_opcodes;
387 1.5 christos for (i = PPC_OPCD_SEGS; i > 0; --i)
388 1.5 christos {
389 1.5 christos if (powerpc_opcd_indices[i] == 0)
390 1.5 christos powerpc_opcd_indices[i] = last;
391 1.5 christos last = powerpc_opcd_indices[i];
392 1.5 christos }
393 1.1 christos
394 1.5 christos i = vle_num_opcodes;
395 1.5 christos while (--i >= 0)
396 1.5 christos {
397 1.5 christos unsigned op = VLE_OP (vle_opcodes[i].opcode, vle_opcodes[i].mask);
398 1.5 christos unsigned seg = VLE_OP_TO_SEG (op);
399 1.1 christos
400 1.5 christos vle_opcd_indices[seg] = i;
401 1.5 christos }
402 1.1 christos
403 1.5 christos last = vle_num_opcodes;
404 1.5 christos for (i = VLE_OPCD_SEGS; i > 0; --i)
405 1.5 christos {
406 1.5 christos if (vle_opcd_indices[i] == 0)
407 1.5 christos vle_opcd_indices[i] = last;
408 1.5 christos last = vle_opcd_indices[i];
409 1.5 christos }
410 1.1 christos }
411 1.1 christos
412 1.1 christos if (info->arch == bfd_arch_powerpc)
413 1.1 christos powerpc_init_dialect (info);
414 1.1 christos }
415 1.1 christos
416 1.1 christos /* Print a big endian PowerPC instruction. */
417 1.1 christos
418 1.1 christos int
419 1.1 christos print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
420 1.1 christos {
421 1.1 christos return print_insn_powerpc (memaddr, info, 1, get_powerpc_dialect (info));
422 1.1 christos }
423 1.1 christos
424 1.1 christos /* Print a little endian PowerPC instruction. */
425 1.1 christos
426 1.1 christos int
427 1.1 christos print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
428 1.1 christos {
429 1.1 christos return print_insn_powerpc (memaddr, info, 0, get_powerpc_dialect (info));
430 1.1 christos }
431 1.1 christos
432 1.1 christos /* Print a POWER (RS/6000) instruction. */
433 1.1 christos
434 1.1 christos int
435 1.1 christos print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info)
436 1.1 christos {
437 1.1 christos return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER);
438 1.1 christos }
439 1.1 christos
440 1.1 christos /* Extract the operand value from the PowerPC or POWER instruction. */
441 1.1 christos
442 1.1 christos static long
443 1.1 christos operand_value_powerpc (const struct powerpc_operand *operand,
444 1.1 christos unsigned long insn, ppc_cpu_t dialect)
445 1.1 christos {
446 1.1 christos long value;
447 1.1 christos int invalid;
448 1.1 christos /* Extract the value from the instruction. */
449 1.1 christos if (operand->extract)
450 1.1 christos value = (*operand->extract) (insn, dialect, &invalid);
451 1.1 christos else
452 1.1 christos {
453 1.1 christos if (operand->shift >= 0)
454 1.1 christos value = (insn >> operand->shift) & operand->bitm;
455 1.1 christos else
456 1.1 christos value = (insn << -operand->shift) & operand->bitm;
457 1.1 christos if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
458 1.1 christos {
459 1.1 christos /* BITM is always some number of zeros followed by some
460 1.1 christos number of ones, followed by some number of zeros. */
461 1.1 christos unsigned long top = operand->bitm;
462 1.1 christos /* top & -top gives the rightmost 1 bit, so this
463 1.1 christos fills in any trailing zeros. */
464 1.1 christos top |= (top & -top) - 1;
465 1.1 christos top &= ~(top >> 1);
466 1.1 christos value = (value ^ top) - top;
467 1.1 christos }
468 1.1 christos }
469 1.1 christos
470 1.1 christos return value;
471 1.1 christos }
472 1.1 christos
473 1.1 christos /* Determine whether the optional operand(s) should be printed. */
474 1.1 christos
475 1.1 christos static int
476 1.1 christos skip_optional_operands (const unsigned char *opindex,
477 1.1 christos unsigned long insn, ppc_cpu_t dialect)
478 1.1 christos {
479 1.1 christos const struct powerpc_operand *operand;
480 1.1 christos
481 1.1 christos for (; *opindex != 0; opindex++)
482 1.1 christos {
483 1.1 christos operand = &powerpc_operands[*opindex];
484 1.1 christos if ((operand->flags & PPC_OPERAND_NEXT) != 0
485 1.1 christos || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
486 1.5 christos && operand_value_powerpc (operand, insn, dialect) !=
487 1.5 christos ppc_optional_operand_value (operand)))
488 1.1 christos return 0;
489 1.1 christos }
490 1.1 christos
491 1.1 christos return 1;
492 1.1 christos }
493 1.1 christos
494 1.6.4.1 christos /* Find a match for INSN in the opcode table, given machine DIALECT. */
495 1.1 christos
496 1.1 christos static const struct powerpc_opcode *
497 1.1 christos lookup_powerpc (unsigned long insn, ppc_cpu_t dialect)
498 1.1 christos {
499 1.6.4.1 christos const struct powerpc_opcode *opcode, *opcode_end, *last;
500 1.1 christos unsigned long op;
501 1.1 christos
502 1.1 christos /* Get the major opcode of the instruction. */
503 1.1 christos op = PPC_OP (insn);
504 1.1 christos
505 1.1 christos /* Find the first match in the opcode table for this major opcode. */
506 1.1 christos opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
507 1.6.4.1 christos last = NULL;
508 1.1 christos for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
509 1.1 christos opcode < opcode_end;
510 1.1 christos ++opcode)
511 1.1 christos {
512 1.1 christos const unsigned char *opindex;
513 1.1 christos const struct powerpc_operand *operand;
514 1.1 christos int invalid;
515 1.1 christos
516 1.1 christos if ((insn & opcode->mask) != opcode->opcode
517 1.6.4.1 christos || ((dialect & PPC_OPCODE_ANY) == 0
518 1.1 christos && ((opcode->flags & dialect) == 0
519 1.1 christos || (opcode->deprecated & dialect) != 0)))
520 1.1 christos continue;
521 1.1 christos
522 1.1 christos /* Check validity of operands. */
523 1.1 christos invalid = 0;
524 1.1 christos for (opindex = opcode->operands; *opindex != 0; opindex++)
525 1.1 christos {
526 1.1 christos operand = powerpc_operands + *opindex;
527 1.1 christos if (operand->extract)
528 1.1 christos (*operand->extract) (insn, dialect, &invalid);
529 1.1 christos }
530 1.1 christos if (invalid)
531 1.1 christos continue;
532 1.1 christos
533 1.6.4.1 christos if ((dialect & PPC_OPCODE_RAW) == 0)
534 1.6.4.1 christos return opcode;
535 1.6.4.1 christos
536 1.6.4.1 christos /* The raw machine insn is one that is not a specialization. */
537 1.6.4.1 christos if (last == NULL
538 1.6.4.1 christos || (last->mask & ~opcode->mask) != 0)
539 1.6.4.1 christos last = opcode;
540 1.1 christos }
541 1.1 christos
542 1.6.4.1 christos return last;
543 1.1 christos }
544 1.1 christos
545 1.1 christos /* Find a match for INSN in the VLE opcode table. */
546 1.1 christos
547 1.1 christos static const struct powerpc_opcode *
548 1.1 christos lookup_vle (unsigned long insn)
549 1.1 christos {
550 1.1 christos const struct powerpc_opcode *opcode;
551 1.1 christos const struct powerpc_opcode *opcode_end;
552 1.1 christos unsigned op, seg;
553 1.1 christos
554 1.1 christos op = PPC_OP (insn);
555 1.1 christos if (op >= 0x20 && op <= 0x37)
556 1.1 christos {
557 1.1 christos /* This insn has a 4-bit opcode. */
558 1.1 christos op &= 0x3c;
559 1.1 christos }
560 1.1 christos seg = VLE_OP_TO_SEG (op);
561 1.1 christos
562 1.1 christos /* Find the first match in the opcode table for this major opcode. */
563 1.1 christos opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
564 1.1 christos for (opcode = vle_opcodes + vle_opcd_indices[seg];
565 1.1 christos opcode < opcode_end;
566 1.1 christos ++opcode)
567 1.1 christos {
568 1.1 christos unsigned long table_opcd = opcode->opcode;
569 1.1 christos unsigned long table_mask = opcode->mask;
570 1.1 christos bfd_boolean table_op_is_short = PPC_OP_SE_VLE(table_mask);
571 1.1 christos unsigned long insn2;
572 1.1 christos const unsigned char *opindex;
573 1.1 christos const struct powerpc_operand *operand;
574 1.1 christos int invalid;
575 1.1 christos
576 1.1 christos insn2 = insn;
577 1.1 christos if (table_op_is_short)
578 1.1 christos insn2 >>= 16;
579 1.1 christos if ((insn2 & table_mask) != table_opcd)
580 1.1 christos continue;
581 1.1 christos
582 1.1 christos /* Check validity of operands. */
583 1.1 christos invalid = 0;
584 1.1 christos for (opindex = opcode->operands; *opindex != 0; ++opindex)
585 1.1 christos {
586 1.1 christos operand = powerpc_operands + *opindex;
587 1.1 christos if (operand->extract)
588 1.1 christos (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
589 1.1 christos }
590 1.1 christos if (invalid)
591 1.1 christos continue;
592 1.1 christos
593 1.1 christos return opcode;
594 1.1 christos }
595 1.1 christos
596 1.1 christos return NULL;
597 1.1 christos }
598 1.1 christos
599 1.1 christos /* Print a PowerPC or POWER instruction. */
600 1.1 christos
601 1.1 christos static int
602 1.1 christos print_insn_powerpc (bfd_vma memaddr,
603 1.1 christos struct disassemble_info *info,
604 1.1 christos int bigendian,
605 1.1 christos ppc_cpu_t dialect)
606 1.1 christos {
607 1.1 christos bfd_byte buffer[4];
608 1.1 christos int status;
609 1.1 christos unsigned long insn;
610 1.1 christos const struct powerpc_opcode *opcode;
611 1.1 christos bfd_boolean insn_is_short;
612 1.1 christos
613 1.1 christos status = (*info->read_memory_func) (memaddr, buffer, 4, info);
614 1.1 christos if (status != 0)
615 1.1 christos {
616 1.1 christos /* The final instruction may be a 2-byte VLE insn. */
617 1.1 christos if ((dialect & PPC_OPCODE_VLE) != 0)
618 1.1 christos {
619 1.1 christos /* Clear buffer so unused bytes will not have garbage in them. */
620 1.1 christos buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0;
621 1.1 christos status = (*info->read_memory_func) (memaddr, buffer, 2, info);
622 1.1 christos if (status != 0)
623 1.1 christos {
624 1.1 christos (*info->memory_error_func) (status, memaddr, info);
625 1.1 christos return -1;
626 1.1 christos }
627 1.1 christos }
628 1.1 christos else
629 1.1 christos {
630 1.1 christos (*info->memory_error_func) (status, memaddr, info);
631 1.1 christos return -1;
632 1.1 christos }
633 1.1 christos }
634 1.1 christos
635 1.1 christos if (bigendian)
636 1.1 christos insn = bfd_getb32 (buffer);
637 1.1 christos else
638 1.1 christos insn = bfd_getl32 (buffer);
639 1.1 christos
640 1.1 christos /* Get the major opcode of the insn. */
641 1.1 christos opcode = NULL;
642 1.1 christos insn_is_short = FALSE;
643 1.1 christos if ((dialect & PPC_OPCODE_VLE) != 0)
644 1.1 christos {
645 1.1 christos opcode = lookup_vle (insn);
646 1.1 christos if (opcode != NULL)
647 1.1 christos insn_is_short = PPC_OP_SE_VLE(opcode->mask);
648 1.1 christos }
649 1.1 christos if (opcode == NULL)
650 1.6.4.1 christos opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
651 1.1 christos if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
652 1.6.4.1 christos opcode = lookup_powerpc (insn, dialect);
653 1.1 christos
654 1.1 christos if (opcode != NULL)
655 1.1 christos {
656 1.1 christos const unsigned char *opindex;
657 1.1 christos const struct powerpc_operand *operand;
658 1.1 christos int need_comma;
659 1.1 christos int need_paren;
660 1.1 christos int skip_optional;
661 1.1 christos
662 1.1 christos if (opcode->operands[0] != 0)
663 1.1 christos (*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
664 1.1 christos else
665 1.1 christos (*info->fprintf_func) (info->stream, "%s", opcode->name);
666 1.1 christos
667 1.1 christos if (insn_is_short)
668 1.1 christos /* The operands will be fetched out of the 16-bit instruction. */
669 1.1 christos insn >>= 16;
670 1.1 christos
671 1.1 christos /* Now extract and print the operands. */
672 1.1 christos need_comma = 0;
673 1.1 christos need_paren = 0;
674 1.1 christos skip_optional = -1;
675 1.1 christos for (opindex = opcode->operands; *opindex != 0; opindex++)
676 1.1 christos {
677 1.1 christos long value;
678 1.1 christos
679 1.1 christos operand = powerpc_operands + *opindex;
680 1.1 christos
681 1.1 christos /* Operands that are marked FAKE are simply ignored. We
682 1.1 christos already made sure that the extract function considered
683 1.1 christos the instruction to be valid. */
684 1.1 christos if ((operand->flags & PPC_OPERAND_FAKE) != 0)
685 1.1 christos continue;
686 1.1 christos
687 1.1 christos /* If all of the optional operands have the value zero,
688 1.1 christos then don't print any of them. */
689 1.1 christos if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
690 1.1 christos {
691 1.1 christos if (skip_optional < 0)
692 1.1 christos skip_optional = skip_optional_operands (opindex, insn,
693 1.1 christos dialect);
694 1.1 christos if (skip_optional)
695 1.1 christos continue;
696 1.1 christos }
697 1.1 christos
698 1.1 christos value = operand_value_powerpc (operand, insn, dialect);
699 1.1 christos
700 1.1 christos if (need_comma)
701 1.1 christos {
702 1.1 christos (*info->fprintf_func) (info->stream, ",");
703 1.1 christos need_comma = 0;
704 1.1 christos }
705 1.1 christos
706 1.1 christos /* Print the operand as directed by the flags. */
707 1.1 christos if ((operand->flags & PPC_OPERAND_GPR) != 0
708 1.1 christos || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
709 1.1 christos (*info->fprintf_func) (info->stream, "r%ld", value);
710 1.1 christos else if ((operand->flags & PPC_OPERAND_FPR) != 0)
711 1.1 christos (*info->fprintf_func) (info->stream, "f%ld", value);
712 1.1 christos else if ((operand->flags & PPC_OPERAND_VR) != 0)
713 1.1 christos (*info->fprintf_func) (info->stream, "v%ld", value);
714 1.1 christos else if ((operand->flags & PPC_OPERAND_VSR) != 0)
715 1.1 christos (*info->fprintf_func) (info->stream, "vs%ld", value);
716 1.1 christos else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
717 1.1 christos (*info->print_address_func) (memaddr + value, info);
718 1.1 christos else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
719 1.1 christos (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
720 1.6 christos else if ((operand->flags & PPC_OPERAND_FSL) != 0)
721 1.1 christos (*info->fprintf_func) (info->stream, "fsl%ld", value);
722 1.1 christos else if ((operand->flags & PPC_OPERAND_FCR) != 0)
723 1.1 christos (*info->fprintf_func) (info->stream, "fcr%ld", value);
724 1.1 christos else if ((operand->flags & PPC_OPERAND_UDI) != 0)
725 1.1 christos (*info->fprintf_func) (info->stream, "%ld", value);
726 1.1 christos else if ((operand->flags & PPC_OPERAND_CR_REG) != 0
727 1.1 christos && (((dialect & PPC_OPCODE_PPC) != 0)
728 1.1 christos || ((dialect & PPC_OPCODE_VLE) != 0)))
729 1.1 christos (*info->fprintf_func) (info->stream, "cr%ld", value);
730 1.1 christos else if (((operand->flags & PPC_OPERAND_CR_BIT) != 0)
731 1.1 christos && (((dialect & PPC_OPCODE_PPC) != 0)
732 1.1 christos || ((dialect & PPC_OPCODE_VLE) != 0)))
733 1.1 christos {
734 1.1 christos static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
735 1.1 christos int cr;
736 1.1 christos int cc;
737 1.1 christos
738 1.1 christos cr = value >> 2;
739 1.1 christos if (cr != 0)
740 1.1 christos (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
741 1.1 christos cc = value & 3;
742 1.1 christos (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
743 1.1 christos }
744 1.1 christos else
745 1.1 christos (*info->fprintf_func) (info->stream, "%d", (int) value);
746 1.1 christos
747 1.1 christos if (need_paren)
748 1.1 christos {
749 1.1 christos (*info->fprintf_func) (info->stream, ")");
750 1.1 christos need_paren = 0;
751 1.1 christos }
752 1.1 christos
753 1.1 christos if ((operand->flags & PPC_OPERAND_PARENS) == 0)
754 1.1 christos need_comma = 1;
755 1.1 christos else
756 1.1 christos {
757 1.1 christos (*info->fprintf_func) (info->stream, "(");
758 1.1 christos need_paren = 1;
759 1.1 christos }
760 1.1 christos }
761 1.1 christos
762 1.1 christos /* We have found and printed an instruction.
763 1.1 christos If it was a short VLE instruction we have more to do. */
764 1.1 christos if (insn_is_short)
765 1.1 christos {
766 1.1 christos memaddr += 2;
767 1.1 christos return 2;
768 1.1 christos }
769 1.1 christos else
770 1.1 christos /* Otherwise, return. */
771 1.1 christos return 4;
772 1.1 christos }
773 1.1 christos
774 1.1 christos /* We could not find a match. */
775 1.1 christos (*info->fprintf_func) (info->stream, ".long 0x%lx", insn);
776 1.1 christos
777 1.1 christos return 4;
778 1.1 christos }
779 1.1 christos
780 1.6.4.1 christos const disasm_options_t *
781 1.6.4.1 christos disassembler_options_powerpc (void)
782 1.6.4.1 christos {
783 1.6.4.1 christos static disasm_options_t *opts = NULL;
784 1.6.4.1 christos
785 1.6.4.1 christos if (opts == NULL)
786 1.6.4.1 christos {
787 1.6.4.1 christos size_t i, num_options = ARRAY_SIZE (ppc_opts);
788 1.6.4.1 christos opts = XNEW (disasm_options_t);
789 1.6.4.1 christos opts->name = XNEWVEC (const char *, num_options + 1);
790 1.6.4.1 christos for (i = 0; i < num_options; i++)
791 1.6.4.1 christos opts->name[i] = ppc_opts[i].opt;
792 1.6.4.1 christos /* The array we return must be NULL terminated. */
793 1.6.4.1 christos opts->name[i] = NULL;
794 1.6.4.1 christos opts->description = NULL;
795 1.6.4.1 christos }
796 1.6.4.1 christos
797 1.6.4.1 christos return opts;
798 1.6.4.1 christos }
799 1.6.4.1 christos
800 1.1 christos void
801 1.1 christos print_ppc_disassembler_options (FILE *stream)
802 1.1 christos {
803 1.1 christos unsigned int i, col;
804 1.1 christos
805 1.1 christos fprintf (stream, _("\n\
806 1.1 christos The following PPC specific disassembler options are supported for use with\n\
807 1.1 christos the -M switch:\n"));
808 1.1 christos
809 1.6.4.1 christos for (col = 0, i = 0; i < ARRAY_SIZE (ppc_opts); i++)
810 1.1 christos {
811 1.1 christos col += fprintf (stream, " %s,", ppc_opts[i].opt);
812 1.1 christos if (col > 66)
813 1.1 christos {
814 1.1 christos fprintf (stream, "\n");
815 1.1 christos col = 0;
816 1.1 christos }
817 1.1 christos }
818 1.6.4.1 christos fprintf (stream, "\n");
819 1.1 christos }
820