bfd:
[external/binutils.git] / opcodes / ppc-dis.c
1 /* ppc-dis.c -- Disassemble PowerPC instructions
2    Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
3    2008, 2009, 2010 Free Software Foundation, Inc.
4    Written by Ian Lance Taylor, Cygnus Support
5
6    This file is part of the GNU opcodes library.
7
8    This library is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3, or (at your option)
11    any later version.
12
13    It is distributed in the hope that it will be useful, but WITHOUT
14    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16    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
20    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
21    MA 02110-1301, USA.  */
22
23 #include <stdio.h>
24 #include "sysdep.h"
25 #include "dis-asm.h"
26 #include "opintl.h"
27 #include "opcode/ppc.h"
28
29 /* This file provides several disassembler functions, all of which use
30    the disassembler interface defined in dis-asm.h.  Several functions
31    are provided because this file handles disassembly for the PowerPC
32    in both big and little endian mode and also for the POWER (RS/6000)
33    chip.  */
34 static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int,
35                                ppc_cpu_t);
36
37 struct dis_private
38 {
39   /* Stash the result of parsing disassembler_options here.  */
40   ppc_cpu_t dialect;
41 };
42
43 #define POWERPC_DIALECT(INFO) \
44   (((struct dis_private *) ((INFO)->private_data))->dialect)
45
46 struct ppc_mopt {
47   const char *opt;
48   ppc_cpu_t cpu;
49   ppc_cpu_t sticky;
50 };
51
52 struct ppc_mopt ppc_opts[] = {
53   { "403",     (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_403
54                 | PPC_OPCODE_32),
55     0 },
56   { "405",     (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_403
57                 | PPC_OPCODE_405 | PPC_OPCODE_32),
58     0 },
59   { "440",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32
60                 | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
61     0 },
62   { "464",     (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32
63                 | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI),
64     0 },
65   { "476",     (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ISEL
66                 | PPC_OPCODE_440 | PPC_OPCODE_476 | PPC_OPCODE_POWER4
67                 | PPC_OPCODE_POWER5),
68     0 },
69   { "601",     (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_601
70                 | PPC_OPCODE_32),
71     0 },
72   { "603",     (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32),
73     0 },
74   { "604",     (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32),
75     0 },
76   { "620",     (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64),
77     0 },
78   { "7400",    (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC
79                 | PPC_OPCODE_32),
80     0 },
81   { "7410",    (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC
82                 | PPC_OPCODE_32),
83     0 },
84   { "7450",    (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC
85                 | PPC_OPCODE_32),
86     0 },
87   { "7455",    (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC
88                 | PPC_OPCODE_32),
89     0 },
90   { "750cl",   (PPC_OPCODE_PPC | PPC_OPCODE_PPCPS)
91     , 0 },
92   { "a2",      (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ISEL
93                 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_CACHELCK
94                 | PPC_OPCODE_64 | PPC_OPCODE_A2),
95     0 },
96   { "altivec", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC),
97     PPC_OPCODE_ALTIVEC },
98   { "any",     0,
99     PPC_OPCODE_ANY },
100   { "booke",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32),
101     0 },
102   { "booke32", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32),
103     0 },
104   { "cell",    (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64
105                 | PPC_OPCODE_POWER4 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC),
106     0 },
107   { "com",     (PPC_OPCODE_COMMON | PPC_OPCODE_32),
108     0 },
109   { "e300",    (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32
110                 | PPC_OPCODE_E300),
111     0 },
112   { "e500",    (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
113                 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
114                 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
115                 | PPC_OPCODE_E500MC),
116     0 },
117   { "e500mc",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
118                 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
119                 | PPC_OPCODE_E500MC),
120     0 },
121   { "e500mc64",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
122                 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
123                 | PPC_OPCODE_E500MC | PPC_OPCODE_64 | PPC_OPCODE_POWER5
124                 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7),
125     0 },
126   { "e500x2",  (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
127                 | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
128                 | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
129                 | PPC_OPCODE_E500MC),
130     0 },
131   { "efs",     (PPC_OPCODE_PPC | PPC_OPCODE_EFS),
132     0 },
133   { "power4",  (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64
134                 | PPC_OPCODE_POWER4),
135     0 },
136   { "power5",  (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64
137                 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
138     0 },
139   { "power6",  (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64
140                 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
141                 | PPC_OPCODE_ALTIVEC),
142     0 },
143   { "power7",  (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ISEL
144                 | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5
145                 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC
146                 | PPC_OPCODE_VSX),
147     0 },
148   { "ppc",     (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32),
149     0 },
150   { "ppc32",   (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32),
151     0 },
152   { "ppc64",   (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64),
153     0 },
154   { "ppc64bridge", (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64_BRIDGE
155                     | PPC_OPCODE_64),
156     0 },
157   { "ppcps",   (PPC_OPCODE_PPC | PPC_OPCODE_PPCPS),
158     0 },
159   { "pwr",     (PPC_OPCODE_POWER | PPC_OPCODE_32),
160     0 },
161   { "pwr2",    (PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_32),
162     0 },
163   { "pwr4",    (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64
164                 | PPC_OPCODE_POWER4),
165     0 },
166   { "pwr5",    (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64
167                 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
168     0 },
169   { "pwr5x",   (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64
170                 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5),
171     0 },
172   { "pwr6",    (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64
173                 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
174                 | PPC_OPCODE_ALTIVEC),
175     0 },
176   { "pwr7",    (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ISEL
177                 | PPC_OPCODE_64 | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5
178                 | PPC_OPCODE_POWER6 | PPC_OPCODE_POWER7 | PPC_OPCODE_ALTIVEC
179                 | PPC_OPCODE_VSX),
180     0 },
181   { "pwrx",    (PPC_OPCODE_POWER | PPC_OPCODE_POWER2 | PPC_OPCODE_32),
182     0 },
183   { "spe",     (PPC_OPCODE_PPC | PPC_OPCODE_EFS),
184     PPC_OPCODE_SPE },
185   { "titan",   (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32 
186                 | PPC_OPCODE_PMR | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
187     0 },
188   { "vsx",     (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC),
189     PPC_OPCODE_VSX },
190 };
191
192 /* Handle -m and -M options that set cpu type, and .machine arg.  */
193
194 ppc_cpu_t
195 ppc_parse_cpu (ppc_cpu_t ppc_cpu, const char *arg)
196 {
197   /* Sticky bits.  */
198   ppc_cpu_t retain_flags = ppc_cpu & (PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX
199                                       | PPC_OPCODE_SPE | PPC_OPCODE_ANY);
200   unsigned int i;
201
202   for (i = 0; i < sizeof (ppc_opts) / sizeof (ppc_opts[0]); i++)
203     if (strcmp (ppc_opts[i].opt, arg) == 0)
204       {
205         if (ppc_opts[i].sticky)
206           {
207             retain_flags |= ppc_opts[i].sticky;
208             if ((ppc_cpu & ~(PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX
209                              | PPC_OPCODE_SPE | PPC_OPCODE_ANY)) != 0)
210               break;
211           }
212         ppc_cpu = ppc_opts[i].cpu;
213         break;
214       }
215   if (i >= sizeof (ppc_opts) / sizeof (ppc_opts[0]))
216     return 0;
217
218   ppc_cpu |= retain_flags;
219   return ppc_cpu;
220 }
221
222 /* Determine which set of machines to disassemble for.  */
223
224 static int
225 powerpc_init_dialect (struct disassemble_info *info)
226 {
227   ppc_cpu_t dialect = 0;
228   char *arg;
229   struct dis_private *priv = calloc (sizeof (*priv), 1);
230
231   if (priv == NULL)
232     return FALSE;
233
234   arg = info->disassembler_options;
235   while (arg != NULL)
236     {
237       ppc_cpu_t new_cpu = 0;
238       char *end = strchr (arg, ',');
239
240       if (end != NULL)
241         *end = 0;
242
243       if ((new_cpu = ppc_parse_cpu (dialect, arg)) != 0)
244         dialect = new_cpu;
245       else if (strcmp (arg, "32") == 0)
246         {
247           dialect &= ~PPC_OPCODE_64;
248           dialect |= PPC_OPCODE_32;
249         }
250       else if (strcmp (arg, "64") == 0)
251         {
252           dialect |= PPC_OPCODE_64;
253           dialect &= ~PPC_OPCODE_32;
254         }
255       else
256         fprintf (stderr, _("warning: ignoring unknown -M%s option\n"), arg);
257
258       if (end != NULL)
259         *end++ = ',';
260       arg = end;
261     }
262
263   if ((dialect & ~(PPC_OPCODE_32 | PPC_OPCODE_64)) == 0)
264     {
265       if (info->mach == bfd_mach_ppc64)
266         dialect |= PPC_OPCODE_64;
267       else
268         dialect |= PPC_OPCODE_32;
269       /* Choose a reasonable default.  */
270       dialect |= (PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_CLASSIC
271                   | PPC_OPCODE_601 | PPC_OPCODE_ALTIVEC);
272     }
273
274   info->private_data = priv;
275   POWERPC_DIALECT(info) = dialect;
276
277   return TRUE;
278 }
279
280 /* Print a big endian PowerPC instruction.  */
281
282 int
283 print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info)
284 {
285   if (info->private_data == NULL && !powerpc_init_dialect (info))
286     return -1;
287   return print_insn_powerpc (memaddr, info, 1, POWERPC_DIALECT(info));
288 }
289
290 /* Print a little endian PowerPC instruction.  */
291
292 int
293 print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info)
294 {
295   if (info->private_data == NULL && !powerpc_init_dialect (info))
296     return -1;
297   return print_insn_powerpc (memaddr, info, 0, POWERPC_DIALECT(info));
298 }
299
300 /* Print a POWER (RS/6000) instruction.  */
301
302 int
303 print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info)
304 {
305   return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER);
306 }
307
308 /* Extract the operand value from the PowerPC or POWER instruction.  */
309
310 static long
311 operand_value_powerpc (const struct powerpc_operand *operand,
312                        unsigned long insn, ppc_cpu_t dialect)
313 {
314   long value;
315   int invalid;
316   /* Extract the value from the instruction.  */
317   if (operand->extract)
318     value = (*operand->extract) (insn, dialect, &invalid);
319   else
320     {
321       value = (insn >> operand->shift) & operand->bitm;
322       if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
323         {
324           /* BITM is always some number of zeros followed by some
325              number of ones, followed by some numer of zeros.  */
326           unsigned long top = operand->bitm;
327           /* top & -top gives the rightmost 1 bit, so this
328              fills in any trailing zeros.  */
329           top |= (top & -top) - 1;
330           top &= ~(top >> 1);
331           value = (value ^ top) - top;
332         }
333     }
334
335   return value;
336 }
337
338 /* Determine whether the optional operand(s) should be printed.  */
339
340 static int
341 skip_optional_operands (const unsigned char *opindex,
342                         unsigned long insn, ppc_cpu_t dialect)
343 {
344   const struct powerpc_operand *operand;
345
346   for (; *opindex != 0; opindex++)
347     {
348       operand = &powerpc_operands[*opindex];
349       if ((operand->flags & PPC_OPERAND_NEXT) != 0
350           || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
351               && operand_value_powerpc (operand, insn, dialect) != 0))
352         return 0;
353     }
354
355   return 1;
356 }
357
358 /* Print a PowerPC or POWER instruction.  */
359
360 static int
361 print_insn_powerpc (bfd_vma memaddr,
362                     struct disassemble_info *info,
363                     int bigendian,
364                     ppc_cpu_t dialect)
365 {
366   bfd_byte buffer[4];
367   int status;
368   unsigned long insn;
369   const struct powerpc_opcode *opcode;
370   const struct powerpc_opcode *opcode_end;
371   unsigned long op;
372   ppc_cpu_t dialect_orig = dialect;
373
374   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
375   if (status != 0)
376     {
377       (*info->memory_error_func) (status, memaddr, info);
378       return -1;
379     }
380
381   if (bigendian)
382     insn = bfd_getb32 (buffer);
383   else
384     insn = bfd_getl32 (buffer);
385
386   /* Get the major opcode of the instruction.  */
387   op = PPC_OP (insn);
388
389   /* Find the first match in the opcode table.  We could speed this up
390      a bit by doing a binary search on the major opcode.  */
391   opcode_end = powerpc_opcodes + powerpc_num_opcodes;
392  again:
393   for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
394     {
395       unsigned long table_op;
396       const unsigned char *opindex;
397       const struct powerpc_operand *operand;
398       int invalid;
399       int need_comma;
400       int need_paren;
401       int skip_optional;
402
403       table_op = PPC_OP (opcode->opcode);
404       if (op < table_op)
405         break;
406       if (op > table_op)
407         continue;
408
409       if ((insn & opcode->mask) != opcode->opcode
410           || (opcode->flags & dialect) == 0
411           || (opcode->deprecated & dialect_orig) != 0)
412         continue;
413
414       /* Make two passes over the operands.  First see if any of them
415          have extraction functions, and, if they do, make sure the
416          instruction is valid.  */
417       invalid = 0;
418       for (opindex = opcode->operands; *opindex != 0; opindex++)
419         {
420           operand = powerpc_operands + *opindex;
421           if (operand->extract)
422             (*operand->extract) (insn, dialect, &invalid);
423         }
424       if (invalid)
425         continue;
426
427       /* The instruction is valid.  */
428       if (opcode->operands[0] != 0)
429         (*info->fprintf_func) (info->stream, "%-7s ", opcode->name);
430       else
431         (*info->fprintf_func) (info->stream, "%s", opcode->name);
432
433       /* Now extract and print the operands.  */
434       need_comma = 0;
435       need_paren = 0;
436       skip_optional = -1;
437       for (opindex = opcode->operands; *opindex != 0; opindex++)
438         {
439           long value;
440
441           operand = powerpc_operands + *opindex;
442
443           /* Operands that are marked FAKE are simply ignored.  We
444              already made sure that the extract function considered
445              the instruction to be valid.  */
446           if ((operand->flags & PPC_OPERAND_FAKE) != 0)
447             continue;
448
449           /* If all of the optional operands have the value zero,
450              then don't print any of them.  */
451           if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
452             {
453               if (skip_optional < 0)
454                 skip_optional = skip_optional_operands (opindex, insn,
455                                                         dialect);
456               if (skip_optional)
457                 continue;
458             }
459
460           value = operand_value_powerpc (operand, insn, dialect);
461
462           if (need_comma)
463             {
464               (*info->fprintf_func) (info->stream, ",");
465               need_comma = 0;
466             }
467
468           /* Print the operand as directed by the flags.  */
469           if ((operand->flags & PPC_OPERAND_GPR) != 0
470               || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0))
471             (*info->fprintf_func) (info->stream, "r%ld", value);
472           else if ((operand->flags & PPC_OPERAND_FPR) != 0)
473             (*info->fprintf_func) (info->stream, "f%ld", value);
474           else if ((operand->flags & PPC_OPERAND_VR) != 0)
475             (*info->fprintf_func) (info->stream, "v%ld", value);
476           else if ((operand->flags & PPC_OPERAND_VSR) != 0)
477             (*info->fprintf_func) (info->stream, "vs%ld", value);
478           else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
479             (*info->print_address_func) (memaddr + value, info);
480           else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
481             (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
482           else if ((operand->flags & PPC_OPERAND_FSL) != 0) 
483             (*info->fprintf_func) (info->stream, "fsl%ld", value);
484           else if ((operand->flags & PPC_OPERAND_FCR) != 0)
485             (*info->fprintf_func) (info->stream, "fcr%ld", value);
486           else if ((operand->flags & PPC_OPERAND_UDI) != 0)
487             (*info->fprintf_func) (info->stream, "%ld", value);
488           else if ((operand->flags & PPC_OPERAND_CR) != 0
489                    && (dialect & PPC_OPCODE_PPC) != 0)
490             {
491               if (operand->bitm == 7)
492                 (*info->fprintf_func) (info->stream, "cr%ld", value);
493               else
494                 {
495                   static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
496                   int cr;
497                   int cc;
498
499                   cr = value >> 2;
500                   if (cr != 0)
501                     (*info->fprintf_func) (info->stream, "4*cr%d+", cr);
502                   cc = value & 3;
503                   (*info->fprintf_func) (info->stream, "%s", cbnames[cc]);
504                 }
505             }
506           else
507             (*info->fprintf_func) (info->stream, "%ld", value);
508
509           if (need_paren)
510             {
511               (*info->fprintf_func) (info->stream, ")");
512               need_paren = 0;
513             }
514
515           if ((operand->flags & PPC_OPERAND_PARENS) == 0)
516             need_comma = 1;
517           else
518             {
519               (*info->fprintf_func) (info->stream, "(");
520               need_paren = 1;
521             }
522         }
523
524       /* We have found and printed an instruction; return.  */
525       return 4;
526     }
527
528   if ((dialect & PPC_OPCODE_ANY) != 0)
529     {
530       dialect = ~PPC_OPCODE_ANY;
531       goto again;
532     }
533
534   /* We could not find a match.  */
535   (*info->fprintf_func) (info->stream, ".long 0x%lx", insn);
536
537   return 4;
538 }
539
540 void
541 print_ppc_disassembler_options (FILE *stream)
542 {
543   unsigned int i, col;
544
545   fprintf (stream, _("\n\
546 The following PPC specific disassembler options are supported for use with\n\
547 the -M switch:\n"));
548
549   for (col = 0, i = 0; i < sizeof (ppc_opts) / sizeof (ppc_opts[0]); i++)
550     {
551       col += fprintf (stream, " %s,", ppc_opts[i].opt);
552       if (col > 66)
553         {
554           fprintf (stream, "\n");
555           col = 0;
556         }
557     }
558   fprintf (stream, " 32, 64\n");
559 }