xref: /netbsd-src/external/gpl3/binutils/dist/opcodes/tic4x-dis.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /* Print instructions for the Texas TMS320C[34]X, for GDB and GNU Binutils.
2 
3    Copyright 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
4 
5    Contributed by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz)
6 
7    This file is part of the GNU opcodes library.
8 
9    This library is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3, or (at your option)
12    any later version.
13 
14    It is distributed in the hope that it will be useful, but WITHOUT
15    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17    License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22    MA 02110-1301, USA.  */
23 
24 #include <math.h>
25 #include "libiberty.h"
26 #include "dis-asm.h"
27 #include "opcode/tic4x.h"
28 
29 #define TIC4X_DEBUG 0
30 
31 #define TIC4X_HASH_SIZE   11   /* 11 (bits) and above should give unique entries.  */
32 #define TIC4X_SPESOP_SIZE 8    /* Max 8. ops for special instructions.  */
33 
34 typedef enum
35 {
36   IMMED_SINT,
37   IMMED_SUINT,
38   IMMED_SFLOAT,
39   IMMED_INT,
40   IMMED_UINT,
41   IMMED_FLOAT
42 }
43 immed_t;
44 
45 typedef enum
46 {
47   INDIRECT_SHORT,
48   INDIRECT_LONG,
49   INDIRECT_TIC4X
50 }
51 indirect_t;
52 
53 static int tic4x_version = 0;
54 static int tic4x_dp = 0;
55 
56 static int
57 tic4x_pc_offset (unsigned int op)
58 {
59   /* Determine the PC offset for a C[34]x instruction.
60      This could be simplified using some boolean algebra
61      but at the expense of readability.  */
62   switch (op >> 24)
63     {
64     case 0x60:	/* br */
65     case 0x62:	/* call  (C4x) */
66     case 0x64:	/* rptb  (C4x) */
67       return 1;
68     case 0x61: 	/* brd */
69     case 0x63: 	/* laj */
70     case 0x65:	/* rptbd (C4x) */
71       return 3;
72     case 0x66: 	/* swi */
73     case 0x67:
74       return 0;
75     default:
76       break;
77     }
78 
79   switch ((op & 0xffe00000) >> 20)
80     {
81     case 0x6a0:	/* bB */
82     case 0x720: /* callB */
83     case 0x740: /* trapB */
84       return 1;
85 
86     case 0x6a2: /* bBd */
87     case 0x6a6: /* bBat */
88     case 0x6aa: /* bBaf */
89     case 0x722:	/* lajB */
90     case 0x748: /* latB */
91     case 0x798: /* rptbd */
92       return 3;
93 
94     default:
95       break;
96     }
97 
98   switch ((op & 0xfe200000) >> 20)
99     {
100     case 0x6e0:	/* dbB */
101       return 1;
102 
103     case 0x6e2:	/* dbBd */
104       return 3;
105 
106     default:
107       break;
108     }
109 
110   return 0;
111 }
112 
113 static int
114 tic4x_print_char (struct disassemble_info * info, char ch)
115 {
116   if (info != NULL)
117     (*info->fprintf_func) (info->stream, "%c", ch);
118   return 1;
119 }
120 
121 static int
122 tic4x_print_str (struct disassemble_info *info, char *str)
123 {
124   if (info != NULL)
125     (*info->fprintf_func) (info->stream, "%s", str);
126   return 1;
127 }
128 
129 static int
130 tic4x_print_register (struct disassemble_info *info, unsigned long regno)
131 {
132   static tic4x_register_t ** registertable = NULL;
133   unsigned int i;
134 
135   if (registertable == NULL)
136     {
137       registertable = xmalloc (sizeof (tic4x_register_t *) * REG_TABLE_SIZE);
138       for (i = 0; i < tic3x_num_registers; i++)
139 	registertable[tic3x_registers[i].regno] = (tic4x_register_t *) (tic3x_registers + i);
140       if (IS_CPU_TIC4X (tic4x_version))
141 	{
142 	  /* Add C4x additional registers, overwriting
143 	     any C3x registers if necessary.  */
144 	  for (i = 0; i < tic4x_num_registers; i++)
145 	    registertable[tic4x_registers[i].regno] =
146 	      (tic4x_register_t *)(tic4x_registers + i);
147 	}
148     }
149   if ((int) regno > (IS_CPU_TIC4X (tic4x_version) ? TIC4X_REG_MAX : TIC3X_REG_MAX))
150     return 0;
151   if (info != NULL)
152     (*info->fprintf_func) (info->stream, "%s", registertable[regno]->name);
153   return 1;
154 }
155 
156 static int
157 tic4x_print_addr (struct disassemble_info *info, unsigned long addr)
158 {
159   if (info != NULL)
160     (*info->print_address_func)(addr, info);
161   return 1;
162 }
163 
164 static int
165 tic4x_print_relative (struct disassemble_info *info,
166 		      unsigned long pc,
167 		      long offset,
168 		      unsigned long opcode)
169 {
170   return tic4x_print_addr (info, pc + offset + tic4x_pc_offset (opcode));
171 }
172 
173 static int
174 tic4x_print_direct (struct disassemble_info *info, unsigned long arg)
175 {
176   if (info != NULL)
177     {
178       (*info->fprintf_func) (info->stream, "@");
179       tic4x_print_addr (info, arg + (tic4x_dp << 16));
180     }
181   return 1;
182 }
183 #if 0
184 /* FIXME: make the floating point stuff not rely on host
185    floating point arithmetic.  */
186 
187 static void
188 tic4x_print_ftoa (unsigned int val, FILE *stream, fprintf_ftype pfunc)
189 {
190   int e;
191   int s;
192   int f;
193   double num = 0.0;
194 
195   e = EXTRS (val, 31, 24);	/* Exponent.  */
196   if (e != -128)
197     {
198       s = EXTRU (val, 23, 23);	/* Sign bit.  */
199       f = EXTRU (val, 22, 0);	/* Mantissa.  */
200       if (s)
201 	f += -2 * (1 << 23);
202       else
203 	f += (1 << 23);
204       num = f / (double)(1 << 23);
205       num = ldexp (num, e);
206     }
207   (*pfunc)(stream, "%.9g", num);
208 }
209 #endif
210 
211 static int
212 tic4x_print_immed (struct disassemble_info *info,
213 		   immed_t type,
214 		   unsigned long arg)
215 {
216   int s;
217   int f;
218   int e;
219   double num = 0.0;
220 
221   if (info == NULL)
222     return 1;
223   switch (type)
224     {
225     case IMMED_SINT:
226     case IMMED_INT:
227       (*info->fprintf_func) (info->stream, "%ld", (long) arg);
228       break;
229 
230     case IMMED_SUINT:
231     case IMMED_UINT:
232       (*info->fprintf_func) (info->stream, "%lu", arg);
233       break;
234 
235     case IMMED_SFLOAT:
236       e = EXTRS (arg, 15, 12);
237       if (e != -8)
238 	{
239 	  s = EXTRU (arg, 11, 11);
240 	  f = EXTRU (arg, 10, 0);
241 	  if (s)
242 	    f += -2 * (1 << 11);
243 	  else
244 	    f += (1 << 11);
245 	  num = f / (double)(1 << 11);
246 	  num = ldexp (num, e);
247 	}
248       (*info->fprintf_func) (info->stream, "%f", num);
249       break;
250     case IMMED_FLOAT:
251       e = EXTRS (arg, 31, 24);
252       if (e != -128)
253 	{
254 	  s = EXTRU (arg, 23, 23);
255 	  f = EXTRU (arg, 22, 0);
256 	  if (s)
257 	    f += -2 * (1 << 23);
258 	  else
259 	    f += (1 << 23);
260 	  num = f / (double)(1 << 23);
261 	  num = ldexp (num, e);
262 	}
263       (*info->fprintf_func) (info->stream, "%f", num);
264       break;
265     }
266   return 1;
267 }
268 
269 static int
270 tic4x_print_cond (struct disassemble_info *info, unsigned int cond)
271 {
272   static tic4x_cond_t **condtable = NULL;
273   unsigned int i;
274 
275   if (condtable == NULL)
276     {
277       condtable = xmalloc (sizeof (tic4x_cond_t *) * 32);
278       for (i = 0; i < tic4x_num_conds; i++)
279 	condtable[tic4x_conds[i].cond] = (tic4x_cond_t *)(tic4x_conds + i);
280     }
281   if (cond > 31 || condtable[cond] == NULL)
282     return 0;
283   if (info != NULL)
284     (*info->fprintf_func) (info->stream, "%s", condtable[cond]->name);
285   return 1;
286 }
287 
288 static int
289 tic4x_print_indirect (struct disassemble_info *info,
290 		      indirect_t type,
291 		      unsigned long arg)
292 {
293   unsigned int aregno;
294   unsigned int modn;
295   unsigned int disp;
296   char *a;
297 
298   aregno = 0;
299   modn = 0;
300   disp = 1;
301   switch(type)
302     {
303     case INDIRECT_TIC4X:		/* *+ARn(disp) */
304       disp = EXTRU (arg, 7, 3);
305       aregno = EXTRU (arg, 2, 0) + REG_AR0;
306       modn = 0;
307       break;
308     case INDIRECT_SHORT:
309       disp = 1;
310       aregno = EXTRU (arg, 2, 0) + REG_AR0;
311       modn = EXTRU (arg, 7, 3);
312       break;
313     case INDIRECT_LONG:
314       disp = EXTRU (arg, 7, 0);
315       aregno = EXTRU (arg, 10, 8) + REG_AR0;
316       modn = EXTRU (arg, 15, 11);
317       if (modn > 7 && disp != 0)
318 	return 0;
319       break;
320     default:
321         (*info->fprintf_func)(info->stream, "# internal error: Unknown indirect type %d", type);
322         return 0;
323     }
324   if (modn > TIC3X_MODN_MAX)
325     return 0;
326   a = tic4x_indirects[modn].name;
327   while (*a)
328     {
329       switch (*a)
330 	{
331 	case 'a':
332 	  tic4x_print_register (info, aregno);
333 	  break;
334 	case 'd':
335 	  tic4x_print_immed (info, IMMED_UINT, disp);
336 	  break;
337 	case 'y':
338 	  tic4x_print_str (info, "ir0");
339 	  break;
340 	case 'z':
341 	  tic4x_print_str (info, "ir1");
342 	  break;
343 	default:
344 	  tic4x_print_char (info, *a);
345 	  break;
346 	}
347       a++;
348     }
349   return 1;
350 }
351 
352 static int
353 tic4x_print_op (struct disassemble_info *info,
354 		unsigned long instruction,
355 		tic4x_inst_t *p,
356 		unsigned long pc)
357 {
358   int val;
359   char *s;
360   char *parallel = NULL;
361 
362   /* Print instruction name.  */
363   s = p->name;
364   while (*s && parallel == NULL)
365     {
366       switch (*s)
367 	{
368 	case 'B':
369 	  if (! tic4x_print_cond (info, EXTRU (instruction, 20, 16)))
370 	    return 0;
371 	  break;
372 	case 'C':
373 	  if (! tic4x_print_cond (info, EXTRU (instruction, 27, 23)))
374 	    return 0;
375 	  break;
376 	case '_':
377 	  parallel = s + 1;	/* Skip past `_' in name.  */
378 	  break;
379 	default:
380 	  tic4x_print_char (info, *s);
381 	  break;
382 	}
383       s++;
384     }
385 
386   /* Print arguments.  */
387   s = p->args;
388   if (*s)
389     tic4x_print_char (info, ' ');
390 
391   while (*s)
392     {
393       switch (*s)
394 	{
395 	case '*': /* Indirect 0--15.  */
396 	  if (! tic4x_print_indirect (info, INDIRECT_LONG,
397 				      EXTRU (instruction, 15, 0)))
398 	    return 0;
399 	  break;
400 
401 	case '#': /* Only used for ldp, ldpk.  */
402 	  tic4x_print_immed (info, IMMED_UINT, EXTRU (instruction, 15, 0));
403 	  break;
404 
405 	case '@': /* Direct 0--15.  */
406 	  tic4x_print_direct (info, EXTRU (instruction, 15, 0));
407 	  break;
408 
409 	case 'A': /* Address register 24--22.  */
410 	  if (! tic4x_print_register (info, EXTRU (instruction, 24, 22) +
411 				      REG_AR0))
412 	    return 0;
413 	  break;
414 
415 	case 'B': /* 24-bit unsigned int immediate br(d)/call/rptb
416 		     address 0--23.  */
417 	  if (IS_CPU_TIC4X (tic4x_version))
418 	    tic4x_print_relative (info, pc, EXTRS (instruction, 23, 0),
419 				  p->opcode);
420 	  else
421 	    tic4x_print_addr (info, EXTRU (instruction, 23, 0));
422 	  break;
423 
424 	case 'C': /* Indirect (short C4x) 0--7.  */
425 	  if (! IS_CPU_TIC4X (tic4x_version))
426 	    return 0;
427 	  if (! tic4x_print_indirect (info, INDIRECT_TIC4X,
428 				      EXTRU (instruction, 7, 0)))
429 	    return 0;
430 	  break;
431 
432 	case 'D':
433 	  /* Cockup if get here...  */
434 	  break;
435 
436 	case 'E': /* Register 0--7.  */
437         case 'e':
438 	  if (! tic4x_print_register (info, EXTRU (instruction, 7, 0)))
439 	    return 0;
440 	  break;
441 
442 	case 'F': /* 16-bit float immediate 0--15.  */
443 	  tic4x_print_immed (info, IMMED_SFLOAT,
444 			     EXTRU (instruction, 15, 0));
445 	  break;
446 
447         case 'i': /* Extended indirect 0--7.  */
448           if (EXTRU (instruction, 7, 5) == 7)
449             {
450               if (!tic4x_print_register (info, EXTRU (instruction, 4, 0)))
451                 return 0;
452               break;
453             }
454           /* Fallthrough */
455 
456 	case 'I': /* Indirect (short) 0--7.  */
457 	  if (! tic4x_print_indirect (info, INDIRECT_SHORT,
458 				      EXTRU (instruction, 7, 0)))
459 	    return 0;
460 	  break;
461 
462         case 'j': /* Extended indirect 8--15 */
463           if (EXTRU (instruction, 15, 13) == 7)
464             {
465               if (! tic4x_print_register (info, EXTRU (instruction, 12, 8)))
466                 return 0;
467               break;
468             }
469 
470 	case 'J': /* Indirect (short) 8--15.  */
471 	  if (! tic4x_print_indirect (info, INDIRECT_SHORT,
472 				      EXTRU (instruction, 15, 8)))
473 	    return 0;
474 	  break;
475 
476 	case 'G': /* Register 8--15.  */
477         case 'g':
478 	  if (! tic4x_print_register (info, EXTRU (instruction, 15, 8)))
479 	    return 0;
480 	  break;
481 
482 	case 'H': /* Register 16--18.  */
483 	  if (! tic4x_print_register (info, EXTRU (instruction, 18, 16)))
484 	    return 0;
485 	  break;
486 
487 	case 'K': /* Register 19--21.  */
488 	  if (! tic4x_print_register (info, EXTRU (instruction, 21, 19)))
489 	    return 0;
490 	  break;
491 
492 	case 'L': /* Register 22--24.  */
493 	  if (! tic4x_print_register (info, EXTRU (instruction, 24, 22)))
494 	    return 0;
495 	  break;
496 
497 	case 'M': /* Register 22--22.  */
498 	  tic4x_print_register (info, EXTRU (instruction, 22, 22) + REG_R2);
499 	  break;
500 
501 	case 'N': /* Register 23--23.  */
502 	  tic4x_print_register (info, EXTRU (instruction, 23, 23) + REG_R0);
503 	  break;
504 
505 	case 'O': /* Indirect (short C4x) 8--15.  */
506 	  if (! IS_CPU_TIC4X (tic4x_version))
507 	    return 0;
508 	  if (! tic4x_print_indirect (info, INDIRECT_TIC4X,
509 				      EXTRU (instruction, 15, 8)))
510 	    return 0;
511 	  break;
512 
513 	case 'P': /* Displacement 0--15 (used by Bcond and BcondD).  */
514 	  tic4x_print_relative (info, pc, EXTRS (instruction, 15, 0),
515 				p->opcode);
516 	  break;
517 
518 	case 'Q': /* Register 0--15.  */
519         case 'q':
520 	  if (! tic4x_print_register (info, EXTRU (instruction, 15, 0)))
521 	    return 0;
522 	  break;
523 
524 	case 'R': /* Register 16--20.  */
525         case 'r':
526 	  if (! tic4x_print_register (info, EXTRU (instruction, 20, 16)))
527 	    return 0;
528 	  break;
529 
530 	case 'S': /* 16-bit signed immediate 0--15.  */
531 	  tic4x_print_immed (info, IMMED_SINT,
532 			     EXTRS (instruction, 15, 0));
533 	  break;
534 
535 	case 'T': /* 5-bit signed immediate 16--20  (C4x stik).  */
536 	  if (! IS_CPU_TIC4X (tic4x_version))
537 	    return 0;
538 	  if (! tic4x_print_immed (info, IMMED_SUINT,
539 				   EXTRU (instruction, 20, 16)))
540 	    return 0;
541 	  break;
542 
543 	case 'U': /* 16-bit unsigned int immediate 0--15.  */
544 	  tic4x_print_immed (info, IMMED_SUINT, EXTRU (instruction, 15, 0));
545 	  break;
546 
547 	case 'V': /* 5/9-bit unsigned vector 0--4/8.  */
548 	  tic4x_print_immed (info, IMMED_SUINT,
549 			     IS_CPU_TIC4X (tic4x_version) ?
550 			     EXTRU (instruction, 8, 0) :
551 			     EXTRU (instruction, 4, 0) & ~0x20);
552 	  break;
553 
554 	case 'W': /* 8-bit signed immediate 0--7.  */
555 	  if (! IS_CPU_TIC4X (tic4x_version))
556 	    return 0;
557 	  tic4x_print_immed (info, IMMED_SINT, EXTRS (instruction, 7, 0));
558 	  break;
559 
560 	case 'X': /* Expansion register 4--0.  */
561 	  val = EXTRU (instruction, 4, 0) + REG_IVTP;
562 	  if (val < REG_IVTP || val > REG_TVTP)
563 	    return 0;
564 	  if (! tic4x_print_register (info, val))
565 	    return 0;
566 	  break;
567 
568 	case 'Y': /* Address register 16--20.  */
569 	  val = EXTRU (instruction, 20, 16);
570 	  if (val < REG_AR0 || val > REG_SP)
571 	    return 0;
572 	  if (! tic4x_print_register (info, val))
573 	    return 0;
574 	  break;
575 
576 	case 'Z': /* Expansion register 16--20.  */
577 	  val = EXTRU (instruction, 20, 16) + REG_IVTP;
578 	  if (val < REG_IVTP || val > REG_TVTP)
579 	    return 0;
580 	  if (! tic4x_print_register (info, val))
581 	    return 0;
582 	  break;
583 
584 	case '|':	/* Parallel instruction.  */
585 	  tic4x_print_str (info, " || ");
586 	  tic4x_print_str (info, parallel);
587 	  tic4x_print_char (info, ' ');
588 	  break;
589 
590 	case ';':
591 	  tic4x_print_char (info, ',');
592 	  break;
593 
594 	default:
595 	  tic4x_print_char (info, *s);
596 	  break;
597 	}
598       s++;
599     }
600   return 1;
601 }
602 
603 static void
604 tic4x_hash_opcode_special (tic4x_inst_t **optable_special,
605 			   const tic4x_inst_t *inst)
606 {
607   int i;
608 
609   for (i = 0;i < TIC4X_SPESOP_SIZE; i++)
610     if (optable_special[i] != NULL
611         && optable_special[i]->opcode == inst->opcode)
612       {
613         /* Collision (we have it already) - overwrite.  */
614         optable_special[i] = (tic4x_inst_t *) inst;
615         return;
616       }
617 
618   for (i = 0; i < TIC4X_SPESOP_SIZE; i++)
619     if (optable_special[i] == NULL)
620       {
621         /* Add the new opcode.  */
622         optable_special[i] = (tic4x_inst_t *) inst;
623         return;
624       }
625 
626   /* This should never occur. This happens if the number of special
627      instructions exceeds TIC4X_SPESOP_SIZE. Please increase the variable
628      of this variable */
629 #if TIC4X_DEBUG
630   printf ("optable_special[] is full, please increase TIC4X_SPESOP_SIZE!\n");
631 #endif
632 }
633 
634 static void
635 tic4x_hash_opcode (tic4x_inst_t **optable,
636 		   tic4x_inst_t **optable_special,
637 		   const tic4x_inst_t *inst,
638 		   const unsigned long tic4x_oplevel)
639 {
640   int j;
641   int opcode = inst->opcode >> (32 - TIC4X_HASH_SIZE);
642   int opmask = inst->opmask >> (32 - TIC4X_HASH_SIZE);
643 
644   /* Use a TIC4X_HASH_SIZE bit index as a hash index.  We should
645      have unique entries so there's no point having a linked list
646      for each entry?  */
647   for (j = opcode; j < opmask; j++)
648     if ((j & opmask) == opcode
649          && inst->oplevel & tic4x_oplevel)
650       {
651 #if TIC4X_DEBUG
652 	/* We should only have collisions for synonyms like
653 	   ldp for ldi.  */
654 	if (optable[j] != NULL)
655 	  printf ("Collision at index %d, %s and %s\n",
656 		  j, optable[j]->name, inst->name);
657 #endif
658         /* Catch those ops that collide with others already inside the
659            hash, and have a opmask greater than the one we use in the
660            hash. Store them in a special-list, that will handle full
661            32-bit INSN, not only the first 11-bit (or so). */
662         if (optable[j] != NULL
663 	    && inst->opmask & ~(opmask << (32 - TIC4X_HASH_SIZE)))
664           {
665             /* Add the instruction already on the list.  */
666             tic4x_hash_opcode_special (optable_special, optable[j]);
667 
668             /* Add the new instruction.  */
669             tic4x_hash_opcode_special (optable_special, inst);
670           }
671 
672         optable[j] = (tic4x_inst_t *) inst;
673       }
674 }
675 
676 /* Disassemble the instruction in 'instruction'.
677    'pc' should be the address of this instruction, it will
678    be used to print the target address if this is a relative jump or call
679    the disassembled instruction is written to 'info'.
680    The function returns the length of this instruction in words.  */
681 
682 static int
683 tic4x_disassemble (unsigned long pc,
684 		   unsigned long instruction,
685 		   struct disassemble_info *info)
686 {
687   static tic4x_inst_t **optable = NULL;
688   static tic4x_inst_t **optable_special = NULL;
689   tic4x_inst_t *p;
690   int i;
691   unsigned long tic4x_oplevel;
692 
693   tic4x_version = info->mach;
694 
695   tic4x_oplevel  = (IS_CPU_TIC4X (tic4x_version)) ? OP_C4X : 0;
696   tic4x_oplevel |= OP_C3X | OP_LPWR | OP_IDLE2 | OP_ENH;
697 
698   if (optable == NULL)
699     {
700       optable = xcalloc (sizeof (tic4x_inst_t *), (1 << TIC4X_HASH_SIZE));
701 
702       optable_special = xcalloc (sizeof (tic4x_inst_t *), TIC4X_SPESOP_SIZE);
703 
704       /* Install opcodes in reverse order so that preferred
705 	 forms overwrite synonyms.  */
706       for (i = tic4x_num_insts - 1; i >= 0; i--)
707         tic4x_hash_opcode (optable, optable_special, &tic4x_insts[i],
708 			   tic4x_oplevel);
709 
710       /* We now need to remove the insn that are special from the
711          "normal" optable, to make the disasm search this extra list
712          for them.  */
713       for (i = 0; i < TIC4X_SPESOP_SIZE; i++)
714         if (optable_special[i] != NULL)
715           optable[optable_special[i]->opcode >> (32 - TIC4X_HASH_SIZE)] = NULL;
716     }
717 
718   /* See if we can pick up any loading of the DP register...  */
719   if ((instruction >> 16) == 0x5070 || (instruction >> 16) == 0x1f70)
720     tic4x_dp = EXTRU (instruction, 15, 0);
721 
722   p = optable[instruction >> (32 - TIC4X_HASH_SIZE)];
723   if (p != NULL)
724     {
725       if (((instruction & p->opmask) == p->opcode)
726            && tic4x_print_op (NULL, instruction, p, pc))
727         tic4x_print_op (info, instruction, p, pc);
728       else
729         (*info->fprintf_func) (info->stream, "%08lx", instruction);
730     }
731   else
732     {
733       for (i = 0; i<TIC4X_SPESOP_SIZE; i++)
734         if (optable_special[i] != NULL
735             && optable_special[i]->opcode == instruction)
736           {
737             (*info->fprintf_func)(info->stream, "%s", optable_special[i]->name);
738             break;
739           }
740       if (i == TIC4X_SPESOP_SIZE)
741         (*info->fprintf_func) (info->stream, "%08lx", instruction);
742     }
743 
744   /* Return size of insn in words.  */
745   return 1;
746 }
747 
748 /* The entry point from objdump and gdb.  */
749 int
750 print_insn_tic4x (bfd_vma memaddr, struct disassemble_info *info)
751 {
752   int status;
753   unsigned long pc;
754   unsigned long op;
755   bfd_byte buffer[4];
756 
757   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
758   if (status != 0)
759     {
760       (*info->memory_error_func) (status, memaddr, info);
761       return -1;
762     }
763 
764   pc = memaddr;
765   op = bfd_getl32 (buffer);
766   info->bytes_per_line = 4;
767   info->bytes_per_chunk = 4;
768   info->octets_per_byte = 4;
769   info->display_endian = BFD_ENDIAN_LITTLE;
770   return tic4x_disassemble (pc, op, info) * 4;
771 }
772