Home | History | Annotate | Download | only in opcodes
      1 /* Print Z80 and R800 instructions
      2    Copyright (C) 2005-2014 Free Software Foundation, Inc.
      3    Contributed by Arnold Metselaar <arnold_m (at) operamail.com>
      4 
      5    This file is part of the GNU opcodes library.
      6 
      7    This library is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3, or (at your option)
     10    any later version.
     11 
     12    It is distributed in the hope that it will be useful, but WITHOUT
     13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15    License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program; if not, write to the Free Software
     19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20    MA 02110-1301, USA.  */
     21 
     22 #include "sysdep.h"
     23 #include "dis-asm.h"
     24 #include <stdio.h>
     25 
     26 struct buffer
     27 {
     28   bfd_vma base;
     29   int n_fetch;
     30   int n_used;
     31   signed char data[4];
     32 } ;
     33 
     34 typedef int (*func)(struct buffer *, disassemble_info *, char *);
     35 
     36 struct tab_elt
     37 {
     38   unsigned char val;
     39   unsigned char mask;
     40   func          fp;
     41   char *        text;
     42 } ;
     43 
     44 #define TXTSIZ 24
     45 /* Names of 16-bit registers.  */
     46 static char * rr_str[] = { "bc", "de", "hl", "sp" };
     47 /* Names of 8-bit registers.  */
     48 static char * r_str[]  = { "b", "c", "d", "e", "h", "l", "(hl)", "a" };
     49 /* Texts for condition codes.  */
     50 static char * cc_str[] = { "nz", "z", "nc", "c", "po", "pe", "p", "m" };
     51 /* Instruction names for 8-bit arithmetic, operand "a" is often implicit */
     52 static char * arit_str[] =
     53 {
     54   "add a,", "adc a,", "sub ", "sbc a,", "and ", "xor ", "or ", "cp "
     55 } ;
     56 
     57 static int
     59 fetch_data (struct buffer *buf, disassemble_info * info, int n)
     60 {
     61   int r;
     62 
     63   if (buf->n_fetch + n > 4)
     64     abort ();
     65 
     66   r = info->read_memory_func (buf->base + buf->n_fetch,
     67 			      (unsigned char*) buf->data + buf->n_fetch,
     68 			      n, info);
     69   if (r == 0)
     70     buf->n_fetch += n;
     71   return !r;
     72 }
     73 
     74 static int
     75 prt (struct buffer *buf, disassemble_info * info, char *txt)
     76 {
     77   info->fprintf_func (info->stream, "%s", txt);
     78   buf->n_used = buf->n_fetch;
     79   return 1;
     80 }
     81 
     82 static int
     83 prt_e (struct buffer *buf, disassemble_info * info, char *txt)
     84 {
     85   char e;
     86   int target_addr;
     87 
     88   if (fetch_data (buf, info, 1))
     89     {
     90       e = buf->data[1];
     91       target_addr = (buf->base + 2 + e) & 0xffff;
     92       buf->n_used = buf->n_fetch;
     93       info->fprintf_func (info->stream, "%s0x%04x", txt, target_addr);
     94     }
     95   else
     96     buf->n_used = -1;
     97 
     98   return buf->n_used;
     99 }
    100 
    101 static int
    102 jr_cc (struct buffer *buf, disassemble_info * info, char *txt)
    103 {
    104   char mytxt[TXTSIZ];
    105 
    106   snprintf (mytxt, TXTSIZ, txt, cc_str[(buf->data[0] >> 3) & 3]);
    107   return prt_e (buf, info, mytxt);
    108 }
    109 
    110 static int
    111 prt_nn (struct buffer *buf, disassemble_info * info, char *txt)
    112 {
    113   int nn;
    114   unsigned char *p;
    115 
    116   p = (unsigned char*) buf->data + buf->n_fetch;
    117   if (fetch_data (buf, info, 2))
    118     {
    119       nn = p[0] + (p[1] << 8);
    120       info->fprintf_func (info->stream, txt, nn);
    121       buf->n_used = buf->n_fetch;
    122     }
    123   else
    124     buf->n_used = -1;
    125   return buf->n_used;
    126 }
    127 
    128 static int
    129 prt_rr_nn (struct buffer *buf, disassemble_info * info, char *txt)
    130 {
    131   char mytxt[TXTSIZ];
    132   int rr;
    133 
    134   rr = (buf->data[buf->n_fetch - 1] >> 4) & 3;
    135   snprintf (mytxt, TXTSIZ, txt, rr_str[rr]);
    136   return prt_nn (buf, info, mytxt);
    137 }
    138 
    139 static int
    140 prt_rr (struct buffer *buf, disassemble_info * info, char *txt)
    141 {
    142   info->fprintf_func (info->stream, "%s%s", txt,
    143 		      rr_str[(buf->data[buf->n_fetch - 1] >> 4) & 3]);
    144   buf->n_used = buf->n_fetch;
    145   return buf->n_used;
    146 }
    147 
    148 static int
    149 prt_n (struct buffer *buf, disassemble_info * info, char *txt)
    150 {
    151   int n;
    152   unsigned char *p;
    153 
    154   p = (unsigned char*) buf->data + buf->n_fetch;
    155 
    156   if (fetch_data (buf, info, 1))
    157     {
    158       n = p[0];
    159       info->fprintf_func (info->stream, txt, n);
    160       buf->n_used = buf->n_fetch;
    161     }
    162   else
    163     buf->n_used = -1;
    164 
    165   return buf->n_used;
    166 }
    167 
    168 static int
    169 ld_r_n (struct buffer *buf, disassemble_info * info, char *txt)
    170 {
    171   char mytxt[TXTSIZ];
    172 
    173   snprintf (mytxt, TXTSIZ, txt, r_str[(buf->data[0] >> 3) & 7]);
    174   return prt_n (buf, info, mytxt);
    175 }
    176 
    177 static int
    178 prt_r (struct buffer *buf, disassemble_info * info, char *txt)
    179 {
    180   info->fprintf_func (info->stream, txt,
    181 		      r_str[(buf->data[buf->n_fetch - 1] >> 3) & 7]);
    182   buf->n_used = buf->n_fetch;
    183   return buf->n_used;
    184 }
    185 
    186 static int
    187 ld_r_r (struct buffer *buf, disassemble_info * info, char *txt)
    188 {
    189   info->fprintf_func (info->stream, txt,
    190 		      r_str[(buf->data[buf->n_fetch - 1] >> 3) & 7],
    191 		      r_str[buf->data[buf->n_fetch - 1] & 7]);
    192   buf->n_used = buf->n_fetch;
    193   return buf->n_used;
    194 }
    195 
    196 static int
    197 arit_r (struct buffer *buf, disassemble_info * info, char *txt)
    198 {
    199   info->fprintf_func (info->stream, txt,
    200 		      arit_str[(buf->data[buf->n_fetch - 1] >> 3) & 7],
    201 		      r_str[buf->data[buf->n_fetch - 1] & 7]);
    202   buf->n_used = buf->n_fetch;
    203   return buf->n_used;
    204 }
    205 
    206 static int
    207 prt_cc (struct buffer *buf, disassemble_info * info, char *txt)
    208 {
    209   info->fprintf_func (info->stream, "%s%s", txt,
    210 		      cc_str[(buf->data[0] >> 3) & 7]);
    211   buf->n_used = buf->n_fetch;
    212   return buf->n_used;
    213 }
    214 
    215 static int
    216 pop_rr (struct buffer *buf, disassemble_info * info, char *txt)
    217 {
    218   static char *rr_stack[] = { "bc","de","hl","af"};
    219 
    220   info->fprintf_func (info->stream, "%s %s", txt,
    221 		      rr_stack[(buf->data[0] >> 4) & 3]);
    222   buf->n_used = buf->n_fetch;
    223   return buf->n_used;
    224 }
    225 
    226 
    227 static int
    228 jp_cc_nn (struct buffer *buf, disassemble_info * info, char *txt)
    229 {
    230   char mytxt[TXTSIZ];
    231 
    232   snprintf (mytxt,TXTSIZ,
    233 	    "%s%s,0x%%04x", txt, cc_str[(buf->data[0] >> 3) & 7]);
    234   return prt_nn (buf, info, mytxt);
    235 }
    236 
    237 static int
    238 arit_n (struct buffer *buf, disassemble_info * info, char *txt)
    239 {
    240   char mytxt[TXTSIZ];
    241 
    242   snprintf (mytxt,TXTSIZ, txt, arit_str[(buf->data[0] >> 3) & 7]);
    243   return prt_n (buf, info, mytxt);
    244 }
    245 
    246 static int
    247 rst (struct buffer *buf, disassemble_info * info, char *txt)
    248 {
    249   info->fprintf_func (info->stream, txt, buf->data[0] & 0x38);
    250   buf->n_used = buf->n_fetch;
    251   return buf->n_used;
    252 }
    253 
    254 
    255 static int
    257 cis (struct buffer *buf, disassemble_info * info, char *txt ATTRIBUTE_UNUSED)
    258 {
    259   static char * opar[] = { "ld", "cp", "in", "out" };
    260   char * op;
    261   char c;
    262 
    263   c = buf->data[1];
    264   op = ((0x13 & c) == 0x13) ? "ot" : (opar[c & 3]);
    265   info->fprintf_func (info->stream,
    266 		      "%s%c%s", op,
    267 		      (c & 0x08) ? 'd' : 'i',
    268 		      (c & 0x10) ? "r" : "");
    269   buf->n_used = 2;
    270   return buf->n_used;
    271 }
    272 
    273 static int
    274 dump (struct buffer *buf, disassemble_info * info, char *txt)
    275 {
    276   int i;
    277 
    278   info->fprintf_func (info->stream, "defb ");
    279   for (i = 0; txt[i]; ++i)
    280     info->fprintf_func (info->stream, i ? ", 0x%02x" : "0x%02x",
    281 			(unsigned char) buf->data[i]);
    282   buf->n_used = i;
    283   return buf->n_used;
    284 }
    285 
    286 /* Table to disassemble machine codes with prefix 0xED.  */
    288 struct tab_elt opc_ed[] =
    289 {
    290   { 0x70, 0xFF, prt, "in f,(c)" },
    291   { 0x70, 0xFF, dump, "xx" },
    292   { 0x40, 0xC7, prt_r, "in %s,(c)" },
    293   { 0x71, 0xFF, prt, "out (c),0" },
    294   { 0x70, 0xFF, dump, "xx" },
    295   { 0x41, 0xC7, prt_r, "out (c),%s" },
    296   { 0x42, 0xCF, prt_rr, "sbc hl," },
    297   { 0x43, 0xCF, prt_rr_nn, "ld (0x%%04x),%s" },
    298   { 0x44, 0xFF, prt, "neg" },
    299   { 0x45, 0xFF, prt, "retn" },
    300   { 0x46, 0xFF, prt, "im 0" },
    301   { 0x47, 0xFF, prt, "ld i,a" },
    302   { 0x4A, 0xCF, prt_rr, "adc hl," },
    303   { 0x4B, 0xCF, prt_rr_nn, "ld %s,(0x%%04x)" },
    304   { 0x4D, 0xFF, prt, "reti" },
    305   { 0x4F, 0xFF, prt, "ld r,a" },
    306   { 0x56, 0xFF, prt, "im 1" },
    307   { 0x57, 0xFF, prt, "ld a,i" },
    308   { 0x5E, 0xFF, prt, "im 2" },
    309   { 0x5F, 0xFF, prt, "ld a,r" },
    310   { 0x67, 0xFF, prt, "rrd" },
    311   { 0x6F, 0xFF, prt, "rld" },
    312   { 0xA0, 0xE4, cis, "" },
    313   { 0xC3, 0xFF, prt, "muluw hl,bc" },
    314   { 0xC5, 0xE7, prt_r, "mulub a,%s" },
    315   { 0xF3, 0xFF, prt, "muluw hl,sp" },
    316   { 0x00, 0x00, dump, "xx" }
    317 };
    318 
    319 static int
    320 pref_ed (struct buffer * buf, disassemble_info * info,
    321 	 char* txt ATTRIBUTE_UNUSED)
    322 {
    323   struct tab_elt *p;
    324 
    325   if (fetch_data(buf, info, 1))
    326     {
    327       for (p = opc_ed; p->val != (buf->data[1] & p->mask); ++p)
    328 	;
    329       p->fp (buf, info, p->text);
    330     }
    331   else
    332     buf->n_used = -1;
    333 
    334   return buf->n_used;
    335 }
    336 
    337 /* Instruction names for the instructions addressing single bits.  */
    339 static char *cb1_str[] = { "", "bit", "res", "set"};
    340 /* Instruction names for shifts and rotates.  */
    341 static char *cb2_str[] =
    342 {
    343   "rlc", "rrc", "rl", "rr", "sla", "sra", "sli", "srl"
    344 };
    345 
    346 static int
    347 pref_cb (struct buffer * buf, disassemble_info * info,
    348 	 char* txt ATTRIBUTE_UNUSED)
    349 {
    350   if (fetch_data (buf, info, 1))
    351     {
    352       buf->n_used = 2;
    353       if ((buf->data[1] & 0xc0) == 0)
    354 	info->fprintf_func (info->stream, "%s %s",
    355 			    cb2_str[(buf->data[1] >> 3) & 7],
    356 			    r_str[buf->data[1] & 7]);
    357       else
    358 	info->fprintf_func (info->stream, "%s %d,%s",
    359 			    cb1_str[(buf->data[1] >> 6) & 3],
    360 			    (buf->data[1] >> 3) & 7,
    361 			    r_str[buf->data[1] & 7]);
    362     }
    363   else
    364     buf->n_used = -1;
    365 
    366   return buf->n_used;
    367 }
    368 
    369 static int
    371 addvv (struct buffer * buf, disassemble_info * info, char* txt)
    372 {
    373   info->fprintf_func (info->stream, "add %s,%s", txt, txt);
    374 
    375   return buf->n_used = buf->n_fetch;
    376 }
    377 
    378 static int
    379 ld_v_v (struct buffer * buf, disassemble_info * info, char* txt)
    380 {
    381   char mytxt[TXTSIZ];
    382 
    383   snprintf (mytxt, TXTSIZ, "ld %s%%s,%s%%s", txt, txt);
    384   return ld_r_r (buf, info, mytxt);
    385 }
    386 
    387 static int
    388 prt_d (struct buffer *buf, disassemble_info * info, char *txt)
    389 {
    390   int d;
    391   signed char *p;
    392 
    393   p = buf->data + buf->n_fetch;
    394 
    395   if (fetch_data (buf, info, 1))
    396     {
    397       d = p[0];
    398       info->fprintf_func (info->stream, txt, d);
    399       buf->n_used = buf->n_fetch;
    400     }
    401   else
    402     buf->n_used = -1;
    403 
    404   return buf->n_used;
    405 }
    406 
    407 static int
    408 prt_d_n (struct buffer *buf, disassemble_info * info, char *txt)
    409 {
    410   char mytxt[TXTSIZ];
    411   int d;
    412   signed char *p;
    413 
    414   p = buf->data + buf->n_fetch;
    415 
    416   if (fetch_data (buf, info, 1))
    417     {
    418       d = p[0];
    419       snprintf (mytxt, TXTSIZ, txt, d);
    420       return prt_n (buf, info, mytxt);
    421     }
    422   else
    423     buf->n_used = -1;
    424 
    425   return buf->n_used;
    426 }
    427 
    428 static int
    429 arit_d (struct buffer *buf, disassemble_info * info, char *txt)
    430 {
    431   char mytxt[TXTSIZ];
    432   signed char c;
    433 
    434   c = buf->data[buf->n_fetch - 1];
    435   snprintf (mytxt, TXTSIZ, txt, arit_str[(c >> 3) & 7]);
    436   return prt_d (buf, info, mytxt);
    437 }
    438 
    439 static int
    440 ld_r_d (struct buffer *buf, disassemble_info * info, char *txt)
    441 {
    442   char mytxt[TXTSIZ];
    443   signed char c;
    444 
    445   c = buf->data[buf->n_fetch - 1];
    446   snprintf (mytxt, TXTSIZ, txt, r_str[(c >> 3) & 7]);
    447   return prt_d (buf, info, mytxt);
    448 }
    449 
    450 static int
    451 ld_d_r(struct buffer *buf, disassemble_info * info, char *txt)
    452 {
    453   char mytxt[TXTSIZ];
    454   signed char c;
    455 
    456   c = buf->data[buf->n_fetch - 1];
    457   snprintf (mytxt, TXTSIZ, txt, r_str[c & 7]);
    458   return prt_d (buf, info, mytxt);
    459 }
    460 
    461 static int
    462 pref_xd_cb (struct buffer * buf, disassemble_info * info, char* txt)
    463 {
    464   if (fetch_data (buf, info, 2))
    465     {
    466       int d;
    467       char arg[TXTSIZ];
    468       signed char *p;
    469 
    470       buf->n_used = 4;
    471       p = buf->data;
    472       d = p[2];
    473 
    474       if (((p[3] & 0xC0) == 0x40) || ((p[3] & 7) == 0x06))
    475 	snprintf (arg, TXTSIZ, "(%s%+d)", txt, d);
    476       else
    477 	snprintf (arg, TXTSIZ, "(%s%+d),%s", txt, d, r_str[p[3] & 7]);
    478 
    479       if ((p[3] & 0xc0) == 0)
    480 	info->fprintf_func (info->stream, "%s %s",
    481 			    cb2_str[(buf->data[3] >> 3) & 7],
    482 			    arg);
    483       else
    484 	info->fprintf_func (info->stream, "%s %d,%s",
    485 			    cb1_str[(buf->data[3] >> 6) & 3],
    486 			    (buf->data[3] >> 3) & 7,
    487 			    arg);
    488     }
    489   else
    490     buf->n_used = -1;
    491 
    492   return buf->n_used;
    493 }
    494 
    495 /* Table to disassemble machine codes with prefix 0xDD or 0xFD.  */
    497 static struct tab_elt opc_ind[] =
    498 {
    499   { 0x24, 0xF7, prt_r, "inc %s%%s" },
    500   { 0x25, 0xF7, prt_r, "dec %s%%s" },
    501   { 0x26, 0xF7, ld_r_n, "ld %s%%s,0x%%%%02x" },
    502   { 0x21, 0xFF, prt_nn, "ld %s,0x%%04x" },
    503   { 0x22, 0xFF, prt_nn, "ld (0x%%04x),%s" },
    504   { 0x2A, 0xFF, prt_nn, "ld %s,(0x%%04x)" },
    505   { 0x23, 0xFF, prt, "inc %s" },
    506   { 0x2B, 0xFF, prt, "dec %s" },
    507   { 0x29, 0xFF, addvv, "%s" },
    508   { 0x09, 0xCF, prt_rr, "add %s," },
    509   { 0x34, 0xFF, prt_d, "inc (%s%%+d)" },
    510   { 0x35, 0xFF, prt_d, "dec (%s%%+d)" },
    511   { 0x36, 0xFF, prt_d_n, "ld (%s%%+d),0x%%%%02x" },
    512 
    513   { 0x76, 0xFF, dump, "h" },
    514   { 0x46, 0xC7, ld_r_d, "ld %%s,(%s%%%%+d)" },
    515   { 0x70, 0xF8, ld_d_r, "ld (%s%%%%+d),%%s" },
    516   { 0x64, 0xF6, ld_v_v, "%s" },
    517   { 0x60, 0xF0, ld_r_r, "ld %s%%s,%%s" },
    518   { 0x44, 0xC6, ld_r_r, "ld %%s,%s%%s" },
    519 
    520   { 0x86, 0xC7, arit_d, "%%s(%s%%%%+d)" },
    521   { 0x84, 0xC6, arit_r, "%%s%s%%s" },
    522 
    523   { 0xE1, 0xFF, prt, "pop %s" },
    524   { 0xE5, 0xFF, prt, "push %s" },
    525   { 0xCB, 0xFF, pref_xd_cb, "%s" },
    526   { 0xE3, 0xFF, prt, "ex (sp),%s" },
    527   { 0xE9, 0xFF, prt, "jp (%s)" },
    528   { 0xF9, 0xFF, prt, "ld sp,%s" },
    529   { 0x00, 0x00, dump, "?" },
    530 } ;
    531 
    532 static int
    533 pref_ind (struct buffer * buf, disassemble_info * info, char* txt)
    534 {
    535   if (fetch_data (buf, info, 1))
    536     {
    537       char mytxt[TXTSIZ];
    538       struct tab_elt *p;
    539 
    540       for (p = opc_ind; p->val != (buf->data[1] & p->mask); ++p)
    541 	;
    542       snprintf (mytxt, TXTSIZ, p->text, txt);
    543       p->fp (buf, info, mytxt);
    544     }
    545   else
    546     buf->n_used = -1;
    547 
    548   return buf->n_used;
    549 }
    550 
    551 /* Table to disassemble machine codes without prefix.  */
    552 static struct tab_elt opc_main[] =
    553 {
    554   { 0x00, 0xFF, prt, "nop" },
    555   { 0x01, 0xCF, prt_rr_nn, "ld %s,0x%%04x" },
    556   { 0x02, 0xFF, prt, "ld (bc),a" },
    557   { 0x03, 0xCF, prt_rr, "inc " },
    558   { 0x04, 0xC7, prt_r, "inc %s" },
    559   { 0x05, 0xC7, prt_r, "dec %s" },
    560   { 0x06, 0xC7, ld_r_n, "ld %s,0x%%02x" },
    561   { 0x07, 0xFF, prt, "rlca" },
    562   { 0x08, 0xFF, prt, "ex af,af'" },
    563   { 0x09, 0xCF, prt_rr, "add hl," },
    564   { 0x0A, 0xFF, prt, "ld a,(bc)" },
    565   { 0x0B, 0xCF, prt_rr, "dec " },
    566   { 0x0F, 0xFF, prt, "rrca" },
    567   { 0x10, 0xFF, prt_e, "djnz " },
    568   { 0x12, 0xFF, prt, "ld (de),a" },
    569   { 0x17, 0xFF, prt, "rla" },
    570   { 0x18, 0xFF, prt_e, "jr "},
    571   { 0x1A, 0xFF, prt, "ld a,(de)" },
    572   { 0x1F, 0xFF, prt, "rra" },
    573   { 0x20, 0xE7, jr_cc, "jr %s,"},
    574   { 0x22, 0xFF, prt_nn, "ld (0x%04x),hl" },
    575   { 0x27, 0xFF, prt, "daa"},
    576   { 0x2A, 0xFF, prt_nn, "ld hl,(0x%04x)" },
    577   { 0x2F, 0xFF, prt, "cpl" },
    578   { 0x32, 0xFF, prt_nn, "ld (0x%04x),a" },
    579   { 0x37, 0xFF, prt, "scf" },
    580   { 0x3A, 0xFF, prt_nn, "ld a,(0x%04x)" },
    581   { 0x3F, 0xFF, prt, "ccf" },
    582 
    583   { 0x76, 0xFF, prt, "halt" },
    584   { 0x40, 0xC0, ld_r_r, "ld %s,%s"},
    585 
    586   { 0x80, 0xC0, arit_r, "%s%s" },
    587 
    588   { 0xC0, 0xC7, prt_cc, "ret " },
    589   { 0xC1, 0xCF, pop_rr, "pop" },
    590   { 0xC2, 0xC7, jp_cc_nn, "jp " },
    591   { 0xC3, 0xFF, prt_nn, "jp 0x%04x" },
    592   { 0xC4, 0xC7, jp_cc_nn, "call " },
    593   { 0xC5, 0xCF, pop_rr, "push" },
    594   { 0xC6, 0xC7, arit_n, "%s0x%%02x" },
    595   { 0xC7, 0xC7, rst, "rst 0x%02x" },
    596   { 0xC9, 0xFF, prt, "ret" },
    597   { 0xCB, 0xFF, pref_cb, "" },
    598   { 0xCD, 0xFF, prt_nn, "call 0x%04x" },
    599   { 0xD3, 0xFF, prt_n, "out (0x%02x),a" },
    600   { 0xD9, 0xFF, prt, "exx" },
    601   { 0xDB, 0xFF, prt_n, "in a,(0x%02x)" },
    602   { 0xDD, 0xFF, pref_ind, "ix" },
    603   { 0xE3, 0xFF, prt, "ex (sp),hl" },
    604   { 0xE9, 0xFF, prt, "jp (hl)" },
    605   { 0xEB, 0xFF, prt, "ex de,hl" },
    606   { 0xED, 0xFF, pref_ed, ""},
    607   { 0xF3, 0xFF, prt, "di" },
    608   { 0xF9, 0xFF, prt, "ld sp,hl" },
    609   { 0xFB, 0xFF, prt, "ei" },
    610   { 0xFD, 0xFF, pref_ind, "iy" },
    611   { 0x00, 0x00, prt, "????" },
    612 } ;
    613 
    614 int
    615 print_insn_z80 (bfd_vma addr, disassemble_info * info)
    616 {
    617   struct buffer buf;
    618   struct tab_elt *p;
    619 
    620   buf.base = addr;
    621   buf.n_fetch = 0;
    622   buf.n_used = 0;
    623 
    624   if (! fetch_data (& buf, info, 1))
    625     return -1;
    626 
    627   for (p = opc_main; p->val != (buf.data[0] & p->mask); ++p)
    628     ;
    629   p->fp (& buf, info, p->text);
    630 
    631   return buf.n_used;
    632 }
    633