]> git.sur5r.net Git - u-boot/blob - common/bedbug.c
Stop passing around bootmem_base value.
[u-boot] / common / bedbug.c
1 /* $Id$ */
2
3 #include <common.h>
4
5 #include <linux/ctype.h>
6 #include <bedbug/bedbug.h>
7 #include <bedbug/ppc.h>
8 #include <bedbug/regs.h>
9 #include <bedbug/tables.h>
10
11 #define Elf32_Word      unsigned long
12
13 /* USE_SOURCE_CODE enables some symbolic debugging functions of this
14    code.  This is only useful if the program will have access to the
15    source code for the binary being examined.
16 */
17
18 /* #define USE_SOURCE_CODE 1 */
19
20 #ifdef USE_SOURCE_CODE
21 extern int line_info_from_addr __P ((Elf32_Word, char *, char *, int *));
22 extern struct symreflist *symByAddr;
23 extern char *symbol_name_from_addr __P ((Elf32_Word, int, int *));
24 #endif /* USE_SOURCE_CODE */
25
26 int print_operands __P ((struct ppc_ctx *));
27 int get_operand_value __P ((struct opcode *, unsigned long,
28                                 enum OP_FIELD, unsigned long *));
29 struct opcode *find_opcode __P ((unsigned long));
30 struct opcode *find_opcode_by_name __P ((char *));
31 char *spr_name __P ((int));
32 int spr_value __P ((char *));
33 char *tbr_name __P ((int));
34 int tbr_value __P ((char *));
35 int parse_operand __P ((unsigned long, struct opcode *,
36                         struct operand *, char *, int *));
37 int get_word __P ((char **, char *));
38 long read_number __P ((char *));
39 int downstring __P ((char *));
40 \f
41
42 /*======================================================================
43  * Entry point for the PPC disassembler.
44  *
45  * Arguments:
46  *      memaddr         The address to start disassembling from.
47  *
48  *      virtual         If this value is non-zero, then this will be
49  *                      used as the base address for the output and
50  *                      symbol lookups.  If this value is zero then
51  *                      memaddr is used as the absolute address.
52  *
53  *      num_instr       The number of instructions to disassemble.  Since
54  *                      each instruction is 32 bits long, this can be
55  *                      computed if you know the total size of the region.
56  *
57  *      pfunc           The address of a function that is called to print
58  *                      each line of output.  The function should take a
59  *                      single character pointer as its parameters a la puts.
60  *
61  *      flags           Sets options for the output.  This is a
62  *                      bitwise-inclusive-OR of the following
63  *                      values.  Note that only one of the radix
64  *                      options may be set.
65  *
66  *                      F_RADOCTAL      - output radix is unsigned base 8.
67  *                      F_RADUDECIMAL   - output radix is unsigned base 10.
68  *                      F_RADSDECIMAL   - output radix is signed base 10.
69  *                      F_RADHEX        - output radix is unsigned base 16.
70  *                      F_SIMPLE        - use simplified mnemonics.
71  *                      F_SYMBOL        - lookup symbols for addresses.
72  *                      F_INSTR         - output raw instruction.
73  *                      F_LINENO        - show line # info if available.
74  *
75  * Returns TRUE if the area was successfully disassembled or FALSE if
76  * a problem was encountered with accessing the memory.
77  */
78
79 int disppc (unsigned char *memaddr, unsigned char *virtual, int num_instr,
80                         int (*pfunc) (const char *), unsigned long flags)
81 {
82         int i;
83         struct ppc_ctx ctx;
84
85 #ifdef USE_SOURCE_CODE
86         int line_no = 0;
87         int last_line_no = 0;
88         char funcname[128] = { 0 };
89         char filename[256] = { 0 };
90         char last_funcname[128] = { 0 };
91         int symoffset;
92         char *symname;
93         char *cursym = (char *) 0;
94 #endif /* USE_SOURCE_CODE */
95   /*------------------------------------------------------------*/
96
97         ctx.flags = flags;
98         ctx.virtual = virtual;
99
100         /* Figure out the output radix before we go any further */
101
102         if (ctx.flags & F_RADOCTAL) {
103                 /* Unsigned octal output */
104                 strcpy (ctx.radix_fmt, "O%o");
105         } else if (ctx.flags & F_RADUDECIMAL) {
106                 /* Unsigned decimal output */
107                 strcpy (ctx.radix_fmt, "%u");
108         } else if (ctx.flags & F_RADSDECIMAL) {
109                 /* Signed decimal output */
110                 strcpy (ctx.radix_fmt, "%d");
111         } else {
112                 /* Unsigned hex output */
113                 strcpy (ctx.radix_fmt, "0x%x");
114         }
115
116         if (ctx.virtual == 0) {
117                 ctx.virtual = memaddr;
118         }
119 #ifdef USE_SOURCE_CODE
120         if (ctx.flags & F_SYMBOL) {
121                 if (symByAddr == 0)             /* no symbols loaded */
122                         ctx.flags &= ~F_SYMBOL;
123                 else {
124                         cursym = (char *) 0;
125                         symoffset = 0;
126                 }
127         }
128 #endif /* USE_SOURCE_CODE */
129
130         /* format each line as "XXXXXXXX: <symbol> IIIIIIII  disassembly" where,
131            XXXXXXXX is the memory address in hex,
132            <symbol> is the symbolic location if F_SYMBOL is set.
133            IIIIIIII is the raw machine code in hex if F_INSTR is set,
134            and disassembly is the disassembled machine code with numbers
135            formatted according to the 'radix' parameter */
136
137         for (i = 0; i < num_instr; ++i, memaddr += 4, ctx.virtual += 4) {
138 #ifdef USE_SOURCE_CODE
139                 if (ctx.flags & F_LINENO) {
140                         if ((line_info_from_addr ((Elf32_Word) ctx.virtual, filename,
141                                                                           funcname, &line_no) == TRUE) &&
142                                 ((line_no != last_line_no) ||
143                                  (strcmp (last_funcname, funcname) != 0))) {
144                                 print_source_line (filename, funcname, line_no, pfunc);
145                         }
146                         last_line_no = line_no;
147                         strcpy (last_funcname, funcname);
148                 }
149 #endif /* USE_SOURCE_CODE */
150
151                 sprintf (ctx.data, "%08lx: ", (unsigned long) ctx.virtual);
152                 ctx.datalen = 10;
153
154 #ifdef USE_SOURCE_CODE
155                 if (ctx.flags & F_SYMBOL) {
156                         if ((symname =
157                                  symbol_name_from_addr ((Elf32_Word) ctx.virtual,
158                                                                                 TRUE, 0)) != 0) {
159                                 cursym = symname;
160                                 symoffset = 0;
161                         } else {
162                                 if ((cursym == 0) &&
163                                         ((symname =
164                                           symbol_name_from_addr ((Elf32_Word) ctx.virtual,
165                                                                                          FALSE, &symoffset)) != 0)) {
166                                         cursym = symname;
167                                 } else {
168                                         symoffset += 4;
169                                 }
170                         }
171
172                         if (cursym != 0) {
173                                 sprintf (&ctx.data[ctx.datalen], "<%s+", cursym);
174                                 ctx.datalen = strlen (ctx.data);
175                                 sprintf (&ctx.data[ctx.datalen], ctx.radix_fmt, symoffset);
176                                 strcat (ctx.data, ">");
177                                 ctx.datalen = strlen (ctx.data);
178                         }
179                 }
180 #endif /* USE_SOURCE_CODE */
181
182                 ctx.instr = INSTRUCTION (memaddr);
183
184                 if (ctx.flags & F_INSTR) {
185                         /* Find the opcode structure for this opcode.  If one is not found
186                            then it must be an illegal instruction */
187                         sprintf (&ctx.data[ctx.datalen],
188                                          "   %02lx %02lx %02lx %02lx    ",
189                                          ((ctx.instr >> 24) & 0xff),
190                                          ((ctx.instr >> 16) & 0xff), ((ctx.instr >> 8) & 0xff),
191                                          (ctx.instr & 0xff));
192                         ctx.datalen += 18;
193                 } else {
194                         strcat (ctx.data, "   ");
195                         ctx.datalen += 3;
196                 }
197
198                 if ((ctx.op = find_opcode (ctx.instr)) == 0) {
199                         /* Illegal Opcode */
200                         sprintf (&ctx.data[ctx.datalen], "        .long 0x%08lx",
201                                          ctx.instr);
202                         ctx.datalen += 24;
203                         (*pfunc) (ctx.data);
204                         continue;
205                 }
206
207                 if (((ctx.flags & F_SIMPLE) == 0) ||
208                         (ctx.op->hfunc == 0) || ((*ctx.op->hfunc) (&ctx) == FALSE)) {
209                         sprintf (&ctx.data[ctx.datalen], "%-7s ", ctx.op->name);
210                         ctx.datalen += 8;
211                         print_operands (&ctx);
212                 }
213
214                 (*pfunc) (ctx.data);
215         }
216
217         return TRUE;
218 }                                                               /* disppc */
219 \f
220
221
222 /*======================================================================
223  * Called by the disassembler to print the operands for an instruction.
224  *
225  * Arguments:
226  *      ctx             A pointer to the disassembler context record.
227  *
228  * always returns 0.
229  */
230
231 int print_operands (struct ppc_ctx *ctx)
232 {
233         int open_parens = 0;
234         int field;
235         unsigned long operand;
236         struct operand *opr;
237
238 #ifdef USE_SOURCE_CODE
239         char *symname;
240         int offset;
241 #endif /* USE_SOURCE_CODE */
242   /*------------------------------------------------------------*/
243
244         /* Walk through the operands and list each in order */
245         for (field = 0; ctx->op->fields[field] != 0; ++field) {
246                 if (ctx->op->fields[field] > n_operands) {
247                         continue;                       /* bad operand ?! */
248                 }
249
250                 opr = &operands[ctx->op->fields[field] - 1];
251
252                 if (opr->hint & OH_SILENT) {
253                         continue;
254                 }
255
256                 if ((field > 0) && !open_parens) {
257                         strcat (ctx->data, ",");
258                         ctx->datalen++;
259                 }
260
261                 operand = (ctx->instr >> opr->shift) & ((1 << opr->bits) - 1);
262
263                 if (opr->hint & OH_ADDR) {
264                         if ((operand & (1 << (opr->bits - 1))) != 0) {
265                                 operand = operand - (1 << opr->bits);
266                         }
267
268                         if (ctx->op->hint & H_RELATIVE)
269                                 operand = (operand << 2) + (unsigned long) ctx->virtual;
270                         else
271                                 operand = (operand << 2);
272
273
274                         sprintf (&ctx->data[ctx->datalen], "0x%lx", operand);
275                         ctx->datalen = strlen (ctx->data);
276
277 #ifdef USE_SOURCE_CODE
278                         if ((ctx->flags & F_SYMBOL) &&
279                                 ((symname =
280                                   symbol_name_from_addr (operand, 0, &offset)) != 0)) {
281                                 sprintf (&ctx->data[ctx->datalen], " <%s", symname);
282                                 if (offset != 0) {
283                                         strcat (ctx->data, "+");
284                                         ctx->datalen = strlen (ctx->data);
285                                         sprintf (&ctx->data[ctx->datalen], ctx->radix_fmt,
286                                                          offset);
287                                 }
288                                 strcat (ctx->data, ">");
289                         }
290 #endif /* USE_SOURCE_CODE */
291                 }
292
293                 else if (opr->hint & OH_REG) {
294                         if ((operand == 0) &&
295                                 (opr->field == O_rA) && (ctx->op->hint & H_RA0_IS_0)) {
296                                 strcat (ctx->data, "0");
297                         } else {
298                                 sprintf (&ctx->data[ctx->datalen], "r%d", (short) operand);
299                         }
300
301                         if (open_parens) {
302                                 strcat (ctx->data, ")");
303                                 open_parens--;
304                         }
305                 }
306
307                 else if (opr->hint & OH_SPR) {
308                         strcat (ctx->data, spr_name (operand));
309                 }
310
311                 else if (opr->hint & OH_TBR) {
312                         strcat (ctx->data, tbr_name (operand));
313                 }
314
315                 else if (opr->hint & OH_LITERAL) {
316                         switch (opr->field) {
317                         case O_cr2:
318                                 strcat (ctx->data, "cr2");
319                                 ctx->datalen += 3;
320                                 break;
321
322                         default:
323                                 break;
324                         }
325                 }
326
327                 else {
328                         sprintf (&ctx->data[ctx->datalen], ctx->radix_fmt,
329                                          (unsigned short) operand);
330
331                         if (open_parens) {
332                                 strcat (ctx->data, ")");
333                                 open_parens--;
334                         }
335
336                         else if (opr->hint & OH_OFFSET) {
337                                 strcat (ctx->data, "(");
338                                 open_parens++;
339                         }
340                 }
341
342                 ctx->datalen = strlen (ctx->data);
343         }
344
345         return 0;
346 }                                                               /* print_operands */
347 \f
348
349
350 /*======================================================================
351  * Called to get the value of an arbitrary operand with in an instruction.
352  *
353  * Arguments:
354  *      op              The pointer to the opcode structure to which
355  *                      the operands belong.
356  *
357  *      instr           The instruction (32 bits) containing the opcode
358  *                      and the operands to print.  By the time that
359  *                      this routine is called the operand has already
360  *                      been added to the output.
361  *
362  *      field           The field (operand) to get the value of.
363  *
364  *      value           The address of an unsigned long to be filled in
365  *                      with the value of the operand if it is found.  This
366  *                      will only be filled in if the function returns
367  *                      TRUE.  This may be passed as 0 if the value is
368  *                      not required.
369  *
370  * Returns TRUE if the operand was found or FALSE if it was not.
371  */
372
373 int get_operand_value (struct opcode *op, unsigned long instr,
374                                            enum OP_FIELD field, unsigned long *value)
375 {
376         int i;
377         struct operand *opr;
378
379   /*------------------------------------------------------------*/
380
381         if (field > n_operands) {
382                 return FALSE;                   /* bad operand ?! */
383         }
384
385         /* Walk through the operands and list each in order */
386         for (i = 0; op->fields[i] != 0; ++i) {
387                 if (op->fields[i] != field) {
388                         continue;
389                 }
390
391                 opr = &operands[op->fields[i] - 1];
392
393                 if (value) {
394                         *value = (instr >> opr->shift) & ((1 << opr->bits) - 1);
395                 }
396                 return TRUE;
397         }
398
399         return FALSE;
400 }                                                               /* operand_value */
401 \f
402
403
404 /*======================================================================
405  * Called by the disassembler to match an opcode value to an opcode structure.
406  *
407  * Arguments:
408  *      instr           The instruction (32 bits) to match.  This value
409  *                      may contain operand values as well as the opcode
410  *                      since they will be masked out anyway for this
411  *                      search.
412  *
413  * Returns the address of an opcode struct (from the opcode table) if the
414  * operand successfully matched an entry, or 0 if no match was found.
415  */
416
417 struct opcode *find_opcode (unsigned long instr)
418 {
419         struct opcode *ptr;
420         int top = 0;
421         int bottom = n_opcodes - 1;
422         int idx;
423
424   /*------------------------------------------------------------*/
425
426         while (top <= bottom) {
427                 idx = (top + bottom) >> 1;
428                 ptr = &opcodes[idx];
429
430                 if ((instr & ptr->mask) < ptr->opcode) {
431                         bottom = idx - 1;
432                 } else if ((instr & ptr->mask) > ptr->opcode) {
433                         top = idx + 1;
434                 } else {
435                         return ptr;
436                 }
437         }
438
439         return (struct opcode *) 0;
440 }                                                               /* find_opcode */
441 \f
442
443
444 /*======================================================================
445  * Called by the assembler to match an opcode name to an opcode structure.
446  *
447  * Arguments:
448  *      name            The text name of the opcode, e.g. "b", "mtspr", etc.
449  *
450  * The opcodes are sorted numerically by their instruction binary code
451  * so a search for the name cannot use the binary search used by the
452  * other find routine.
453  *
454  * Returns the address of an opcode struct (from the opcode table) if the
455  * name successfully matched an entry, or 0 if no match was found.
456  */
457
458 struct opcode *find_opcode_by_name (char *name)
459 {
460         int idx;
461
462   /*------------------------------------------------------------*/
463
464         downstring (name);
465
466         for (idx = 0; idx < n_opcodes; ++idx) {
467                 if (!strcmp (name, opcodes[idx].name))
468                         return &opcodes[idx];
469         }
470
471         return (struct opcode *) 0;
472 }                                                               /* find_opcode_by_name */
473 \f
474
475
476 /*======================================================================
477  * Convert the 'spr' operand from its numeric value to its symbolic name.
478  *
479  * Arguments:
480  *      value           The value of the 'spr' operand.  This value should
481  *                      be unmodified from its encoding in the instruction.
482  *                      the split-field computations will be performed
483  *                      here before the switch.
484  *
485  * Returns the address of a character array containing the name of the
486  * special purpose register defined by the 'value' parameter, or the
487  * address of a character array containing "???" if no match was found.
488  */
489
490 char *spr_name (int value)
491 {
492         unsigned short spr;
493         static char other[10];
494         int i;
495
496   /*------------------------------------------------------------*/
497
498         /* spr is a 10 bit field whose interpretation has the high and low
499            five-bit fields reversed from their encoding in the operand */
500
501         spr = ((value >> 5) & 0x1f) | ((value & 0x1f) << 5);
502
503         for (i = 0; i < n_sprs; ++i) {
504                 if (spr == spr_map[i].spr_val)
505                         return spr_map[i].spr_name;
506         }
507
508         sprintf (other, "%d", spr);
509         return other;
510 }                                                               /* spr_name */
511 \f
512
513
514 /*======================================================================
515  * Convert the 'spr' operand from its symbolic name to its numeric value
516  *
517  * Arguments:
518  *      name            The symbolic name of the 'spr' operand.  The
519  *                      split-field encoding will be done by this routine.
520  *                      NOTE: name can be a number.
521  *
522  * Returns the numeric value for the spr appropriate for encoding a machine
523  * instruction.  Returns 0 if unable to find the SPR.
524  */
525
526 int spr_value (char *name)
527 {
528         struct spr_info *sprp;
529         int spr;
530         int i;
531
532   /*------------------------------------------------------------*/
533
534         if (!name || !*name)
535                 return 0;
536
537         if (isdigit ((int) name[0])) {
538                 i = htonl (read_number (name));
539                 spr = ((i >> 5) & 0x1f) | ((i & 0x1f) << 5);
540                 return spr;
541         }
542
543         downstring (name);
544
545         for (i = 0; i < n_sprs; ++i) {
546                 sprp = &spr_map[i];
547
548                 if (strcmp (name, sprp->spr_name) == 0) {
549                         /* spr is a 10 bit field whose interpretation has the high and low
550                            five-bit fields reversed from their encoding in the operand */
551                         i = htonl (sprp->spr_val);
552                         spr = ((i >> 5) & 0x1f) | ((i & 0x1f) << 5);
553
554                         return spr;
555                 }
556         }
557
558         return 0;
559 }                                                               /* spr_value */
560 \f
561
562
563 /*======================================================================
564  * Convert the 'tbr' operand from its numeric value to its symbolic name.
565  *
566  * Arguments:
567  *      value           The value of the 'tbr' operand.  This value should
568  *                      be unmodified from its encoding in the instruction.
569  *                      the split-field computations will be performed
570  *                      here before the switch.
571  *
572  * Returns the address of a character array containing the name of the
573  * time base register defined by the 'value' parameter, or the address
574  * of a character array containing "???" if no match was found.
575  */
576
577 char *tbr_name (int value)
578 {
579         unsigned short tbr;
580
581   /*------------------------------------------------------------*/
582
583         /* tbr is a 10 bit field whose interpretation has the high and low
584            five-bit fields reversed from their encoding in the operand */
585
586         tbr = ((value >> 5) & 0x1f) | ((value & 0x1f) << 5);
587
588         if (tbr == 268)
589                 return "TBL";
590
591         else if (tbr == 269)
592                 return "TBU";
593
594
595         return "???";
596 }                                                               /* tbr_name */
597 \f
598
599
600 /*======================================================================
601  * Convert the 'tbr' operand from its symbolic name to its numeric value.
602  *
603  * Arguments:
604  *      name            The symbolic name of the 'tbr' operand.  The
605  *                      split-field encoding will be done by this routine.
606  *
607  * Returns the numeric value for the spr appropriate for encoding a machine
608  * instruction.  Returns 0 if unable to find the TBR.
609  */
610
611 int tbr_value (char *name)
612 {
613         int tbr;
614         int val;
615
616   /*------------------------------------------------------------*/
617
618         if (!name || !*name)
619                 return 0;
620
621         downstring (name);
622
623         if (isdigit ((int) name[0])) {
624                 val = read_number (name);
625
626                 if (val != 268 && val != 269)
627                         return 0;
628         } else if (strcmp (name, "tbl") == 0)
629                 val = 268;
630         else if (strcmp (name, "tbu") == 0)
631                 val = 269;
632         else
633                 return 0;
634
635         /* tbr is a 10 bit field whose interpretation has the high and low
636            five-bit fields reversed from their encoding in the operand */
637
638         val = htonl (val);
639         tbr = ((val >> 5) & 0x1f) | ((val & 0x1f) << 5);
640         return tbr;
641 }                                                               /* tbr_name */
642 \f
643
644
645 /*======================================================================
646  * The next several functions (handle_xxx) are the routines that handle
647  * disassembling the opcodes with simplified mnemonics.
648  *
649  * Arguments:
650  *      ctx             A pointer to the disassembler context record.
651  *
652  * Returns TRUE if the simpler form was printed or FALSE if it was not.
653  */
654
655 int handle_bc (struct ppc_ctx *ctx)
656 {
657         unsigned long bo;
658         unsigned long bi;
659         static struct opcode blt = { B_OPCODE (16, 0, 0), B_MASK, {O_BD, 0},
660         0, "blt", H_RELATIVE
661         };
662         static struct opcode bne =
663                         { B_OPCODE (16, 0, 0), B_MASK, {O_cr2, O_BD, 0},
664         0, "bne", H_RELATIVE
665         };
666         static struct opcode bdnz = { B_OPCODE (16, 0, 0), B_MASK, {O_BD, 0},
667         0, "bdnz", H_RELATIVE
668         };
669
670   /*------------------------------------------------------------*/
671
672         if (get_operand_value (ctx->op, ctx->instr, O_BO, &bo) == FALSE)
673                 return FALSE;
674
675         if (get_operand_value (ctx->op, ctx->instr, O_BI, &bi) == FALSE)
676                 return FALSE;
677
678         if ((bo == 12) && (bi == 0)) {
679                 ctx->op = &blt;
680                 sprintf (&ctx->data[ctx->datalen], "%-7s ", ctx->op->name);
681                 ctx->datalen += 8;
682                 print_operands (ctx);
683                 return TRUE;
684         } else if ((bo == 4) && (bi == 10)) {
685                 ctx->op = &bne;
686                 sprintf (&ctx->data[ctx->datalen], "%-7s ", ctx->op->name);
687                 ctx->datalen += 8;
688                 print_operands (ctx);
689                 return TRUE;
690         } else if ((bo == 16) && (bi == 0)) {
691                 ctx->op = &bdnz;
692                 sprintf (&ctx->data[ctx->datalen], "%-7s ", ctx->op->name);
693                 ctx->datalen += 8;
694                 print_operands (ctx);
695                 return TRUE;
696         }
697
698         return FALSE;
699 }                                                               /* handle_blt */
700 \f
701
702
703 /*======================================================================
704  * Outputs source line information for the disassembler.  This should
705  * be modified in the future to lookup the actual line of source code
706  * from the file, but for now this will do.
707  *
708  * Arguments:
709  *      filename        The address of a character array containing the
710  *                      absolute path and file name of the source file.
711  *
712  *      funcname        The address of a character array containing the
713  *                      name of the function (not C++ demangled (yet))
714  *                      to which this code belongs.
715  *
716  *      line_no         An integer specifying the source line number that
717  *                      generated this code.
718  *
719  *      pfunc           The address of a function to call to print the output.
720  *
721  *
722  * Returns TRUE if it was able to output the line info, or false if it was
723  * not.
724  */
725
726 int print_source_line (char *filename, char *funcname,
727                                            int line_no, int (*pfunc) (const char *))
728 {
729         char out_buf[256];
730
731   /*------------------------------------------------------------*/
732
733         (*pfunc) ("");                          /* output a newline */
734         sprintf (out_buf, "%s %s(): line %d", filename, funcname, line_no);
735         (*pfunc) (out_buf);
736
737         return TRUE;
738 }                                                               /* print_source_line */
739 \f
740
741
742 /*======================================================================
743  * Entry point for the PPC assembler.
744  *
745  * Arguments:
746  *      asm_buf         An array of characters containing the assembly opcode
747  *                      and operands to convert to a POWERPC machine
748  *                      instruction.
749  *
750  * Returns the machine instruction or zero.
751  */
752
753 unsigned long asmppc (unsigned long memaddr, char *asm_buf, int *err)
754 {
755         struct opcode *opc;
756         struct operand *oper[MAX_OPERANDS];
757         unsigned long instr;
758         unsigned long param;
759         char *ptr = asm_buf;
760         char scratch[20];
761         int i;
762         int w_operands = 0;                     /* wanted # of operands */
763         int n_operands = 0;                     /* # of operands read */
764         int asm_debug = 0;
765
766   /*------------------------------------------------------------*/
767
768         if (err)
769                 *err = 0;
770
771         if (get_word (&ptr, scratch) == 0)
772                 return 0;
773
774         /* Lookup the opcode structure based on the opcode name */
775         if ((opc = find_opcode_by_name (scratch)) == (struct opcode *) 0) {
776                 if (err)
777                         *err = E_ASM_BAD_OPCODE;
778                 return 0;
779         }
780
781         if (asm_debug) {
782                 printf ("asmppc: Opcode = \"%s\"\n", opc->name);
783         }
784
785         for (i = 0; i < 8; ++i) {
786                 if (opc->fields[i] == 0)
787                         break;
788                 ++w_operands;
789         }
790
791         if (asm_debug) {
792                 printf ("asmppc: Expecting %d operands\n", w_operands);
793         }
794
795         instr = opc->opcode;
796
797         /* read each operand */
798         while (n_operands < w_operands) {
799
800                 oper[n_operands] = &operands[opc->fields[n_operands] - 1];
801
802                 if (oper[n_operands]->hint & OH_SILENT) {
803                         /* Skip silent operands, they are covered in opc->opcode */
804
805                         if (asm_debug) {
806                                 printf ("asmppc: Operand %d \"%s\" SILENT\n", n_operands,
807                                                 oper[n_operands]->name);
808                         }
809
810                         ++n_operands;
811                         continue;
812                 }
813
814                 if (get_word (&ptr, scratch) == 0)
815                         break;
816
817                 if (asm_debug) {
818                         printf ("asmppc: Operand %d \"%s\" : \"%s\"\n", n_operands,
819                                         oper[n_operands]->name, scratch);
820                 }
821
822                 if ((param = parse_operand (memaddr, opc, oper[n_operands],
823                                                                         scratch, err)) == -1)
824                         return 0;
825
826                 instr |= param;
827                 ++n_operands;
828         }
829
830         if (n_operands < w_operands) {
831                 if (err)
832                         *err = E_ASM_NUM_OPERANDS;
833                 return 0;
834         }
835
836         if (asm_debug) {
837                 printf ("asmppc: Instruction = 0x%08lx\n", instr);
838         }
839
840         return instr;
841 }                                                               /* asmppc */
842 \f
843
844
845 /*======================================================================
846  * Called by the assembler to interpret a single operand
847  *
848  * Arguments:
849  *      ctx             A pointer to the disassembler context record.
850  *
851  * Returns 0 if the operand is ok, or -1 if it is bad.
852  */
853
854 int parse_operand (unsigned long memaddr, struct opcode *opc,
855                                    struct operand *oper, char *txt, int *err)
856 {
857         long data;
858         long mask;
859         int is_neg = 0;
860
861   /*------------------------------------------------------------*/
862
863         mask = (1 << oper->bits) - 1;
864
865         if (oper->hint & OH_ADDR) {
866                 data = read_number (txt);
867
868                 if (opc->hint & H_RELATIVE)
869                         data = data - memaddr;
870
871                 if (data < 0)
872                         is_neg = 1;
873
874                 data >>= 2;
875                 data &= (mask >> 1);
876
877                 if (is_neg)
878                         data |= 1 << (oper->bits - 1);
879         }
880
881         else if (oper->hint & OH_REG) {
882                 if (txt[0] == 'r' || txt[0] == 'R')
883                         txt++;
884                 else if (txt[0] == '%' && (txt[1] == 'r' || txt[1] == 'R'))
885                         txt += 2;
886
887                 data = read_number (txt);
888                 if (data > 31) {
889                         if (err)
890                                 *err = E_ASM_BAD_REGISTER;
891                         return -1;
892                 }
893
894                 data = htonl (data);
895         }
896
897         else if (oper->hint & OH_SPR) {
898                 if ((data = spr_value (txt)) == 0) {
899                         if (err)
900                                 *err = E_ASM_BAD_SPR;
901                         return -1;
902                 }
903         }
904
905         else if (oper->hint & OH_TBR) {
906                 if ((data = tbr_value (txt)) == 0) {
907                         if (err)
908                                 *err = E_ASM_BAD_TBR;
909                         return -1;
910                 }
911         }
912
913         else {
914                 data = htonl (read_number (txt));
915         }
916
917         return (data & mask) << oper->shift;
918 }                                                               /* parse_operand */
919
920
921 char *asm_error_str (int err)
922 {
923         switch (err) {
924         case E_ASM_BAD_OPCODE:
925                 return "Bad opcode";
926         case E_ASM_NUM_OPERANDS:
927                 return "Bad number of operands";
928         case E_ASM_BAD_REGISTER:
929                 return "Bad register number";
930         case E_ASM_BAD_SPR:
931                 return "Bad SPR name or number";
932         case E_ASM_BAD_TBR:
933                 return "Bad TBR name or number";
934         }
935
936         return "";
937 }                                                               /* asm_error_str */
938 \f
939
940
941 /*======================================================================
942  * Copy a word from one buffer to another, ignores leading white spaces.
943  *
944  * Arguments:
945  *      src             The address of a character pointer to the
946  *                      source buffer.
947  *      dest            A pointer to a character buffer to write the word
948  *                      into.
949  *
950  * Returns the number of non-white space characters copied, or zero.
951  */
952
953 int get_word (char **src, char *dest)
954 {
955         char *ptr = *src;
956         int nchars = 0;
957
958   /*------------------------------------------------------------*/
959
960         /* Eat white spaces */
961         while (*ptr && isblank (*ptr))
962                 ptr++;
963
964         if (*ptr == 0) {
965                 *src = ptr;
966                 return 0;
967         }
968
969         /* Find the text of the word */
970         while (*ptr && !isblank (*ptr) && (*ptr != ','))
971                 dest[nchars++] = *ptr++;
972         ptr = (*ptr == ',') ? ptr + 1 : ptr;
973         dest[nchars] = 0;
974
975         *src = ptr;
976         return nchars;
977 }                                                               /* get_word */
978 \f
979
980
981 /*======================================================================
982  * Convert a numeric string to a number, be aware of base notations.
983  *
984  * Arguments:
985  *      txt             The numeric string.
986  *
987  * Returns the converted numeric value.
988  */
989
990 long read_number (char *txt)
991 {
992         long val;
993         int is_neg = 0;
994
995   /*------------------------------------------------------------*/
996
997         if (txt == 0 || *txt == 0)
998                 return 0;
999
1000         if (*txt == '-') {
1001                 is_neg = 1;
1002                 ++txt;
1003         }
1004
1005         if (txt[0] == '0' && (txt[1] == 'x' || txt[1] == 'X'))  /* hex */
1006                 val = simple_strtoul (&txt[2], NULL, 16);
1007         else                                            /* decimal */
1008                 val = simple_strtoul (txt, NULL, 10);
1009
1010         if (is_neg)
1011                 val = -val;
1012
1013         return val;
1014 }                                                               /* read_number */
1015
1016
1017 int downstring (char *s)
1018 {
1019         if (!s || !*s)
1020                 return 0;
1021
1022         while (*s) {
1023                 if (isupper (*s))
1024                         *s = tolower (*s);
1025                 s++;
1026         }
1027
1028         return 0;
1029 }                                                               /* downstring */
1030 \f
1031
1032
1033 /*======================================================================
1034  * Examines the instruction at the current address and determines the
1035  * next address to be executed.  This will take into account branches
1036  * of different types so that a "step" and "next" operations can be
1037  * supported.
1038  *
1039  * Arguments:
1040  *      nextaddr        The address (to be filled in) of the next
1041  *                      instruction to execute.  This will only be a valid
1042  *                      address if TRUE is returned.
1043  *
1044  *      step_over       A flag indicating how to compute addresses for
1045  *                      branch statements:
1046  *                       TRUE  = Step over the branch (next)
1047  *                       FALSE = step into the branch (step)
1048  *
1049  * Returns TRUE if it was able to compute the address.  Returns FALSE if
1050  * it has a problem reading the current instruction or one of the registers.
1051  */
1052
1053 int find_next_address (unsigned char *nextaddr, int step_over,
1054                                            struct pt_regs *regs)
1055 {
1056         unsigned long pc;                       /* SRR0 register from PPC */
1057         unsigned long ctr;                      /* CTR register from PPC */
1058         unsigned long cr;                       /* CR register from PPC */
1059         unsigned long lr;                       /* LR register from PPC */
1060         unsigned long instr;            /* instruction at SRR0 */
1061         unsigned long next;                     /* computed instruction for 'next' */
1062         unsigned long step;                     /* computed instruction for 'step' */
1063         unsigned long addr = 0;         /* target address operand */
1064         unsigned long aa = 0;           /* AA operand */
1065         unsigned long lk = 0;           /* LK operand */
1066         unsigned long bo = 0;           /* BO operand */
1067         unsigned long bi = 0;           /* BI operand */
1068         struct opcode *op = 0;          /* opcode structure for 'instr' */
1069         int ctr_ok = 0;
1070         int cond_ok = 0;
1071         int conditional = 0;
1072         int branch = 0;
1073
1074   /*------------------------------------------------------------*/
1075
1076         if (nextaddr == 0 || regs == 0) {
1077                 printf ("find_next_address: bad args");
1078                 return FALSE;
1079         }
1080
1081         pc = regs->nip & 0xfffffffc;
1082         instr = INSTRUCTION (pc);
1083
1084         if ((op = find_opcode (instr)) == (struct opcode *) 0) {
1085                 printf ("find_next_address: can't parse opcode 0x%lx", instr);
1086                 return FALSE;
1087         }
1088
1089         ctr = regs->ctr;
1090         cr = regs->ccr;
1091         lr = regs->link;
1092
1093         switch (op->opcode) {
1094         case B_OPCODE (16, 0, 0):       /* bc */
1095         case B_OPCODE (16, 0, 1):       /* bcl */
1096         case B_OPCODE (16, 1, 0):       /* bca */
1097         case B_OPCODE (16, 1, 1):       /* bcla */
1098                 if (!get_operand_value (op, instr, O_BD, &addr) ||
1099                         !get_operand_value (op, instr, O_BO, &bo) ||
1100                         !get_operand_value (op, instr, O_BI, &bi) ||
1101                         !get_operand_value (op, instr, O_AA, &aa) ||
1102                         !get_operand_value (op, instr, O_LK, &lk))
1103                         return FALSE;
1104
1105                 if ((addr & (1 << 13)) != 0)
1106                         addr = addr - (1 << 14);
1107                 addr <<= 2;
1108                 conditional = 1;
1109                 branch = 1;
1110                 break;
1111
1112         case I_OPCODE (18, 0, 0):       /* b */
1113         case I_OPCODE (18, 0, 1):       /* bl */
1114         case I_OPCODE (18, 1, 0):       /* ba */
1115         case I_OPCODE (18, 1, 1):       /* bla */
1116                 if (!get_operand_value (op, instr, O_LI, &addr) ||
1117                         !get_operand_value (op, instr, O_AA, &aa) ||
1118                         !get_operand_value (op, instr, O_LK, &lk))
1119                         return FALSE;
1120
1121                 if ((addr & (1 << 23)) != 0)
1122                         addr = addr - (1 << 24);
1123                 addr <<= 2;
1124                 conditional = 0;
1125                 branch = 1;
1126                 break;
1127
1128         case XL_OPCODE (19, 528, 0):    /* bcctr */
1129         case XL_OPCODE (19, 528, 1):    /* bcctrl */
1130                 if (!get_operand_value (op, instr, O_BO, &bo) ||
1131                         !get_operand_value (op, instr, O_BI, &bi) ||
1132                         !get_operand_value (op, instr, O_LK, &lk))
1133                         return FALSE;
1134
1135                 addr = ctr;
1136                 aa = 1;
1137                 conditional = 1;
1138                 branch = 1;
1139                 break;
1140
1141         case XL_OPCODE (19, 16, 0):     /* bclr */
1142         case XL_OPCODE (19, 16, 1):     /* bclrl */
1143                 if (!get_operand_value (op, instr, O_BO, &bo) ||
1144                         !get_operand_value (op, instr, O_BI, &bi) ||
1145                         !get_operand_value (op, instr, O_LK, &lk))
1146                         return FALSE;
1147
1148                 addr = lr;
1149                 aa = 1;
1150                 conditional = 1;
1151                 branch = 1;
1152                 break;
1153
1154         default:
1155                 conditional = 0;
1156                 branch = 0;
1157                 break;
1158         }
1159
1160         if (conditional) {
1161                 switch ((bo & 0x1e) >> 1) {
1162                 case 0:                         /* 0000y */
1163                         if (--ctr != 0)
1164                                 ctr_ok = 1;
1165
1166                         cond_ok = !(cr & (1 << (31 - bi)));
1167                         break;
1168
1169                 case 1:                         /* 0001y */
1170                         if (--ctr == 0)
1171                                 ctr_ok = 1;
1172
1173                         cond_ok = !(cr & (1 << (31 - bi)));
1174                         break;
1175
1176                 case 2:                         /* 001zy */
1177                         ctr_ok = 1;
1178                         cond_ok = !(cr & (1 << (31 - bi)));
1179                         break;
1180
1181                 case 4:                         /* 0100y */
1182                         if (--ctr != 0)
1183                                 ctr_ok = 1;
1184
1185                         cond_ok = cr & (1 << (31 - bi));
1186                         break;
1187
1188                 case 5:                         /* 0101y */
1189                         if (--ctr == 0)
1190                                 ctr_ok = 1;
1191
1192                         cond_ok = cr & (1 << (31 - bi));
1193                         break;
1194
1195                 case 6:                         /* 011zy */
1196                         ctr_ok = 1;
1197                         cond_ok = cr & (1 << (31 - bi));
1198                         break;
1199
1200                 case 8:                         /* 1z00y */
1201                         if (--ctr != 0)
1202                                 ctr_ok = cond_ok = 1;
1203                         break;
1204
1205                 case 9:                         /* 1z01y */
1206                         if (--ctr == 0)
1207                                 ctr_ok = cond_ok = 1;
1208                         break;
1209
1210                 case 10:                                /* 1z1zz */
1211                         ctr_ok = cond_ok = 1;
1212                         break;
1213                 }
1214         }
1215
1216         if (branch && (!conditional || (ctr_ok && cond_ok))) {
1217                 if (aa)
1218                         step = addr;
1219                 else
1220                         step = addr + pc;
1221
1222                 if (lk)
1223                         next = pc + 4;
1224                 else
1225                         next = step;
1226         } else {
1227                 step = next = pc + 4;
1228         }
1229
1230         if (step_over == TRUE)
1231                 *(unsigned long *) nextaddr = next;
1232         else
1233                 *(unsigned long *) nextaddr = step;
1234
1235         return TRUE;
1236 }                                                               /* find_next_address */
1237
1238
1239 /*
1240  * Copyright (c) 2000 William L. Pitts and W. Gerald Hicks
1241  * All rights reserved.
1242  *
1243  * Redistribution and use in source and binary forms are freely
1244  * permitted provided that the above copyright notice and this
1245  * paragraph and the following disclaimer are duplicated in all
1246  * such forms.
1247  *
1248  * This software is provided "AS IS" and without any express or
1249  * implied warranties, including, without limitation, the implied
1250  * warranties of merchantability and fitness for a particular
1251  * purpose.
1252  */