Change source files over to GPLv3.
[deliverable/binutils-gdb.git] / opcodes / m68k-dis.c
1 /* Print Motorola 68k instructions.
2 Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
3 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
4 Free Software Foundation, Inc.
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 program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
22
23 #include "sysdep.h"
24 #include "dis-asm.h"
25 #include "floatformat.h"
26 #include "libiberty.h"
27 #include "opintl.h"
28
29 #include "opcode/m68k.h"
30
31 /* Local function prototypes. */
32
33 const char * const fpcr_names[] =
34 {
35 "", "%fpiar", "%fpsr", "%fpiar/%fpsr", "%fpcr",
36 "%fpiar/%fpcr", "%fpsr/%fpcr", "%fpiar/%fpsr/%fpcr"
37 };
38
39 static char *const reg_names[] =
40 {
41 "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
42 "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%fp", "%sp",
43 "%ps", "%pc"
44 };
45
46 /* Name of register halves for MAC/EMAC.
47 Seperate from reg_names since 'spu', 'fpl' look weird. */
48 static char *const reg_half_names[] =
49 {
50 "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
51 "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",
52 "%ps", "%pc"
53 };
54
55 /* Sign-extend an (unsigned char). */
56 #if __STDC__ == 1
57 #define COERCE_SIGNED_CHAR(ch) ((signed char) (ch))
58 #else
59 #define COERCE_SIGNED_CHAR(ch) ((int) (((ch) ^ 0x80) & 0xFF) - 128)
60 #endif
61
62 /* Get a 1 byte signed integer. */
63 #define NEXTBYTE(p) (p += 2, FETCH_DATA (info, p), COERCE_SIGNED_CHAR(p[-1]))
64
65 /* Get a 2 byte signed integer. */
66 #define COERCE16(x) ((int) (((x) ^ 0x8000) - 0x8000))
67 #define NEXTWORD(p) \
68 (p += 2, FETCH_DATA (info, p), \
69 COERCE16 ((p[-2] << 8) + p[-1]))
70
71 /* Get a 4 byte signed integer. */
72 #define COERCE32(x) ((bfd_signed_vma) ((x) ^ 0x80000000) - 0x80000000)
73 #define NEXTLONG(p) \
74 (p += 4, FETCH_DATA (info, p), \
75 (COERCE32 ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1])))
76
77 /* Get a 4 byte unsigned integer. */
78 #define NEXTULONG(p) \
79 (p += 4, FETCH_DATA (info, p), \
80 (unsigned int) ((((((p[-4] << 8) + p[-3]) << 8) + p[-2]) << 8) + p[-1]))
81
82 /* Get a single precision float. */
83 #define NEXTSINGLE(val, p) \
84 (p += 4, FETCH_DATA (info, p), \
85 floatformat_to_double (&floatformat_ieee_single_big, (char *) p - 4, &val))
86
87 /* Get a double precision float. */
88 #define NEXTDOUBLE(val, p) \
89 (p += 8, FETCH_DATA (info, p), \
90 floatformat_to_double (&floatformat_ieee_double_big, (char *) p - 8, &val))
91
92 /* Get an extended precision float. */
93 #define NEXTEXTEND(val, p) \
94 (p += 12, FETCH_DATA (info, p), \
95 floatformat_to_double (&floatformat_m68881_ext, (char *) p - 12, &val))
96
97 /* Need a function to convert from packed to double
98 precision. Actually, it's easier to print a
99 packed number than a double anyway, so maybe
100 there should be a special case to handle this... */
101 #define NEXTPACKED(p) \
102 (p += 12, FETCH_DATA (info, p), 0.0)
103 \f
104 /* Maximum length of an instruction. */
105 #define MAXLEN 22
106
107 #include <setjmp.h>
108
109 struct private
110 {
111 /* Points to first byte not fetched. */
112 bfd_byte *max_fetched;
113 bfd_byte the_buffer[MAXLEN];
114 bfd_vma insn_start;
115 jmp_buf bailout;
116 };
117
118 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
119 to ADDR (exclusive) are valid. Returns 1 for success, longjmps
120 on error. */
121 #define FETCH_DATA(info, addr) \
122 ((addr) <= ((struct private *) (info->private_data))->max_fetched \
123 ? 1 : fetch_data ((info), (addr)))
124
125 static int
126 fetch_data (struct disassemble_info *info, bfd_byte *addr)
127 {
128 int status;
129 struct private *priv = (struct private *)info->private_data;
130 bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
131
132 status = (*info->read_memory_func) (start,
133 priv->max_fetched,
134 addr - priv->max_fetched,
135 info);
136 if (status != 0)
137 {
138 (*info->memory_error_func) (status, start, info);
139 longjmp (priv->bailout, 1);
140 }
141 else
142 priv->max_fetched = addr;
143 return 1;
144 }
145 \f
146 /* This function is used to print to the bit-bucket. */
147 static int
148 dummy_printer (FILE *file ATTRIBUTE_UNUSED,
149 const char *format ATTRIBUTE_UNUSED,
150 ...)
151 {
152 return 0;
153 }
154
155 static void
156 dummy_print_address (bfd_vma vma ATTRIBUTE_UNUSED,
157 struct disassemble_info *info ATTRIBUTE_UNUSED)
158 {
159 }
160
161 /* Fetch BITS bits from a position in the instruction specified by CODE.
162 CODE is a "place to put an argument", or 'x' for a destination
163 that is a general address (mode and register).
164 BUFFER contains the instruction. */
165
166 static int
167 fetch_arg (unsigned char *buffer,
168 int code,
169 int bits,
170 disassemble_info *info)
171 {
172 int val = 0;
173
174 switch (code)
175 {
176 case '/': /* MAC/EMAC mask bit. */
177 val = buffer[3] >> 5;
178 break;
179
180 case 'G': /* EMAC ACC load. */
181 val = ((buffer[3] >> 3) & 0x2) | ((~buffer[1] >> 7) & 0x1);
182 break;
183
184 case 'H': /* EMAC ACC !load. */
185 val = ((buffer[3] >> 3) & 0x2) | ((buffer[1] >> 7) & 0x1);
186 break;
187
188 case ']': /* EMAC ACCEXT bit. */
189 val = buffer[0] >> 2;
190 break;
191
192 case 'I': /* MAC/EMAC scale factor. */
193 val = buffer[2] >> 1;
194 break;
195
196 case 'F': /* EMAC ACCx. */
197 val = buffer[0] >> 1;
198 break;
199
200 case 'f':
201 val = buffer[1];
202 break;
203
204 case 's':
205 val = buffer[1];
206 break;
207
208 case 'd': /* Destination, for register or quick. */
209 val = (buffer[0] << 8) + buffer[1];
210 val >>= 9;
211 break;
212
213 case 'x': /* Destination, for general arg. */
214 val = (buffer[0] << 8) + buffer[1];
215 val >>= 6;
216 break;
217
218 case 'k':
219 FETCH_DATA (info, buffer + 3);
220 val = (buffer[3] >> 4);
221 break;
222
223 case 'C':
224 FETCH_DATA (info, buffer + 3);
225 val = buffer[3];
226 break;
227
228 case '1':
229 FETCH_DATA (info, buffer + 3);
230 val = (buffer[2] << 8) + buffer[3];
231 val >>= 12;
232 break;
233
234 case '2':
235 FETCH_DATA (info, buffer + 3);
236 val = (buffer[2] << 8) + buffer[3];
237 val >>= 6;
238 break;
239
240 case '3':
241 case 'j':
242 FETCH_DATA (info, buffer + 3);
243 val = (buffer[2] << 8) + buffer[3];
244 break;
245
246 case '4':
247 FETCH_DATA (info, buffer + 5);
248 val = (buffer[4] << 8) + buffer[5];
249 val >>= 12;
250 break;
251
252 case '5':
253 FETCH_DATA (info, buffer + 5);
254 val = (buffer[4] << 8) + buffer[5];
255 val >>= 6;
256 break;
257
258 case '6':
259 FETCH_DATA (info, buffer + 5);
260 val = (buffer[4] << 8) + buffer[5];
261 break;
262
263 case '7':
264 FETCH_DATA (info, buffer + 3);
265 val = (buffer[2] << 8) + buffer[3];
266 val >>= 7;
267 break;
268
269 case '8':
270 FETCH_DATA (info, buffer + 3);
271 val = (buffer[2] << 8) + buffer[3];
272 val >>= 10;
273 break;
274
275 case '9':
276 FETCH_DATA (info, buffer + 3);
277 val = (buffer[2] << 8) + buffer[3];
278 val >>= 5;
279 break;
280
281 case 'e':
282 val = (buffer[1] >> 6);
283 break;
284
285 case 'E':
286 FETCH_DATA (info, buffer + 3);
287 val = (buffer[2] >> 1);
288 break;
289
290 case 'm':
291 val = (buffer[1] & 0x40 ? 0x8 : 0)
292 | ((buffer[0] >> 1) & 0x7)
293 | (buffer[3] & 0x80 ? 0x10 : 0);
294 break;
295
296 case 'n':
297 val = (buffer[1] & 0x40 ? 0x8 : 0) | ((buffer[0] >> 1) & 0x7);
298 break;
299
300 case 'o':
301 val = (buffer[2] >> 4) | (buffer[3] & 0x80 ? 0x10 : 0);
302 break;
303
304 case 'M':
305 val = (buffer[1] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0);
306 break;
307
308 case 'N':
309 val = (buffer[3] & 0xf) | (buffer[3] & 0x40 ? 0x10 : 0);
310 break;
311
312 case 'h':
313 val = buffer[2] >> 2;
314 break;
315
316 default:
317 abort ();
318 }
319
320 /* bits is never too big. */
321 return val & ((1 << bits) - 1);
322 }
323
324 /* Check if an EA is valid for a particular code. This is required
325 for the EMAC instructions since the type of source address determines
326 if it is a EMAC-load instruciton if the EA is mode 2-5, otherwise it
327 is a non-load EMAC instruction and the bits mean register Ry.
328 A similar case exists for the movem instructions where the register
329 mask is interpreted differently for different EAs. */
330
331 static bfd_boolean
332 m68k_valid_ea (char code, int val)
333 {
334 int mode, mask;
335 #define M(n0,n1,n2,n3,n4,n5,n6,n70,n71,n72,n73,n74) \
336 (n0 | n1 << 1 | n2 << 2 | n3 << 3 | n4 << 4 | n5 << 5 | n6 << 6 \
337 | n70 << 7 | n71 << 8 | n72 << 9 | n73 << 10 | n74 << 11)
338
339 switch (code)
340 {
341 case '*':
342 mask = M (1,1,1,1,1,1,1,1,1,1,1,1);
343 break;
344 case '~':
345 mask = M (0,0,1,1,1,1,1,1,1,0,0,0);
346 break;
347 case '%':
348 mask = M (1,1,1,1,1,1,1,1,1,0,0,0);
349 break;
350 case ';':
351 mask = M (1,0,1,1,1,1,1,1,1,1,1,1);
352 break;
353 case '@':
354 mask = M (1,0,1,1,1,1,1,1,1,1,1,0);
355 break;
356 case '!':
357 mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
358 break;
359 case '&':
360 mask = M (0,0,1,0,0,1,1,1,1,0,0,0);
361 break;
362 case '$':
363 mask = M (1,0,1,1,1,1,1,1,1,0,0,0);
364 break;
365 case '?':
366 mask = M (1,0,1,0,0,1,1,1,1,0,0,0);
367 break;
368 case '/':
369 mask = M (1,0,1,0,0,1,1,1,1,1,1,0);
370 break;
371 case '|':
372 mask = M (0,0,1,0,0,1,1,1,1,1,1,0);
373 break;
374 case '>':
375 mask = M (0,0,1,0,1,1,1,1,1,0,0,0);
376 break;
377 case '<':
378 mask = M (0,0,1,1,0,1,1,1,1,1,1,0);
379 break;
380 case 'm':
381 mask = M (1,1,1,1,1,0,0,0,0,0,0,0);
382 break;
383 case 'n':
384 mask = M (0,0,0,0,0,1,0,0,0,1,0,0);
385 break;
386 case 'o':
387 mask = M (0,0,0,0,0,0,1,1,1,0,1,1);
388 break;
389 case 'p':
390 mask = M (1,1,1,1,1,1,0,0,0,0,0,0);
391 break;
392 case 'q':
393 mask = M (1,0,1,1,1,1,0,0,0,0,0,0);
394 break;
395 case 'v':
396 mask = M (1,0,1,1,1,1,0,1,1,0,0,0);
397 break;
398 case 'b':
399 mask = M (1,0,1,1,1,1,0,0,0,1,0,0);
400 break;
401 case 'w':
402 mask = M (0,0,1,1,1,1,0,0,0,1,0,0);
403 break;
404 case 'y':
405 mask = M (0,0,1,0,0,1,0,0,0,0,0,0);
406 break;
407 case 'z':
408 mask = M (0,0,1,0,0,1,0,0,0,1,0,0);
409 break;
410 case '4':
411 mask = M (0,0,1,1,1,1,0,0,0,0,0,0);
412 break;
413 default:
414 abort ();
415 }
416 #undef M
417
418 mode = (val >> 3) & 7;
419 if (mode == 7)
420 mode += val & 7;
421 return (mask & (1 << mode)) != 0;
422 }
423
424 /* Print a base register REGNO and displacement DISP, on INFO->STREAM.
425 REGNO = -1 for pc, -2 for none (suppressed). */
426
427 static void
428 print_base (int regno, bfd_vma disp, disassemble_info *info)
429 {
430 if (regno == -1)
431 {
432 (*info->fprintf_func) (info->stream, "%%pc@(");
433 (*info->print_address_func) (disp, info);
434 }
435 else
436 {
437 char buf[50];
438
439 if (regno == -2)
440 (*info->fprintf_func) (info->stream, "@(");
441 else if (regno == -3)
442 (*info->fprintf_func) (info->stream, "%%zpc@(");
443 else
444 (*info->fprintf_func) (info->stream, "%s@(", reg_names[regno]);
445
446 sprintf_vma (buf, disp);
447 (*info->fprintf_func) (info->stream, "%s", buf);
448 }
449 }
450
451 /* Print an indexed argument. The base register is BASEREG (-1 for pc).
452 P points to extension word, in buffer.
453 ADDR is the nominal core address of that extension word. */
454
455 static unsigned char *
456 print_indexed (int basereg,
457 unsigned char *p,
458 bfd_vma addr,
459 disassemble_info *info)
460 {
461 int word;
462 static char *const scales[] = { "", ":2", ":4", ":8" };
463 bfd_vma base_disp;
464 bfd_vma outer_disp;
465 char buf[40];
466 char vmabuf[50];
467
468 word = NEXTWORD (p);
469
470 /* Generate the text for the index register.
471 Where this will be output is not yet determined. */
472 sprintf (buf, "%s:%c%s",
473 reg_names[(word >> 12) & 0xf],
474 (word & 0x800) ? 'l' : 'w',
475 scales[(word >> 9) & 3]);
476
477 /* Handle the 68000 style of indexing. */
478
479 if ((word & 0x100) == 0)
480 {
481 base_disp = word & 0xff;
482 if ((base_disp & 0x80) != 0)
483 base_disp -= 0x100;
484 if (basereg == -1)
485 base_disp += addr;
486 print_base (basereg, base_disp, info);
487 (*info->fprintf_func) (info->stream, ",%s)", buf);
488 return p;
489 }
490
491 /* Handle the generalized kind. */
492 /* First, compute the displacement to add to the base register. */
493 if (word & 0200)
494 {
495 if (basereg == -1)
496 basereg = -3;
497 else
498 basereg = -2;
499 }
500 if (word & 0100)
501 buf[0] = '\0';
502 base_disp = 0;
503 switch ((word >> 4) & 3)
504 {
505 case 2:
506 base_disp = NEXTWORD (p);
507 break;
508 case 3:
509 base_disp = NEXTLONG (p);
510 }
511 if (basereg == -1)
512 base_disp += addr;
513
514 /* Handle single-level case (not indirect). */
515 if ((word & 7) == 0)
516 {
517 print_base (basereg, base_disp, info);
518 if (buf[0] != '\0')
519 (*info->fprintf_func) (info->stream, ",%s", buf);
520 (*info->fprintf_func) (info->stream, ")");
521 return p;
522 }
523
524 /* Two level. Compute displacement to add after indirection. */
525 outer_disp = 0;
526 switch (word & 3)
527 {
528 case 2:
529 outer_disp = NEXTWORD (p);
530 break;
531 case 3:
532 outer_disp = NEXTLONG (p);
533 }
534
535 print_base (basereg, base_disp, info);
536 if ((word & 4) == 0 && buf[0] != '\0')
537 {
538 (*info->fprintf_func) (info->stream, ",%s", buf);
539 buf[0] = '\0';
540 }
541 sprintf_vma (vmabuf, outer_disp);
542 (*info->fprintf_func) (info->stream, ")@(%s", vmabuf);
543 if (buf[0] != '\0')
544 (*info->fprintf_func) (info->stream, ",%s", buf);
545 (*info->fprintf_func) (info->stream, ")");
546
547 return p;
548 }
549
550 /* Returns number of bytes "eaten" by the operand, or
551 return -1 if an invalid operand was found, or -2 if
552 an opcode tabe error was found.
553 ADDR is the pc for this arg to be relative to. */
554
555 static int
556 print_insn_arg (const char *d,
557 unsigned char *buffer,
558 unsigned char *p0,
559 bfd_vma addr,
560 disassemble_info *info)
561 {
562 int val = 0;
563 int place = d[1];
564 unsigned char *p = p0;
565 int regno;
566 const char *regname;
567 unsigned char *p1;
568 double flval;
569 int flt_p;
570 bfd_signed_vma disp;
571 unsigned int uval;
572
573 switch (*d)
574 {
575 case 'c': /* Cache identifier. */
576 {
577 static char *const cacheFieldName[] = { "nc", "dc", "ic", "bc" };
578 val = fetch_arg (buffer, place, 2, info);
579 (*info->fprintf_func) (info->stream, cacheFieldName[val]);
580 break;
581 }
582
583 case 'a': /* Address register indirect only. Cf. case '+'. */
584 {
585 (*info->fprintf_func)
586 (info->stream,
587 "%s@",
588 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
589 break;
590 }
591
592 case '_': /* 32-bit absolute address for move16. */
593 {
594 uval = NEXTULONG (p);
595 (*info->print_address_func) (uval, info);
596 break;
597 }
598
599 case 'C':
600 (*info->fprintf_func) (info->stream, "%%ccr");
601 break;
602
603 case 'S':
604 (*info->fprintf_func) (info->stream, "%%sr");
605 break;
606
607 case 'U':
608 (*info->fprintf_func) (info->stream, "%%usp");
609 break;
610
611 case 'E':
612 (*info->fprintf_func) (info->stream, "%%acc");
613 break;
614
615 case 'G':
616 (*info->fprintf_func) (info->stream, "%%macsr");
617 break;
618
619 case 'H':
620 (*info->fprintf_func) (info->stream, "%%mask");
621 break;
622
623 case 'J':
624 {
625 /* FIXME: There's a problem here, different m68k processors call the
626 same address different names. This table can't get it right
627 because it doesn't know which processor it's disassembling for. */
628 static const struct { char *name; int value; } names[]
629 = {{"%sfc", 0x000}, {"%dfc", 0x001}, {"%cacr", 0x002},
630 {"%tc", 0x003}, {"%itt0",0x004}, {"%itt1", 0x005},
631 {"%dtt0",0x006}, {"%dtt1",0x007}, {"%buscr",0x008},
632 {"%usp", 0x800}, {"%vbr", 0x801}, {"%caar", 0x802},
633 {"%msp", 0x803}, {"%isp", 0x804},
634 /* reg c04 is sometimes called flashbar or rambar.
635 rec c05 is also sometimes called rambar. */
636 {"%rambar0", 0xc04}, {"%rambar1", 0xc05},
637
638 /* Should we be calling this psr like we do in case 'Y'? */
639 {"%mmusr",0x805},
640
641 {"%urp", 0x806}, {"%srp", 0x807}, {"%pcr", 0x808},
642
643 /* Fido added these. */
644 {"%cac", 0xffe}, {"%mbb", 0xfff}};
645
646 val = fetch_arg (buffer, place, 12, info);
647 for (regno = sizeof names / sizeof names[0] - 1; regno >= 0; regno--)
648 if (names[regno].value == val)
649 {
650 (*info->fprintf_func) (info->stream, "%s", names[regno].name);
651 break;
652 }
653 if (regno < 0)
654 (*info->fprintf_func) (info->stream, "%d", val);
655 }
656 break;
657
658 case 'Q':
659 val = fetch_arg (buffer, place, 3, info);
660 /* 0 means 8, except for the bkpt instruction... */
661 if (val == 0 && d[1] != 's')
662 val = 8;
663 (*info->fprintf_func) (info->stream, "#%d", val);
664 break;
665
666 case 'x':
667 val = fetch_arg (buffer, place, 3, info);
668 /* 0 means -1. */
669 if (val == 0)
670 val = -1;
671 (*info->fprintf_func) (info->stream, "#%d", val);
672 break;
673
674 case 'j':
675 val = fetch_arg (buffer, place, 3, info);
676 (*info->fprintf_func) (info->stream, "#%d", val+1);
677 break;
678
679 case 'K':
680 val = fetch_arg (buffer, place, 9, info);
681 (*info->fprintf_func) (info->stream, "#%d", val);
682 break;
683
684 case 'M':
685 if (place == 'h')
686 {
687 static char *const scalefactor_name[] = { "<<", ">>" };
688 val = fetch_arg (buffer, place, 1, info);
689 (*info->fprintf_func) (info->stream, scalefactor_name[val]);
690 }
691 else
692 {
693 val = fetch_arg (buffer, place, 8, info);
694 if (val & 0x80)
695 val = val - 0x100;
696 (*info->fprintf_func) (info->stream, "#%d", val);
697 }
698 break;
699
700 case 'T':
701 val = fetch_arg (buffer, place, 4, info);
702 (*info->fprintf_func) (info->stream, "#%d", val);
703 break;
704
705 case 'D':
706 (*info->fprintf_func) (info->stream, "%s",
707 reg_names[fetch_arg (buffer, place, 3, info)]);
708 break;
709
710 case 'A':
711 (*info->fprintf_func)
712 (info->stream, "%s",
713 reg_names[fetch_arg (buffer, place, 3, info) + 010]);
714 break;
715
716 case 'R':
717 (*info->fprintf_func)
718 (info->stream, "%s",
719 reg_names[fetch_arg (buffer, place, 4, info)]);
720 break;
721
722 case 'r':
723 regno = fetch_arg (buffer, place, 4, info);
724 if (regno > 7)
725 (*info->fprintf_func) (info->stream, "%s@", reg_names[regno]);
726 else
727 (*info->fprintf_func) (info->stream, "@(%s)", reg_names[regno]);
728 break;
729
730 case 'F':
731 (*info->fprintf_func)
732 (info->stream, "%%fp%d",
733 fetch_arg (buffer, place, 3, info));
734 break;
735
736 case 'O':
737 val = fetch_arg (buffer, place, 6, info);
738 if (val & 0x20)
739 (*info->fprintf_func) (info->stream, "%s", reg_names[val & 7]);
740 else
741 (*info->fprintf_func) (info->stream, "%d", val);
742 break;
743
744 case '+':
745 (*info->fprintf_func)
746 (info->stream, "%s@+",
747 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
748 break;
749
750 case '-':
751 (*info->fprintf_func)
752 (info->stream, "%s@-",
753 reg_names[fetch_arg (buffer, place, 3, info) + 8]);
754 break;
755
756 case 'k':
757 if (place == 'k')
758 (*info->fprintf_func)
759 (info->stream, "{%s}",
760 reg_names[fetch_arg (buffer, place, 3, info)]);
761 else if (place == 'C')
762 {
763 val = fetch_arg (buffer, place, 7, info);
764 if (val > 63) /* This is a signed constant. */
765 val -= 128;
766 (*info->fprintf_func) (info->stream, "{#%d}", val);
767 }
768 else
769 return -2;
770 break;
771
772 case '#':
773 case '^':
774 p1 = buffer + (*d == '#' ? 2 : 4);
775 if (place == 's')
776 val = fetch_arg (buffer, place, 4, info);
777 else if (place == 'C')
778 val = fetch_arg (buffer, place, 7, info);
779 else if (place == '8')
780 val = fetch_arg (buffer, place, 3, info);
781 else if (place == '3')
782 val = fetch_arg (buffer, place, 8, info);
783 else if (place == 'b')
784 val = NEXTBYTE (p1);
785 else if (place == 'w' || place == 'W')
786 val = NEXTWORD (p1);
787 else if (place == 'l')
788 val = NEXTLONG (p1);
789 else
790 return -2;
791 (*info->fprintf_func) (info->stream, "#%d", val);
792 break;
793
794 case 'B':
795 if (place == 'b')
796 disp = NEXTBYTE (p);
797 else if (place == 'B')
798 disp = COERCE_SIGNED_CHAR (buffer[1]);
799 else if (place == 'w' || place == 'W')
800 disp = NEXTWORD (p);
801 else if (place == 'l' || place == 'L' || place == 'C')
802 disp = NEXTLONG (p);
803 else if (place == 'g')
804 {
805 disp = NEXTBYTE (buffer);
806 if (disp == 0)
807 disp = NEXTWORD (p);
808 else if (disp == -1)
809 disp = NEXTLONG (p);
810 }
811 else if (place == 'c')
812 {
813 if (buffer[1] & 0x40) /* If bit six is one, long offset. */
814 disp = NEXTLONG (p);
815 else
816 disp = NEXTWORD (p);
817 }
818 else
819 return -2;
820
821 (*info->print_address_func) (addr + disp, info);
822 break;
823
824 case 'd':
825 val = NEXTWORD (p);
826 (*info->fprintf_func)
827 (info->stream, "%s@(%d)",
828 reg_names[fetch_arg (buffer, place, 3, info) + 8], val);
829 break;
830
831 case 's':
832 (*info->fprintf_func) (info->stream, "%s",
833 fpcr_names[fetch_arg (buffer, place, 3, info)]);
834 break;
835
836 case 'e':
837 val = fetch_arg(buffer, place, 2, info);
838 (*info->fprintf_func) (info->stream, "%%acc%d", val);
839 break;
840
841 case 'g':
842 val = fetch_arg(buffer, place, 1, info);
843 (*info->fprintf_func) (info->stream, "%%accext%s", val==0 ? "01" : "23");
844 break;
845
846 case 'i':
847 val = fetch_arg(buffer, place, 2, info);
848 if (val == 1)
849 (*info->fprintf_func) (info->stream, "<<");
850 else if (val == 3)
851 (*info->fprintf_func) (info->stream, ">>");
852 else
853 return -1;
854 break;
855
856 case 'I':
857 /* Get coprocessor ID... */
858 val = fetch_arg (buffer, 'd', 3, info);
859
860 if (val != 1) /* Unusual coprocessor ID? */
861 (*info->fprintf_func) (info->stream, "(cpid=%d) ", val);
862 break;
863
864 case '4':
865 case '*':
866 case '~':
867 case '%':
868 case ';':
869 case '@':
870 case '!':
871 case '$':
872 case '?':
873 case '/':
874 case '&':
875 case '|':
876 case '<':
877 case '>':
878 case 'm':
879 case 'n':
880 case 'o':
881 case 'p':
882 case 'q':
883 case 'v':
884 case 'b':
885 case 'w':
886 case 'y':
887 case 'z':
888 if (place == 'd')
889 {
890 val = fetch_arg (buffer, 'x', 6, info);
891 val = ((val & 7) << 3) + ((val >> 3) & 7);
892 }
893 else
894 val = fetch_arg (buffer, 's', 6, info);
895
896 /* If the <ea> is invalid for *d, then reject this match. */
897 if (!m68k_valid_ea (*d, val))
898 return -1;
899
900 /* Get register number assuming address register. */
901 regno = (val & 7) + 8;
902 regname = reg_names[regno];
903 switch (val >> 3)
904 {
905 case 0:
906 (*info->fprintf_func) (info->stream, "%s", reg_names[val]);
907 break;
908
909 case 1:
910 (*info->fprintf_func) (info->stream, "%s", regname);
911 break;
912
913 case 2:
914 (*info->fprintf_func) (info->stream, "%s@", regname);
915 break;
916
917 case 3:
918 (*info->fprintf_func) (info->stream, "%s@+", regname);
919 break;
920
921 case 4:
922 (*info->fprintf_func) (info->stream, "%s@-", regname);
923 break;
924
925 case 5:
926 val = NEXTWORD (p);
927 (*info->fprintf_func) (info->stream, "%s@(%d)", regname, val);
928 break;
929
930 case 6:
931 p = print_indexed (regno, p, addr, info);
932 break;
933
934 case 7:
935 switch (val & 7)
936 {
937 case 0:
938 val = NEXTWORD (p);
939 (*info->print_address_func) (val, info);
940 break;
941
942 case 1:
943 uval = NEXTULONG (p);
944 (*info->print_address_func) (uval, info);
945 break;
946
947 case 2:
948 val = NEXTWORD (p);
949 (*info->fprintf_func) (info->stream, "%%pc@(");
950 (*info->print_address_func) (addr + val, info);
951 (*info->fprintf_func) (info->stream, ")");
952 break;
953
954 case 3:
955 p = print_indexed (-1, p, addr, info);
956 break;
957
958 case 4:
959 flt_p = 1; /* Assume it's a float... */
960 switch (place)
961 {
962 case 'b':
963 val = NEXTBYTE (p);
964 flt_p = 0;
965 break;
966
967 case 'w':
968 val = NEXTWORD (p);
969 flt_p = 0;
970 break;
971
972 case 'l':
973 val = NEXTLONG (p);
974 flt_p = 0;
975 break;
976
977 case 'f':
978 NEXTSINGLE (flval, p);
979 break;
980
981 case 'F':
982 NEXTDOUBLE (flval, p);
983 break;
984
985 case 'x':
986 NEXTEXTEND (flval, p);
987 break;
988
989 case 'p':
990 flval = NEXTPACKED (p);
991 break;
992
993 default:
994 return -1;
995 }
996 if (flt_p) /* Print a float? */
997 (*info->fprintf_func) (info->stream, "#%g", flval);
998 else
999 (*info->fprintf_func) (info->stream, "#%d", val);
1000 break;
1001
1002 default:
1003 return -1;
1004 }
1005 }
1006
1007 /* If place is '/', then this is the case of the mask bit for
1008 mac/emac loads. Now that the arg has been printed, grab the
1009 mask bit and if set, add a '&' to the arg. */
1010 if (place == '/')
1011 {
1012 val = fetch_arg (buffer, place, 1, info);
1013 if (val)
1014 info->fprintf_func (info->stream, "&");
1015 }
1016 break;
1017
1018 case 'L':
1019 case 'l':
1020 if (place == 'w')
1021 {
1022 char doneany;
1023 p1 = buffer + 2;
1024 val = NEXTWORD (p1);
1025 /* Move the pointer ahead if this point is farther ahead
1026 than the last. */
1027 p = p1 > p ? p1 : p;
1028 if (val == 0)
1029 {
1030 (*info->fprintf_func) (info->stream, "#0");
1031 break;
1032 }
1033 if (*d == 'l')
1034 {
1035 int newval = 0;
1036
1037 for (regno = 0; regno < 16; ++regno)
1038 if (val & (0x8000 >> regno))
1039 newval |= 1 << regno;
1040 val = newval;
1041 }
1042 val &= 0xffff;
1043 doneany = 0;
1044 for (regno = 0; regno < 16; ++regno)
1045 if (val & (1 << regno))
1046 {
1047 int first_regno;
1048
1049 if (doneany)
1050 (*info->fprintf_func) (info->stream, "/");
1051 doneany = 1;
1052 (*info->fprintf_func) (info->stream, "%s", reg_names[regno]);
1053 first_regno = regno;
1054 while (val & (1 << (regno + 1)))
1055 ++regno;
1056 if (regno > first_regno)
1057 (*info->fprintf_func) (info->stream, "-%s",
1058 reg_names[regno]);
1059 }
1060 }
1061 else if (place == '3')
1062 {
1063 /* `fmovem' insn. */
1064 char doneany;
1065 val = fetch_arg (buffer, place, 8, info);
1066 if (val == 0)
1067 {
1068 (*info->fprintf_func) (info->stream, "#0");
1069 break;
1070 }
1071 if (*d == 'l')
1072 {
1073 int newval = 0;
1074
1075 for (regno = 0; regno < 8; ++regno)
1076 if (val & (0x80 >> regno))
1077 newval |= 1 << regno;
1078 val = newval;
1079 }
1080 val &= 0xff;
1081 doneany = 0;
1082 for (regno = 0; regno < 8; ++regno)
1083 if (val & (1 << regno))
1084 {
1085 int first_regno;
1086 if (doneany)
1087 (*info->fprintf_func) (info->stream, "/");
1088 doneany = 1;
1089 (*info->fprintf_func) (info->stream, "%%fp%d", regno);
1090 first_regno = regno;
1091 while (val & (1 << (regno + 1)))
1092 ++regno;
1093 if (regno > first_regno)
1094 (*info->fprintf_func) (info->stream, "-%%fp%d", regno);
1095 }
1096 }
1097 else if (place == '8')
1098 {
1099 /* fmoveml for FP status registers. */
1100 (*info->fprintf_func) (info->stream, "%s",
1101 fpcr_names[fetch_arg (buffer, place, 3,
1102 info)]);
1103 }
1104 else
1105 return -2;
1106 break;
1107
1108 case 'X':
1109 place = '8';
1110 case 'Y':
1111 case 'Z':
1112 case 'W':
1113 case '0':
1114 case '1':
1115 case '2':
1116 case '3':
1117 {
1118 int val = fetch_arg (buffer, place, 5, info);
1119 char *name = 0;
1120
1121 switch (val)
1122 {
1123 case 2: name = "%tt0"; break;
1124 case 3: name = "%tt1"; break;
1125 case 0x10: name = "%tc"; break;
1126 case 0x11: name = "%drp"; break;
1127 case 0x12: name = "%srp"; break;
1128 case 0x13: name = "%crp"; break;
1129 case 0x14: name = "%cal"; break;
1130 case 0x15: name = "%val"; break;
1131 case 0x16: name = "%scc"; break;
1132 case 0x17: name = "%ac"; break;
1133 case 0x18: name = "%psr"; break;
1134 case 0x19: name = "%pcsr"; break;
1135 case 0x1c:
1136 case 0x1d:
1137 {
1138 int break_reg = ((buffer[3] >> 2) & 7);
1139
1140 (*info->fprintf_func)
1141 (info->stream, val == 0x1c ? "%%bad%d" : "%%bac%d",
1142 break_reg);
1143 }
1144 break;
1145 default:
1146 (*info->fprintf_func) (info->stream, "<mmu register %d>", val);
1147 }
1148 if (name)
1149 (*info->fprintf_func) (info->stream, "%s", name);
1150 }
1151 break;
1152
1153 case 'f':
1154 {
1155 int fc = fetch_arg (buffer, place, 5, info);
1156
1157 if (fc == 1)
1158 (*info->fprintf_func) (info->stream, "%%dfc");
1159 else if (fc == 0)
1160 (*info->fprintf_func) (info->stream, "%%sfc");
1161 else
1162 /* xgettext:c-format */
1163 (*info->fprintf_func) (info->stream, _("<function code %d>"), fc);
1164 }
1165 break;
1166
1167 case 'V':
1168 (*info->fprintf_func) (info->stream, "%%val");
1169 break;
1170
1171 case 't':
1172 {
1173 int level = fetch_arg (buffer, place, 3, info);
1174
1175 (*info->fprintf_func) (info->stream, "%d", level);
1176 }
1177 break;
1178
1179 case 'u':
1180 {
1181 short is_upper = 0;
1182 int reg = fetch_arg (buffer, place, 5, info);
1183
1184 if (reg & 0x10)
1185 {
1186 is_upper = 1;
1187 reg &= 0xf;
1188 }
1189 (*info->fprintf_func) (info->stream, "%s%s",
1190 reg_half_names[reg],
1191 is_upper ? "u" : "l");
1192 }
1193 break;
1194
1195 default:
1196 return -2;
1197 }
1198
1199 return p - p0;
1200 }
1201
1202 /* Try to match the current instruction to best and if so, return the
1203 number of bytes consumed from the instruction stream, else zero. */
1204
1205 static int
1206 match_insn_m68k (bfd_vma memaddr,
1207 disassemble_info * info,
1208 const struct m68k_opcode * best)
1209 {
1210 unsigned char *save_p;
1211 unsigned char *p;
1212 const char *d;
1213 const char *args = best->args;
1214
1215 struct private *priv = (struct private *) info->private_data;
1216 bfd_byte *buffer = priv->the_buffer;
1217 fprintf_ftype save_printer = info->fprintf_func;
1218 void (* save_print_address) (bfd_vma, struct disassemble_info *)
1219 = info->print_address_func;
1220
1221 if (*args == '.')
1222 args++;
1223
1224 /* Point at first word of argument data,
1225 and at descriptor for first argument. */
1226 p = buffer + 2;
1227
1228 /* Figure out how long the fixed-size portion of the instruction is.
1229 The only place this is stored in the opcode table is
1230 in the arguments--look for arguments which specify fields in the 2nd
1231 or 3rd words of the instruction. */
1232 for (d = args; *d; d += 2)
1233 {
1234 /* I don't think it is necessary to be checking d[0] here;
1235 I suspect all this could be moved to the case statement below. */
1236 if (d[0] == '#')
1237 {
1238 if (d[1] == 'l' && p - buffer < 6)
1239 p = buffer + 6;
1240 else if (p - buffer < 4 && d[1] != 'C' && d[1] != '8')
1241 p = buffer + 4;
1242 }
1243
1244 if ((d[0] == 'L' || d[0] == 'l') && d[1] == 'w' && p - buffer < 4)
1245 p = buffer + 4;
1246
1247 switch (d[1])
1248 {
1249 case '1':
1250 case '2':
1251 case '3':
1252 case '7':
1253 case '8':
1254 case '9':
1255 case 'i':
1256 if (p - buffer < 4)
1257 p = buffer + 4;
1258 break;
1259 case '4':
1260 case '5':
1261 case '6':
1262 if (p - buffer < 6)
1263 p = buffer + 6;
1264 break;
1265 default:
1266 break;
1267 }
1268 }
1269
1270 /* pflusha is an exceptions. It takes no arguments but is two words
1271 long. Recognize it by looking at the lower 16 bits of the mask. */
1272 if (p - buffer < 4 && (best->match & 0xFFFF) != 0)
1273 p = buffer + 4;
1274
1275 /* lpstop is another exception. It takes a one word argument but is
1276 three words long. */
1277 if (p - buffer < 6
1278 && (best->match & 0xffff) == 0xffff
1279 && args[0] == '#'
1280 && args[1] == 'w')
1281 {
1282 /* Copy the one word argument into the usual location for a one
1283 word argument, to simplify printing it. We can get away with
1284 this because we know exactly what the second word is, and we
1285 aren't going to print anything based on it. */
1286 p = buffer + 6;
1287 FETCH_DATA (info, p);
1288 buffer[2] = buffer[4];
1289 buffer[3] = buffer[5];
1290 }
1291
1292 FETCH_DATA (info, p);
1293
1294 save_p = p;
1295 info->print_address_func = dummy_print_address;
1296 info->fprintf_func = (fprintf_ftype) dummy_printer;
1297
1298 /* We scan the operands twice. The first time we don't print anything,
1299 but look for errors. */
1300 for (d = args; *d; d += 2)
1301 {
1302 int eaten = print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
1303
1304 if (eaten >= 0)
1305 p += eaten;
1306 else if (eaten == -1)
1307 {
1308 info->fprintf_func = save_printer;
1309 info->print_address_func = save_print_address;
1310 return 0;
1311 }
1312 else
1313 {
1314 /* We must restore the print functions before trying to print the
1315 error message. */
1316 info->fprintf_func = save_printer;
1317 info->print_address_func = save_print_address;
1318 info->fprintf_func (info->stream,
1319 /* xgettext:c-format */
1320 _("<internal error in opcode table: %s %s>\n"),
1321 best->name, best->args);
1322 return 2;
1323 }
1324 }
1325
1326 p = save_p;
1327 info->fprintf_func = save_printer;
1328 info->print_address_func = save_print_address;
1329
1330 d = args;
1331
1332 info->fprintf_func (info->stream, "%s", best->name);
1333
1334 if (*d)
1335 info->fprintf_func (info->stream, " ");
1336
1337 while (*d)
1338 {
1339 p += print_insn_arg (d, buffer, p, memaddr + (p - buffer), info);
1340 d += 2;
1341
1342 if (*d && *(d - 2) != 'I' && *d != 'k')
1343 info->fprintf_func (info->stream, ",");
1344 }
1345
1346 return p - buffer;
1347 }
1348
1349 /* Try to interpret the instruction at address MEMADDR as one that
1350 can execute on a processor with the features given by ARCH_MASK.
1351 If successful, print the instruction to INFO->STREAM and return
1352 its length in bytes. Return 0 otherwise. */
1353
1354 static int
1355 m68k_scan_mask (bfd_vma memaddr, disassemble_info *info,
1356 unsigned int arch_mask)
1357 {
1358 int i;
1359 const char *d;
1360 static const struct m68k_opcode **opcodes[16];
1361 static int numopcodes[16];
1362 int val;
1363 int major_opcode;
1364
1365 struct private *priv = (struct private *) info->private_data;
1366 bfd_byte *buffer = priv->the_buffer;
1367
1368 if (!opcodes[0])
1369 {
1370 /* Speed up the matching by sorting the opcode
1371 table on the upper four bits of the opcode. */
1372 const struct m68k_opcode **opc_pointer[16];
1373
1374 /* First count how many opcodes are in each of the sixteen buckets. */
1375 for (i = 0; i < m68k_numopcodes; i++)
1376 numopcodes[(m68k_opcodes[i].opcode >> 28) & 15]++;
1377
1378 /* Then create a sorted table of pointers
1379 that point into the unsorted table. */
1380 opc_pointer[0] = xmalloc (sizeof (struct m68k_opcode *)
1381 * m68k_numopcodes);
1382 opcodes[0] = opc_pointer[0];
1383
1384 for (i = 1; i < 16; i++)
1385 {
1386 opc_pointer[i] = opc_pointer[i - 1] + numopcodes[i - 1];
1387 opcodes[i] = opc_pointer[i];
1388 }
1389
1390 for (i = 0; i < m68k_numopcodes; i++)
1391 *opc_pointer[(m68k_opcodes[i].opcode >> 28) & 15]++ = &m68k_opcodes[i];
1392 }
1393
1394 FETCH_DATA (info, buffer + 2);
1395 major_opcode = (buffer[0] >> 4) & 15;
1396
1397 for (i = 0; i < numopcodes[major_opcode]; i++)
1398 {
1399 const struct m68k_opcode *opc = opcodes[major_opcode][i];
1400 unsigned long opcode = opc->opcode;
1401 unsigned long match = opc->match;
1402 const char *args = opc->args;
1403
1404 if (*args == '.')
1405 args++;
1406
1407 if (((0xff & buffer[0] & (match >> 24)) == (0xff & (opcode >> 24)))
1408 && ((0xff & buffer[1] & (match >> 16)) == (0xff & (opcode >> 16)))
1409 /* Only fetch the next two bytes if we need to. */
1410 && (((0xffff & match) == 0)
1411 ||
1412 (FETCH_DATA (info, buffer + 4)
1413 && ((0xff & buffer[2] & (match >> 8)) == (0xff & (opcode >> 8)))
1414 && ((0xff & buffer[3] & match) == (0xff & opcode)))
1415 )
1416 && (opc->arch & arch_mask) != 0)
1417 {
1418 /* Don't use for printout the variants of divul and divsl
1419 that have the same register number in two places.
1420 The more general variants will match instead. */
1421 for (d = args; *d; d += 2)
1422 if (d[1] == 'D')
1423 break;
1424
1425 /* Don't use for printout the variants of most floating
1426 point coprocessor instructions which use the same
1427 register number in two places, as above. */
1428 if (*d == '\0')
1429 for (d = args; *d; d += 2)
1430 if (d[1] == 't')
1431 break;
1432
1433 /* Don't match fmovel with more than one register;
1434 wait for fmoveml. */
1435 if (*d == '\0')
1436 {
1437 for (d = args; *d; d += 2)
1438 {
1439 if (d[0] == 's' && d[1] == '8')
1440 {
1441 val = fetch_arg (buffer, d[1], 3, info);
1442 if ((val & (val - 1)) != 0)
1443 break;
1444 }
1445 }
1446 }
1447
1448 /* Don't match FPU insns with non-default coprocessor ID. */
1449 if (*d == '\0')
1450 {
1451 for (d = args; *d; d += 2)
1452 {
1453 if (d[0] == 'I')
1454 {
1455 val = fetch_arg (buffer, 'd', 3, info);
1456 if (val != 1)
1457 break;
1458 }
1459 }
1460 }
1461
1462 if (*d == '\0')
1463 if ((val = match_insn_m68k (memaddr, info, opc)))
1464 return val;
1465 }
1466 }
1467 return 0;
1468 }
1469
1470 /* Print the m68k instruction at address MEMADDR in debugged memory,
1471 on INFO->STREAM. Returns length of the instruction, in bytes. */
1472
1473 int
1474 print_insn_m68k (bfd_vma memaddr, disassemble_info *info)
1475 {
1476 unsigned int arch_mask;
1477 struct private priv;
1478 int val;
1479
1480 bfd_byte *buffer = priv.the_buffer;
1481
1482 /* Save these printing functions in case we need to restore them
1483 later. */
1484 fprintf_ftype save_printer = info->fprintf_func;
1485 void (* save_print_address) (bfd_vma, struct disassemble_info *)
1486 = info->print_address_func;
1487
1488 info->private_data = (PTR) &priv;
1489 /* Tell objdump to use two bytes per chunk
1490 and six bytes per line for displaying raw data. */
1491 info->bytes_per_chunk = 2;
1492 info->bytes_per_line = 6;
1493 info->display_endian = BFD_ENDIAN_BIG;
1494 priv.max_fetched = priv.the_buffer;
1495 priv.insn_start = memaddr;
1496
1497 if (setjmp (priv.bailout) != 0)
1498 {
1499 /* longjmp may be called while these printing functions are
1500 temporarily replaced with dummy functions. Restore them
1501 before we leave.
1502
1503 Admittedly, this save-and-restore operation is somewhat ugly
1504 in that we are exposing the fact that match_insn_m68k
1505 temporarily replaces insn->fprintf_func and
1506 insn->print_address_func. Perhaps, a real fix is to report a
1507 FETCH_DATA failure with a return value of some sort, without
1508 using setjmp/longjmp. A better fix may be to teach the m68k
1509 disassembler do its job without temporarily replacing
1510 insn->fprintf_func and insn->print_address_func, but that's a
1511 task for another day. */
1512 info->fprintf_func = save_printer;
1513 info->print_address_func = save_print_address;
1514
1515 /* Error return. */
1516 return -1;
1517 }
1518
1519 arch_mask = bfd_m68k_mach_to_features (info->mach);
1520 if (!arch_mask)
1521 {
1522 /* First try printing an m680x0 instruction. Try printing a Coldfire
1523 one if that fails. */
1524 val = m68k_scan_mask (memaddr, info, m68k_mask);
1525 if (val)
1526 return val;
1527
1528 val = m68k_scan_mask (memaddr, info, mcf_mask);
1529 if (val)
1530 return val;
1531 }
1532 else
1533 {
1534 val = m68k_scan_mask (memaddr, info, arch_mask);
1535 if (val)
1536 return val;
1537 }
1538
1539 /* Handle undefined instructions. */
1540 info->fprintf_func (info->stream, "0%o", (buffer[0] << 8) + buffer[1]);
1541 return 2;
1542 }
This page took 0.062461 seconds and 4 git commands to generate.