Wed Jun 10 07:53:24 1992 Steve Chamberlain (sac@thepub.cygnus.com)
[deliverable/binutils-gdb.git] / binutils / m68k-pinsn.c
CommitLineData
2fa0b342 1/* Print m68k instructions for objdump
d8474a9b 2 Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
2fa0b342
DHW
3
4
5This file is part of the binutils.
6
7The binutils are free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
d8474a9b 9the Free Software Foundation; either version 2, or (at your option)
2fa0b342
DHW
10any later version.
11
12The binutils are distributed in the hope that they will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with the binutils; see the file COPYING. If not, write to
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
3bdb6bf8 21
2a5f387b 22#include "bfd.h"
2fa0b342 23#include "sysdep.h"
17e6f61f 24#include <stdio.h>
4aa58a0a 25#include "opcode/m68k.h"
2fa0b342 26
6ba70f64
DZ
27#ifndef GDB
28#define fprintf_filtered fprintf
29#define fputs_filtered fputs
30#endif
31
6f34472d
PB
32/* Sign-extend an (unsigned char). */
33#if __STDC__ == 1
34#define COERCE_SIGNED_CHAR(ch) ((signed char)(ch))
35#else
36#define COERCE_SIGNED_CHAR(ch) ((int)(((ch) ^ 0x80) & 0xFF) - 128)
37#endif
38
2fa0b342
DHW
39extern void print_address();
40
41/* 68k instructions are never longer than this many bytes. */
42#define MAXLEN 22
43
44/* Number of elements in the opcode table. */
45#define NOPCODES (sizeof m68k_opcodes / sizeof m68k_opcodes[0])
46
47extern char *reg_names[];
48char *fpcr_names[] = { "", "fpiar", "fpsr", "fpiar/fpsr", "fpcr",
49 "fpiar/fpcr", "fpsr/fpcr", "fpiar-fpcr"};
50
51char *reg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "a0", "a1", "a2", "a3", "a4", "a5", "fp", "sp", "ps", "pc"};
52static unsigned char *print_insn_arg ();
53static unsigned char *print_indexed ();
54static void print_base ();
55static int fetch_arg ();
56
6f34472d 57#define NEXTBYTE(p) (p += 2, COERCE_SIGNED_CHAR(p[-1]))
2fa0b342
DHW
58
59#define NEXTWORD(p) \
60 (p += 2, ((((char *)p)[-2]) << 8) + p[-1])
61
62#define NEXTLONG(p) \
63 (p += 4, (((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])
64
6ba70f64
DZ
65/* NEXTSINGLE and NEXTDOUBLE handle alignment problems, but not
66 * byte-swapping or other float format differences. FIXME! */
67
68union number {
69 double d;
70 float f;
71 char c[10];
72};
2fa0b342 73
6ba70f64
DZ
74#define NEXTSINGLE(val, p) \
75 { int i; union number u;\
76 for (i = 0; i < sizeof(float); i++) u.c[i] = *p++; \
77 val = u.f; }
78
79#define NEXTDOUBLE(val, p) \
80 { int i; union number u;\
81 for (i = 0; i < sizeof(double); i++) u.c[i] = *p++; \
82 val = u.d; }
2fa0b342
DHW
83
84#define NEXTEXTEND(p) \
85 (p += 12, 0.0) /* Need a function to convert from extended to double
86 precision... */
87
88#define NEXTPACKED(p) \
89 (p += 12, 0.0) /* Need a function to convert from packed to double
90 precision. Actually, it's easier to print a
91 packed number than a double anyway, so maybe
92 there should be a special case to handle this... */
93\f
94/* Print the m68k instruction at address MEMADDR in debugged memory,
95 on STREAM. Returns length of the instruction, in bytes. */
96
97int
98print_insn_m68k(addr, buffer, stream)
99 bfd_vma addr;
100unsigned char *buffer;
101 FILE *stream;
102{
103 register unsigned int i;
104 register unsigned char *p;
105 register char *d;
106 register unsigned int bestmask;
107 int best;
108
109
110
111 bestmask = 0;
112 best = -1;
113 for (i = 0; i < NOPCODES; i++)
114 {
115 register unsigned int opcode = m68k_opcodes[i].opcode;
116 register unsigned int match = m68k_opcodes[i].match;
117 if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
118 && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
119 && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
120 && ((0xff & buffer[3] & match) == (0xff & opcode)))
121 {
122 /* Don't use for printout the variants of divul and divsl
123 that have the same register number in two places.
124 The more general variants will match instead. */
125 for (d = m68k_opcodes[i].args; *d; d += 2)
126 if (d[1] == 'D')
127 break;
128
129 /* Don't use for printout the variants of most floating
130 point coprocessor instructions which use the same
131 register number in two places, as above. */
132 if (*d == 0)
133 for (d = m68k_opcodes[i].args; *d; d += 2)
134 if (d[1] == 't')
135 break;
136
137 if (*d == 0 && match > bestmask)
138 {
139 best = i;
140 bestmask = match;
141 }
142 }
143 }
144
145 /* Handle undefined instructions. */
146 if (best < 0)
147 {
6ba70f64 148 fprintf_filtered (stream, "0%o", (unsigned) (buffer[0] << 8) + buffer[1]);
2fa0b342
DHW
149 return 2;
150 }
151
6ba70f64 152 fprintf_filtered (stream, "%s", m68k_opcodes[best].name);
2fa0b342
DHW
153
154 /* Point at first word of argument data,
155 and at descriptor for first argument. */
156 p = buffer + 2;
157
158 /* Why do this this way? -MelloN */
159 for (d = m68k_opcodes[best].args; *d; d += 2)
160 {
161 if (d[0] == '#')
162 {
163 if (d[1] == 'l' && p - buffer < 6)
164 p = buffer + 6;
165 else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8' )
166 p = buffer + 4;
167 }
168 if (d[1] >= '1' && d[1] <= '3' && p - buffer < 4)
169 p = buffer + 4;
170 if (d[1] >= '4' && d[1] <= '6' && p - buffer < 6)
171 p = buffer + 6;
172 if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
173 p = buffer + 4;
174 }
175
176 d = m68k_opcodes[best].args;
177
178 if (*d)
6ba70f64 179 fputs_filtered (" ", stream);
2fa0b342
DHW
180
181 while (*d)
182 {
183 p = print_insn_arg (d, buffer, p, addr + p - buffer, stream);
184 d += 2;
185 if (*d && *(d - 2) != 'I' && *d != 'k')
6ba70f64 186 fputs_filtered (",", stream);
2fa0b342
DHW
187 }
188 return p - buffer;
189}
190
191static unsigned char *
192print_insn_arg (d, buffer, p, addr, stream)
193 char *d;
194 unsigned char *buffer;
195 register unsigned char *p;
196 bfd_vma addr; /* PC for this arg to be relative to */
197 FILE *stream;
198{
5a77e916 199 register int val = 0;
2fa0b342
DHW
200 register int place = d[1];
201 int regno;
202 register char *regname;
203 register unsigned char *p1;
5a77e916 204 register double flval = 0;
2fa0b342
DHW
205 int flt_p;
206
207 switch (*d)
208 {
209 case 'C':
6ba70f64 210 fprintf_filtered (stream, "ccr");
2fa0b342
DHW
211 break;
212
213 case 'S':
6ba70f64 214 fprintf_filtered (stream, "sr");
2fa0b342
DHW
215 break;
216
217 case 'U':
6ba70f64 218 fprintf_filtered (stream, "usp");
2fa0b342
DHW
219 break;
220
221 case 'J':
222 {
223 static struct { char *name; int value; } names[]
224 = {{"sfc", 0x000}, {"dfc", 0x001}, {"cacr", 0x002},
225 {"usp", 0x800}, {"vbr", 0x801}, {"caar", 0x802},
226 {"msp", 0x803}, {"isp", 0x804}};
227
228 val = fetch_arg (buffer, place, 12);
229 for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
230 if (names[regno].value == val)
231 {
6ba70f64 232 fprintf_filtered (stream, names[regno].name);
2fa0b342
DHW
233 break;
234 }
235 if (regno < 0)
6ba70f64 236 fprintf_filtered (stream, "%d", val);
2fa0b342
DHW
237 }
238 break;
239
240 case 'Q':
241 val = fetch_arg (buffer, place, 3);
6ba70f64
DZ
242 /* 0 means 8, except for the bkpt instruction... */
243 if (val == 0 && d[1] != 's')
244 val = 8;
245 fprintf_filtered (stream, "#%d", val);
2fa0b342
DHW
246 break;
247
248 case 'M':
249 val = fetch_arg (buffer, place, 8);
250 if (val & 0x80)
251 val = val - 0x100;
6ba70f64 252 fprintf_filtered (stream, "#%d", val);
2fa0b342
DHW
253 break;
254
255 case 'T':
256 val = fetch_arg (buffer, place, 4);
6ba70f64 257 fprintf_filtered (stream, "#%d", val);
2fa0b342
DHW
258 break;
259
260 case 'D':
6ba70f64 261 fprintf_filtered (stream, "%s", reg_names[fetch_arg (buffer, place, 3)]);
2fa0b342
DHW
262 break;
263
264 case 'A':
6ba70f64 265 fprintf_filtered (stream, "%s",
2fa0b342
DHW
266 reg_names[fetch_arg (buffer, place, 3) + 010]);
267 break;
268
269 case 'R':
6ba70f64 270 fprintf_filtered (stream, "%s", reg_names[fetch_arg (buffer, place, 4)]);
2fa0b342
DHW
271 break;
272
273 case 'F':
6ba70f64 274 fprintf_filtered (stream, "fp%d", fetch_arg (buffer, place, 3));
2fa0b342
DHW
275 break;
276
277 case 'O':
278 val = fetch_arg (buffer, place, 6);
279 if (val & 0x20)
6ba70f64 280 fprintf_filtered (stream, "%s", reg_names [val & 7]);
2fa0b342 281 else
6ba70f64 282 fprintf_filtered (stream, "%d", val);
2fa0b342
DHW
283 break;
284
285 case '+':
6ba70f64 286 fprintf_filtered (stream, "%s@+",
2fa0b342
DHW
287 reg_names[fetch_arg (buffer, place, 3) + 8]);
288 break;
289
290 case '-':
6ba70f64 291 fprintf_filtered (stream, "%s@-",
2fa0b342
DHW
292 reg_names[fetch_arg (buffer, place, 3) + 8]);
293 break;
294
295 case 'k':
296 if (place == 'k')
6ba70f64 297 fprintf_filtered (stream, "{%s}", reg_names[fetch_arg (buffer, place, 3)]);
2fa0b342
DHW
298 else if (place == 'C')
299 {
300 val = fetch_arg (buffer, place, 7);
301 if ( val > 63 ) /* This is a signed constant. */
302 val -= 128;
6ba70f64 303 fprintf_filtered (stream, "{#%d}", val);
2fa0b342
DHW
304 }
305 else
6ba70f64 306 fprintf_filtered(stderr, "Invalid arg format in opcode table: \"%c%c\".",
2fa0b342
DHW
307 *d, place);
308 break;
309
310 case '#':
311 case '^':
312 p1 = buffer + (*d == '#' ? 2 : 4);
313 if (place == 's')
314 val = fetch_arg (buffer, place, 4);
315 else if (place == 'C')
316 val = fetch_arg (buffer, place, 7);
317 else if (place == '8')
318 val = fetch_arg (buffer, place, 3);
319 else if (place == '3')
320 val = fetch_arg (buffer, place, 8);
321 else if (place == 'b')
322 val = NEXTBYTE (p1);
323 else if (place == 'w')
324 val = NEXTWORD (p1);
325 else if (place == 'l')
326 val = NEXTLONG (p1);
327 else
6ba70f64 328 fprintf_filtered(stderr, "Invalid arg format in opcode table: \"%c%c\".",
2fa0b342 329 *d, place);
6ba70f64 330 fprintf_filtered (stream, "#%d", val);
2fa0b342
DHW
331 break;
332
333 case 'B':
334 if (place == 'b')
335 val = NEXTBYTE (p);
b27d2046 336 else if (place == 'B')
6f34472d 337 val = COERCE_SIGNED_CHAR(buffer[1]);
b27d2046 338 else if (place == 'w' || place == 'W')
2fa0b342 339 val = NEXTWORD (p);
b27d2046 340 else if (place == 'l' || place == 'L')
2fa0b342
DHW
341 val = NEXTLONG (p);
342 else if (place == 'g')
343 {
344 val = ((char *)buffer)[1];
345 if (val == 0)
346 val = NEXTWORD (p);
347 else if (val == -1)
348 val = NEXTLONG (p);
349 }
350 else if (place == 'c')
351 {
352 if (buffer[1] & 0x40) /* If bit six is one, long offset */
353 val = NEXTLONG (p);
354 else
355 val = NEXTWORD (p);
356 }
357 else
6ba70f64 358 fprintf_filtered(stderr, "Invalid arg format in opcode table: \"%c%c\".",
2fa0b342
DHW
359 *d, place);
360 print_address (addr + val, stream);
361 break;
362
363 case 'd':
364 val = NEXTWORD (p);
6ba70f64 365 fprintf_filtered (stream, "%s@(%d)",
2fa0b342
DHW
366 reg_names[fetch_arg (buffer, place, 3)], val);
367 break;
368
369 case 's':
6ba70f64 370 fprintf_filtered (stream, "%s",
2fa0b342
DHW
371 fpcr_names[fetch_arg (buffer, place, 3)]);
372 break;
373
374 case 'I':
375 val = fetch_arg (buffer, 'd', 3); /* Get coprocessor ID... */
376 if (val != 1) /* Unusual coprocessor ID? */
6ba70f64 377 fprintf_filtered (stream, "(cpid=%d) ", val);
2fa0b342
DHW
378 if (place == 'i')
379 p += 2; /* Skip coprocessor extended operands */
380 break;
381
382 case '*':
383 case '~':
384 case '%':
385 case ';':
386 case '@':
387 case '!':
388 case '$':
389 case '?':
390 case '/':
391 case '&':
392
393 if (place == 'd')
394 {
395 val = fetch_arg (buffer, 'x', 6);
396 val = ((val & 7) << 3) + ((val >> 3) & 7);
397 }
398 else
399 val = fetch_arg (buffer, 's', 6);
400
401 /* Get register number assuming address register. */
402 regno = (val & 7) + 8;
403 regname = reg_names[regno];
404 switch (val >> 3)
405 {
406 case 0:
6ba70f64 407 fprintf_filtered (stream, "%s", reg_names[val]);
2fa0b342
DHW
408 break;
409
410 case 1:
6ba70f64 411 fprintf_filtered (stream, "%s", regname);
2fa0b342
DHW
412 break;
413
414 case 2:
6ba70f64 415 fprintf_filtered (stream, "%s@", regname);
2fa0b342
DHW
416 break;
417
418 case 3:
6ba70f64 419 fprintf_filtered (stream, "%s@+", regname);
2fa0b342
DHW
420 break;
421
422 case 4:
6ba70f64 423 fprintf_filtered (stream, "%s@-", regname);
2fa0b342
DHW
424 break;
425
426 case 5:
427 val = NEXTWORD (p);
6ba70f64 428 fprintf_filtered (stream, "%s@(%d)", regname, val);
2fa0b342
DHW
429 break;
430
431 case 6:
432 p = print_indexed (regno, p, addr, stream);
433 break;
434
435 case 7:
436 switch (val & 7)
437 {
438 case 0:
439 val = NEXTWORD (p);
6ba70f64 440 fprintf_filtered (stream, "@#");
2fa0b342
DHW
441 print_address (val, stream);
442 break;
443
444 case 1:
445 val = NEXTLONG (p);
6ba70f64 446 fprintf_filtered (stream, "@#");
2fa0b342
DHW
447 print_address (val, stream);
448 break;
449
450 case 2:
451 val = NEXTWORD (p);
452 print_address (addr + val, stream);
453 break;
454
455 case 3:
456 p = print_indexed (-1, p, addr, stream);
457 break;
458
459 case 4:
460 flt_p = 1; /* Assume it's a float... */
461 switch( place )
462 {
463 case 'b':
464 val = NEXTBYTE (p);
465 flt_p = 0;
466 break;
467
468 case 'w':
469 val = NEXTWORD (p);
470 flt_p = 0;
471 break;
472
473 case 'l':
474 val = NEXTLONG (p);
475 flt_p = 0;
476 break;
477
478 case 'f':
6ba70f64 479 NEXTSINGLE(flval, p);
2fa0b342
DHW
480 break;
481
482 case 'F':
6ba70f64 483 NEXTDOUBLE(flval, p);
2fa0b342
DHW
484 break;
485
486 case 'x':
487 flval = NEXTEXTEND(p);
488 break;
489
490 case 'p':
491 flval = NEXTPACKED(p);
492 break;
493
494 default:
6ba70f64 495 fprintf_filtered(stderr, "Invalid arg format in opcode table: \"%c%c\".",
2fa0b342
DHW
496 *d, place);
497 }
498 if ( flt_p ) /* Print a float? */
6ba70f64 499 fprintf_filtered (stream, "#%g", flval);
2fa0b342 500 else
6ba70f64 501 fprintf_filtered (stream, "#%d", val);
2fa0b342
DHW
502 break;
503
504 default:
6ba70f64 505 fprintf_filtered (stream, "<invalid address mode 0%o>", (unsigned) val);
2fa0b342
DHW
506 }
507 }
508 break;
509
510 case 'L':
511 case 'l':
512 if (place == 'w')
513 {
514 char doneany;
515 p1 = buffer + 2;
516 val = NEXTWORD (p1);
517 /* Move the pointer ahead if this point is farther ahead
518 than the last. */
519 p = p1 > p ? p1 : p;
520 if (val == 0)
521 {
6ba70f64 522 fputs_filtered ("#0", stream);
2fa0b342
DHW
523 break;
524 }
525 if (*d == 'l')
526 {
527 register int newval = 0;
528 for (regno = 0; regno < 16; ++regno)
529 if (val & (0x8000 >> regno))
530 newval |= 1 << regno;
531 val = newval;
532 }
533 val &= 0xffff;
534 doneany = 0;
535 for (regno = 0; regno < 16; ++regno)
536 if (val & (1 << regno))
537 {
538 int first_regno;
539 if (doneany)
6ba70f64 540 fputs_filtered ("/", stream);
2fa0b342 541 doneany = 1;
6ba70f64 542 fprintf_filtered (stream, "%s", reg_names[regno]);
2fa0b342
DHW
543 first_regno = regno;
544 while (val & (1 << (regno + 1)))
545 ++regno;
546 if (regno > first_regno)
6ba70f64 547 fprintf_filtered (stream, "-%s", reg_names[regno]);
2fa0b342
DHW
548 }
549 }
550 else if (place == '3')
551 {
552 /* `fmovem' insn. */
553 char doneany;
554 val = fetch_arg (buffer, place, 8);
555 if (val == 0)
556 {
6ba70f64 557 fputs_filtered ("#0", stream);
2fa0b342
DHW
558 break;
559 }
560 if (*d == 'l')
561 {
562 register int newval = 0;
563 for (regno = 0; regno < 8; ++regno)
564 if (val & (0x80 >> regno))
565 newval |= 1 << regno;
566 val = newval;
567 }
568 val &= 0xff;
569 doneany = 0;
570 for (regno = 0; regno < 8; ++regno)
571 if (val & (1 << regno))
572 {
573 int first_regno;
574 if (doneany)
6ba70f64 575 fputs_filtered ("/", stream);
2fa0b342 576 doneany = 1;
6ba70f64 577 fprintf_filtered (stream, "fp%d", regno);
2fa0b342
DHW
578 first_regno = regno;
579 while (val & (1 << (regno + 1)))
580 ++regno;
581 if (regno > first_regno)
6ba70f64 582 fprintf_filtered (stream, "-fp%d", regno);
2fa0b342
DHW
583 }
584 }
585 else
6ba70f64 586 goto de_fault;
2fa0b342
DHW
587 break;
588
6ba70f64
DZ
589 default: de_fault:
590 fprintf_filtered(stderr, "Invalid arg format in opcode table: \"%c\".", *d);
2fa0b342
DHW
591 }
592
593 return (unsigned char *) p;
594}
595
596/* Fetch BITS bits from a position in the instruction specified by CODE.
597 CODE is a "place to put an argument", or 'x' for a destination
598 that is a general address (mode and register).
599 BUFFER contains the instruction. */
600
601static int
602fetch_arg (buffer, code, bits)
603 unsigned char *buffer;
604 char code;
605 int bits;
606{
5a77e916 607 register int val = 0;
2fa0b342
DHW
608 switch (code)
609 {
610 case 's':
611 val = buffer[1];
612 break;
613
614 case 'd': /* Destination, for register or quick. */
615 val = (buffer[0] << 8) + buffer[1];
616 val >>= 9;
617 break;
618
619 case 'x': /* Destination, for general arg */
620 val = (buffer[0] << 8) + buffer[1];
621 val >>= 6;
622 break;
623
624 case 'k':
625 val = (buffer[3] >> 4);
626 break;
627
628 case 'C':
629 val = buffer[3];
630 break;
631
632 case '1':
633 val = (buffer[2] << 8) + buffer[3];
634 val >>= 12;
635 break;
636
637 case '2':
638 val = (buffer[2] << 8) + buffer[3];
639 val >>= 6;
640 break;
641
642 case '3':
643 case 'j':
644 val = (buffer[2] << 8) + buffer[3];
645 break;
646
647 case '4':
648 val = (buffer[4] << 8) + buffer[5];
649 val >>= 12;
650 break;
651
652 case '5':
653 val = (buffer[4] << 8) + buffer[5];
654 val >>= 6;
655 break;
656
657 case '6':
658 val = (buffer[4] << 8) + buffer[5];
659 break;
660
661 case '7':
662 val = (buffer[2] << 8) + buffer[3];
663 val >>= 7;
664 break;
665
666 case '8':
667 val = (buffer[2] << 8) + buffer[3];
668 val >>= 10;
669 break;
670
671 default:
672 abort ();
673 }
674
675 switch (bits)
676 {
677 case 3:
678 return val & 7;
679 case 4:
680 return val & 017;
681 case 5:
682 return val & 037;
683 case 6:
684 return val & 077;
685 case 7:
686 return val & 0177;
687 case 8:
688 return val & 0377;
689 case 12:
690 return val & 07777;
691 default:
692 abort ();
693 return(0);
694 }
695} /* fetch_arg() */
696
697/* Print an indexed argument. The base register is BASEREG (-1 for pc).
698 P points to extension word, in buffer.
699 ADDR is the nominal core address of that extension word. */
700
701static unsigned char *
702print_indexed (basereg, p, addr, stream)
703 int basereg;
704 unsigned char *p;
705 FILE *stream;
706bfd_vma addr;
707{
708 register int word;
709 static char *scales[] = {"", "*2", "*4", "*8"};
710 register int base_disp;
711 register int outer_disp;
712 char buf[40];
713
714 word = NEXTWORD (p);
715
716 /* Generate the text for the index register.
717 Where this will be output is not yet determined. */
718 sprintf (buf, "[%s.%c%s]",
719 reg_names[(word >> 12) & 0xf],
720 (word & 0x800) ? 'l' : 'w',
721 scales[(word >> 9) & 3]);
722
723 /* Handle the 68000 style of indexing. */
724
725 if ((word & 0x100) == 0)
726 {
727 print_base (basereg,
728 ((word & 0x80) ? word | 0xff00 : word & 0xff)
729 + ((basereg == -1) ? addr : 0),
730 stream);
6ba70f64 731 fputs_filtered (buf, stream);
2fa0b342
DHW
732 return p;
733 }
734
735 /* Handle the generalized kind. */
736 /* First, compute the displacement to add to the base register. */
737
738 if (word & 0200)
739 basereg = -2;
740 if (word & 0100)
741 buf[0] = 0;
742 base_disp = 0;
743 switch ((word >> 4) & 3)
744 {
745 case 2:
746 base_disp = NEXTWORD (p);
747 break;
748 case 3:
749 base_disp = NEXTLONG (p);
750 }
751 if (basereg == -1)
752 base_disp += addr;
753
754 /* Handle single-level case (not indirect) */
755
756 if ((word & 7) == 0)
757 {
758 print_base (basereg, base_disp, stream);
6ba70f64 759 fputs_filtered (buf, stream);
2fa0b342
DHW
760 return p;
761 }
762
763 /* Two level. Compute displacement to add after indirection. */
764
765 outer_disp = 0;
766 switch (word & 3)
767 {
768 case 2:
769 outer_disp = NEXTWORD (p);
770 break;
771 case 3:
772 outer_disp = NEXTLONG (p);
773 }
774
6ba70f64 775 fprintf_filtered (stream, "%d(", outer_disp);
2fa0b342
DHW
776 print_base (basereg, base_disp, stream);
777
778 /* If postindexed, print the closeparen before the index. */
779 if (word & 4)
6ba70f64 780 fprintf_filtered (stream, ")%s", buf);
2fa0b342
DHW
781 /* If preindexed, print the closeparen after the index. */
782 else
6ba70f64 783 fprintf_filtered (stream, "%s)", buf);
2fa0b342
DHW
784
785 return p;
786}
787
788/* Print a base register REGNO and displacement DISP, on STREAM.
789 REGNO = -1 for pc, -2 for none (suppressed). */
790
791static void
792print_base (regno, disp, stream)
793 int regno;
794 int disp;
795 FILE *stream;
796{
797 if (regno == -2)
6ba70f64 798 fprintf_filtered (stream, "%d", disp);
2fa0b342 799 else if (regno == -1)
6ba70f64 800 fprintf_filtered (stream, "0x%x", (unsigned) disp);
2fa0b342 801 else
6ba70f64 802 fprintf_filtered (stream, "%d(%s)", disp, reg_names[regno]);
2fa0b342 803}
This page took 0.105428 seconds and 4 git commands to generate.