xref: /netbsd-src/external/gpl3/binutils.old/dist/opcodes/m32r-dis.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
1ede78133Schristos /* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
275fd0b74Schristos /* Disassembler interface for targets using CGEN. -*- C -*-
375fd0b74Schristos    CGEN: Cpu tools GENerator
475fd0b74Schristos 
575fd0b74Schristos    THIS FILE IS MACHINE GENERATED WITH CGEN.
675fd0b74Schristos    - the resultant file is machine generated, cgen-dis.in isn't
775fd0b74Schristos 
8*e992f068Schristos    Copyright (C) 1996-2022 Free Software Foundation, Inc.
975fd0b74Schristos 
1075fd0b74Schristos    This file is part of libopcodes.
1175fd0b74Schristos 
1275fd0b74Schristos    This library is free software; you can redistribute it and/or modify
1375fd0b74Schristos    it under the terms of the GNU General Public License as published by
1475fd0b74Schristos    the Free Software Foundation; either version 3, or (at your option)
1575fd0b74Schristos    any later version.
1675fd0b74Schristos 
1775fd0b74Schristos    It is distributed in the hope that it will be useful, but WITHOUT
1875fd0b74Schristos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1975fd0b74Schristos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
2075fd0b74Schristos    License for more details.
2175fd0b74Schristos 
2275fd0b74Schristos    You should have received a copy of the GNU General Public License
2375fd0b74Schristos    along with this program; if not, write to the Free Software Foundation, Inc.,
2475fd0b74Schristos    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
2575fd0b74Schristos 
2675fd0b74Schristos /* ??? Eventually more and more of this stuff can go to cpu-independent files.
2775fd0b74Schristos    Keep that in mind.  */
2875fd0b74Schristos 
2975fd0b74Schristos #include "sysdep.h"
3075fd0b74Schristos #include <stdio.h>
3175fd0b74Schristos #include "ansidecl.h"
32ede78133Schristos #include "disassemble.h"
3375fd0b74Schristos #include "bfd.h"
3475fd0b74Schristos #include "symcat.h"
3575fd0b74Schristos #include "libiberty.h"
3675fd0b74Schristos #include "m32r-desc.h"
3775fd0b74Schristos #include "m32r-opc.h"
3875fd0b74Schristos #include "opintl.h"
3975fd0b74Schristos 
4075fd0b74Schristos /* Default text to print if an instruction isn't recognized.  */
4175fd0b74Schristos #define UNKNOWN_INSN_MSG _("*unknown*")
4275fd0b74Schristos 
4375fd0b74Schristos static void print_normal
4475fd0b74Schristos   (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
4575fd0b74Schristos static void print_address
4675fd0b74Schristos   (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
4775fd0b74Schristos static void print_keyword
4875fd0b74Schristos   (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
4975fd0b74Schristos static void print_insn_normal
5075fd0b74Schristos   (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
5175fd0b74Schristos static int print_insn
5275fd0b74Schristos   (CGEN_CPU_DESC, bfd_vma,  disassemble_info *, bfd_byte *, unsigned);
5375fd0b74Schristos static int default_print_insn
5475fd0b74Schristos   (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
5575fd0b74Schristos static int read_insn
5675fd0b74Schristos   (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
5775fd0b74Schristos    unsigned long *);
5875fd0b74Schristos 
5975fd0b74Schristos /* -- disassembler routines inserted here.  */
6075fd0b74Schristos 
6175fd0b74Schristos /* -- dis.c */
6275fd0b74Schristos 
6375fd0b74Schristos /* Print signed operands with '#' prefixes.  */
6475fd0b74Schristos 
6575fd0b74Schristos static void
print_signed_with_hash_prefix(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)6675fd0b74Schristos print_signed_with_hash_prefix (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
6775fd0b74Schristos 			       void * dis_info,
6875fd0b74Schristos 			       long value,
6975fd0b74Schristos 			       unsigned int attrs ATTRIBUTE_UNUSED,
7075fd0b74Schristos 			       bfd_vma pc ATTRIBUTE_UNUSED,
7175fd0b74Schristos 			       int length ATTRIBUTE_UNUSED)
7275fd0b74Schristos {
7375fd0b74Schristos   disassemble_info *info = (disassemble_info *) dis_info;
7475fd0b74Schristos 
7575fd0b74Schristos   (*info->fprintf_func) (info->stream, "#");
7675fd0b74Schristos   (*info->fprintf_func) (info->stream, "%ld", value);
7775fd0b74Schristos }
7875fd0b74Schristos 
7975fd0b74Schristos /* Print unsigned operands with '#' prefixes.  */
8075fd0b74Schristos 
8175fd0b74Schristos static void
print_unsigned_with_hash_prefix(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)8275fd0b74Schristos print_unsigned_with_hash_prefix (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
8375fd0b74Schristos 				 void * dis_info,
8475fd0b74Schristos 				 long value,
8575fd0b74Schristos 				 unsigned int attrs ATTRIBUTE_UNUSED,
8675fd0b74Schristos 				 bfd_vma pc ATTRIBUTE_UNUSED,
8775fd0b74Schristos 				 int length ATTRIBUTE_UNUSED)
8875fd0b74Schristos {
8975fd0b74Schristos   disassemble_info *info = (disassemble_info *) dis_info;
9075fd0b74Schristos 
9175fd0b74Schristos   (*info->fprintf_func) (info->stream, "#");
9275fd0b74Schristos   (*info->fprintf_func) (info->stream, "0x%lx", value);
9375fd0b74Schristos }
9475fd0b74Schristos 
9575fd0b74Schristos /* Handle '#' prefixes as operands.  */
9675fd0b74Schristos 
9775fd0b74Schristos static void
print_hash(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value ATTRIBUTE_UNUSED,unsigned int attrs ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)9875fd0b74Schristos print_hash (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
9975fd0b74Schristos 	    void * dis_info,
10075fd0b74Schristos 	    long value ATTRIBUTE_UNUSED,
10175fd0b74Schristos 	    unsigned int attrs ATTRIBUTE_UNUSED,
10275fd0b74Schristos 	    bfd_vma pc ATTRIBUTE_UNUSED,
10375fd0b74Schristos 	    int length ATTRIBUTE_UNUSED)
10475fd0b74Schristos {
10575fd0b74Schristos   disassemble_info *info = (disassemble_info *) dis_info;
10675fd0b74Schristos 
10775fd0b74Schristos   (*info->fprintf_func) (info->stream, "#");
10875fd0b74Schristos }
10975fd0b74Schristos 
11075fd0b74Schristos #undef  CGEN_PRINT_INSN
11175fd0b74Schristos #define CGEN_PRINT_INSN my_print_insn
11275fd0b74Schristos 
11375fd0b74Schristos static int
my_print_insn(CGEN_CPU_DESC cd,bfd_vma pc,disassemble_info * info)11475fd0b74Schristos my_print_insn (CGEN_CPU_DESC cd,
11575fd0b74Schristos 	       bfd_vma pc,
11675fd0b74Schristos 	       disassemble_info *info)
11775fd0b74Schristos {
11875fd0b74Schristos   bfd_byte buffer[CGEN_MAX_INSN_SIZE];
11975fd0b74Schristos   bfd_byte *buf = buffer;
12075fd0b74Schristos   int status;
12175fd0b74Schristos   int buflen = (pc & 3) == 0 ? 4 : 2;
12275fd0b74Schristos   int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
12375fd0b74Schristos   bfd_byte *x;
12475fd0b74Schristos 
12575fd0b74Schristos   /* Read the base part of the insn.  */
12675fd0b74Schristos 
12775fd0b74Schristos   status = (*info->read_memory_func) (pc - ((!big_p && (pc & 3) != 0) ? 2 : 0),
12875fd0b74Schristos 				      buf, buflen, info);
12975fd0b74Schristos   if (status != 0)
13075fd0b74Schristos     {
13175fd0b74Schristos       (*info->memory_error_func) (status, pc, info);
13275fd0b74Schristos       return -1;
13375fd0b74Schristos     }
13475fd0b74Schristos 
13575fd0b74Schristos   /* 32 bit insn?  */
13675fd0b74Schristos   x = (big_p ? &buf[0] : &buf[3]);
13775fd0b74Schristos   if ((pc & 3) == 0 && (*x & 0x80) != 0)
13875fd0b74Schristos     return print_insn (cd, pc, info, buf, buflen);
13975fd0b74Schristos 
14075fd0b74Schristos   /* Print the first insn.  */
14175fd0b74Schristos   if ((pc & 3) == 0)
14275fd0b74Schristos     {
14375fd0b74Schristos       buf += (big_p ? 0 : 2);
14475fd0b74Schristos       if (print_insn (cd, pc, info, buf, 2) == 0)
14575fd0b74Schristos 	(*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
14675fd0b74Schristos       buf += (big_p ? 2 : -2);
14775fd0b74Schristos     }
14875fd0b74Schristos 
14975fd0b74Schristos   x = (big_p ? &buf[0] : &buf[1]);
15075fd0b74Schristos   if (*x & 0x80)
15175fd0b74Schristos     {
15275fd0b74Schristos       /* Parallel.  */
15375fd0b74Schristos       (*info->fprintf_func) (info->stream, " || ");
15475fd0b74Schristos       *x &= 0x7f;
15575fd0b74Schristos     }
15675fd0b74Schristos   else
15775fd0b74Schristos     (*info->fprintf_func) (info->stream, " -> ");
15875fd0b74Schristos 
15975fd0b74Schristos   /* The "& 3" is to pass a consistent address.
16075fd0b74Schristos      Parallel insns arguably both begin on the word boundary.
16175fd0b74Schristos      Also, branch insns are calculated relative to the word boundary.  */
16275fd0b74Schristos   if (print_insn (cd, pc & ~ (bfd_vma) 3, info, buf, 2) == 0)
16375fd0b74Schristos     (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
16475fd0b74Schristos 
16575fd0b74Schristos   return (pc & 3) ? 2 : 4;
16675fd0b74Schristos }
16775fd0b74Schristos 
16875fd0b74Schristos /* -- */
16975fd0b74Schristos 
17075fd0b74Schristos void m32r_cgen_print_operand
171*e992f068Schristos   (CGEN_CPU_DESC, int, void *, CGEN_FIELDS *, void const *, bfd_vma, int);
17275fd0b74Schristos 
17375fd0b74Schristos /* Main entry point for printing operands.
17475fd0b74Schristos    XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
17575fd0b74Schristos    of dis-asm.h on cgen.h.
17675fd0b74Schristos 
17775fd0b74Schristos    This function is basically just a big switch statement.  Earlier versions
17875fd0b74Schristos    used tables to look up the function to use, but
17975fd0b74Schristos    - if the table contains both assembler and disassembler functions then
18075fd0b74Schristos      the disassembler contains much of the assembler and vice-versa,
18175fd0b74Schristos    - there's a lot of inlining possibilities as things grow,
18275fd0b74Schristos    - using a switch statement avoids the function call overhead.
18375fd0b74Schristos 
18475fd0b74Schristos    This function could be moved into `print_insn_normal', but keeping it
18575fd0b74Schristos    separate makes clear the interface between `print_insn_normal' and each of
18675fd0b74Schristos    the handlers.  */
18775fd0b74Schristos 
18875fd0b74Schristos void
m32r_cgen_print_operand(CGEN_CPU_DESC cd,int opindex,void * xinfo,CGEN_FIELDS * fields,void const * attrs ATTRIBUTE_UNUSED,bfd_vma pc,int length)18975fd0b74Schristos m32r_cgen_print_operand (CGEN_CPU_DESC cd,
19075fd0b74Schristos 			   int opindex,
19175fd0b74Schristos 			   void * xinfo,
19275fd0b74Schristos 			   CGEN_FIELDS *fields,
19375fd0b74Schristos 			   void const *attrs ATTRIBUTE_UNUSED,
19475fd0b74Schristos 			   bfd_vma pc,
19575fd0b74Schristos 			   int length)
19675fd0b74Schristos {
19775fd0b74Schristos   disassemble_info *info = (disassemble_info *) xinfo;
19875fd0b74Schristos 
19975fd0b74Schristos   switch (opindex)
20075fd0b74Schristos     {
20175fd0b74Schristos     case M32R_OPERAND_ACC :
20275fd0b74Schristos       print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_acc, 0);
20375fd0b74Schristos       break;
20475fd0b74Schristos     case M32R_OPERAND_ACCD :
20575fd0b74Schristos       print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accd, 0);
20675fd0b74Schristos       break;
20775fd0b74Schristos     case M32R_OPERAND_ACCS :
20875fd0b74Schristos       print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accs, 0);
20975fd0b74Schristos       break;
21075fd0b74Schristos     case M32R_OPERAND_DCR :
21175fd0b74Schristos       print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r1, 0);
21275fd0b74Schristos       break;
21375fd0b74Schristos     case M32R_OPERAND_DISP16 :
21475fd0b74Schristos       print_address (cd, info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
21575fd0b74Schristos       break;
21675fd0b74Schristos     case M32R_OPERAND_DISP24 :
21775fd0b74Schristos       print_address (cd, info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
21875fd0b74Schristos       break;
21975fd0b74Schristos     case M32R_OPERAND_DISP8 :
22075fd0b74Schristos       print_address (cd, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
22175fd0b74Schristos       break;
22275fd0b74Schristos     case M32R_OPERAND_DR :
22375fd0b74Schristos       print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0);
22475fd0b74Schristos       break;
22575fd0b74Schristos     case M32R_OPERAND_HASH :
22675fd0b74Schristos       print_hash (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
22775fd0b74Schristos       break;
22875fd0b74Schristos     case M32R_OPERAND_HI16 :
22975fd0b74Schristos       print_normal (cd, info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
23075fd0b74Schristos       break;
23175fd0b74Schristos     case M32R_OPERAND_IMM1 :
23275fd0b74Schristos       print_unsigned_with_hash_prefix (cd, info, fields->f_imm1, 0, pc, length);
23375fd0b74Schristos       break;
23475fd0b74Schristos     case M32R_OPERAND_SCR :
23575fd0b74Schristos       print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r2, 0);
23675fd0b74Schristos       break;
23775fd0b74Schristos     case M32R_OPERAND_SIMM16 :
23875fd0b74Schristos       print_signed_with_hash_prefix (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
23975fd0b74Schristos       break;
24075fd0b74Schristos     case M32R_OPERAND_SIMM8 :
24175fd0b74Schristos       print_signed_with_hash_prefix (cd, info, fields->f_simm8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
24275fd0b74Schristos       break;
24375fd0b74Schristos     case M32R_OPERAND_SLO16 :
24475fd0b74Schristos       print_normal (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
24575fd0b74Schristos       break;
24675fd0b74Schristos     case M32R_OPERAND_SR :
24775fd0b74Schristos       print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r2, 0);
24875fd0b74Schristos       break;
24975fd0b74Schristos     case M32R_OPERAND_SRC1 :
25075fd0b74Schristos       print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0);
25175fd0b74Schristos       break;
25275fd0b74Schristos     case M32R_OPERAND_SRC2 :
25375fd0b74Schristos       print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r2, 0);
25475fd0b74Schristos       break;
25575fd0b74Schristos     case M32R_OPERAND_UIMM16 :
25675fd0b74Schristos       print_unsigned_with_hash_prefix (cd, info, fields->f_uimm16, 0, pc, length);
25775fd0b74Schristos       break;
25875fd0b74Schristos     case M32R_OPERAND_UIMM24 :
25975fd0b74Schristos       print_address (cd, info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
26075fd0b74Schristos       break;
26175fd0b74Schristos     case M32R_OPERAND_UIMM3 :
26275fd0b74Schristos       print_unsigned_with_hash_prefix (cd, info, fields->f_uimm3, 0, pc, length);
26375fd0b74Schristos       break;
26475fd0b74Schristos     case M32R_OPERAND_UIMM4 :
26575fd0b74Schristos       print_unsigned_with_hash_prefix (cd, info, fields->f_uimm4, 0, pc, length);
26675fd0b74Schristos       break;
26775fd0b74Schristos     case M32R_OPERAND_UIMM5 :
26875fd0b74Schristos       print_unsigned_with_hash_prefix (cd, info, fields->f_uimm5, 0, pc, length);
26975fd0b74Schristos       break;
27075fd0b74Schristos     case M32R_OPERAND_UIMM8 :
27175fd0b74Schristos       print_unsigned_with_hash_prefix (cd, info, fields->f_uimm8, 0, pc, length);
27275fd0b74Schristos       break;
27375fd0b74Schristos     case M32R_OPERAND_ULO16 :
27475fd0b74Schristos       print_normal (cd, info, fields->f_uimm16, 0, pc, length);
27575fd0b74Schristos       break;
27675fd0b74Schristos 
27775fd0b74Schristos     default :
27875fd0b74Schristos       /* xgettext:c-format */
279ede78133Schristos       opcodes_error_handler
280ede78133Schristos 	(_("internal error: unrecognized field %d while printing insn"),
28175fd0b74Schristos 	 opindex);
28275fd0b74Schristos       abort ();
28375fd0b74Schristos   }
28475fd0b74Schristos }
28575fd0b74Schristos 
28675fd0b74Schristos cgen_print_fn * const m32r_cgen_print_handlers[] =
28775fd0b74Schristos {
28875fd0b74Schristos   print_insn_normal,
28975fd0b74Schristos };
29075fd0b74Schristos 
29175fd0b74Schristos 
29275fd0b74Schristos void
m32r_cgen_init_dis(CGEN_CPU_DESC cd)29375fd0b74Schristos m32r_cgen_init_dis (CGEN_CPU_DESC cd)
29475fd0b74Schristos {
29575fd0b74Schristos   m32r_cgen_init_opcode_table (cd);
29675fd0b74Schristos   m32r_cgen_init_ibld_table (cd);
29775fd0b74Schristos   cd->print_handlers = & m32r_cgen_print_handlers[0];
29875fd0b74Schristos   cd->print_operand = m32r_cgen_print_operand;
29975fd0b74Schristos }
30075fd0b74Schristos 
30175fd0b74Schristos 
30275fd0b74Schristos /* Default print handler.  */
30375fd0b74Schristos 
30475fd0b74Schristos static void
print_normal(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)30575fd0b74Schristos print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
30675fd0b74Schristos 	      void *dis_info,
30775fd0b74Schristos 	      long value,
30875fd0b74Schristos 	      unsigned int attrs,
30975fd0b74Schristos 	      bfd_vma pc ATTRIBUTE_UNUSED,
31075fd0b74Schristos 	      int length ATTRIBUTE_UNUSED)
31175fd0b74Schristos {
31275fd0b74Schristos   disassemble_info *info = (disassemble_info *) dis_info;
31375fd0b74Schristos 
31475fd0b74Schristos   /* Print the operand as directed by the attributes.  */
31575fd0b74Schristos   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
31675fd0b74Schristos     ; /* nothing to do */
31775fd0b74Schristos   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
31875fd0b74Schristos     (*info->fprintf_func) (info->stream, "%ld", value);
31975fd0b74Schristos   else
32075fd0b74Schristos     (*info->fprintf_func) (info->stream, "0x%lx", value);
32175fd0b74Schristos }
32275fd0b74Schristos 
32375fd0b74Schristos /* Default address handler.  */
32475fd0b74Schristos 
32575fd0b74Schristos static void
print_address(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,bfd_vma value,unsigned int attrs,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)32675fd0b74Schristos print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
32775fd0b74Schristos 	       void *dis_info,
32875fd0b74Schristos 	       bfd_vma value,
32975fd0b74Schristos 	       unsigned int attrs,
33075fd0b74Schristos 	       bfd_vma pc ATTRIBUTE_UNUSED,
33175fd0b74Schristos 	       int length ATTRIBUTE_UNUSED)
33275fd0b74Schristos {
33375fd0b74Schristos   disassemble_info *info = (disassemble_info *) dis_info;
33475fd0b74Schristos 
33575fd0b74Schristos   /* Print the operand as directed by the attributes.  */
33675fd0b74Schristos   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
33775fd0b74Schristos     ; /* Nothing to do.  */
33875fd0b74Schristos   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
33975fd0b74Schristos     (*info->print_address_func) (value, info);
34075fd0b74Schristos   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
34175fd0b74Schristos     (*info->print_address_func) (value, info);
34275fd0b74Schristos   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
34375fd0b74Schristos     (*info->fprintf_func) (info->stream, "%ld", (long) value);
34475fd0b74Schristos   else
34575fd0b74Schristos     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
34675fd0b74Schristos }
34775fd0b74Schristos 
34875fd0b74Schristos /* Keyword print handler.  */
34975fd0b74Schristos 
35075fd0b74Schristos static void
print_keyword(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,CGEN_KEYWORD * keyword_table,long value,unsigned int attrs ATTRIBUTE_UNUSED)35175fd0b74Schristos print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
35275fd0b74Schristos 	       void *dis_info,
35375fd0b74Schristos 	       CGEN_KEYWORD *keyword_table,
35475fd0b74Schristos 	       long value,
35575fd0b74Schristos 	       unsigned int attrs ATTRIBUTE_UNUSED)
35675fd0b74Schristos {
35775fd0b74Schristos   disassemble_info *info = (disassemble_info *) dis_info;
35875fd0b74Schristos   const CGEN_KEYWORD_ENTRY *ke;
35975fd0b74Schristos 
36075fd0b74Schristos   ke = cgen_keyword_lookup_value (keyword_table, value);
36175fd0b74Schristos   if (ke != NULL)
36275fd0b74Schristos     (*info->fprintf_func) (info->stream, "%s", ke->name);
36375fd0b74Schristos   else
36475fd0b74Schristos     (*info->fprintf_func) (info->stream, "???");
36575fd0b74Schristos }
36675fd0b74Schristos 
36775fd0b74Schristos /* Default insn printer.
36875fd0b74Schristos 
36975fd0b74Schristos    DIS_INFO is defined as `void *' so the disassembler needn't know anything
37075fd0b74Schristos    about disassemble_info.  */
37175fd0b74Schristos 
37275fd0b74Schristos static void
print_insn_normal(CGEN_CPU_DESC cd,void * dis_info,const CGEN_INSN * insn,CGEN_FIELDS * fields,bfd_vma pc,int length)37375fd0b74Schristos print_insn_normal (CGEN_CPU_DESC cd,
37475fd0b74Schristos 		   void *dis_info,
37575fd0b74Schristos 		   const CGEN_INSN *insn,
37675fd0b74Schristos 		   CGEN_FIELDS *fields,
37775fd0b74Schristos 		   bfd_vma pc,
37875fd0b74Schristos 		   int length)
37975fd0b74Schristos {
38075fd0b74Schristos   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
38175fd0b74Schristos   disassemble_info *info = (disassemble_info *) dis_info;
38275fd0b74Schristos   const CGEN_SYNTAX_CHAR_TYPE *syn;
38375fd0b74Schristos 
38475fd0b74Schristos   CGEN_INIT_PRINT (cd);
38575fd0b74Schristos 
38675fd0b74Schristos   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
38775fd0b74Schristos     {
38875fd0b74Schristos       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
38975fd0b74Schristos 	{
39075fd0b74Schristos 	  (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
39175fd0b74Schristos 	  continue;
39275fd0b74Schristos 	}
39375fd0b74Schristos       if (CGEN_SYNTAX_CHAR_P (*syn))
39475fd0b74Schristos 	{
39575fd0b74Schristos 	  (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
39675fd0b74Schristos 	  continue;
39775fd0b74Schristos 	}
39875fd0b74Schristos 
39975fd0b74Schristos       /* We have an operand.  */
40075fd0b74Schristos       m32r_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
40175fd0b74Schristos 				 fields, CGEN_INSN_ATTRS (insn), pc, length);
40275fd0b74Schristos     }
40375fd0b74Schristos }
40475fd0b74Schristos 
40575fd0b74Schristos /* Subroutine of print_insn. Reads an insn into the given buffers and updates
40675fd0b74Schristos    the extract info.
40775fd0b74Schristos    Returns 0 if all is well, non-zero otherwise.  */
40875fd0b74Schristos 
40975fd0b74Schristos static int
read_insn(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,bfd_vma pc,disassemble_info * info,bfd_byte * buf,int buflen,CGEN_EXTRACT_INFO * ex_info,unsigned long * insn_value)41075fd0b74Schristos read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
41175fd0b74Schristos 	   bfd_vma pc,
41275fd0b74Schristos 	   disassemble_info *info,
41375fd0b74Schristos 	   bfd_byte *buf,
41475fd0b74Schristos 	   int buflen,
41575fd0b74Schristos 	   CGEN_EXTRACT_INFO *ex_info,
41675fd0b74Schristos 	   unsigned long *insn_value)
41775fd0b74Schristos {
41875fd0b74Schristos   int status = (*info->read_memory_func) (pc, buf, buflen, info);
41975fd0b74Schristos 
42075fd0b74Schristos   if (status != 0)
42175fd0b74Schristos     {
42275fd0b74Schristos       (*info->memory_error_func) (status, pc, info);
42375fd0b74Schristos       return -1;
42475fd0b74Schristos     }
42575fd0b74Schristos 
42675fd0b74Schristos   ex_info->dis_info = info;
42775fd0b74Schristos   ex_info->valid = (1 << buflen) - 1;
42875fd0b74Schristos   ex_info->insn_bytes = buf;
42975fd0b74Schristos 
43075fd0b74Schristos   *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
43175fd0b74Schristos   return 0;
43275fd0b74Schristos }
43375fd0b74Schristos 
43475fd0b74Schristos /* Utility to print an insn.
43575fd0b74Schristos    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
43675fd0b74Schristos    The result is the size of the insn in bytes or zero for an unknown insn
43775fd0b74Schristos    or -1 if an error occurs fetching data (memory_error_func will have
43875fd0b74Schristos    been called).  */
43975fd0b74Schristos 
44075fd0b74Schristos static int
print_insn(CGEN_CPU_DESC cd,bfd_vma pc,disassemble_info * info,bfd_byte * buf,unsigned int buflen)44175fd0b74Schristos print_insn (CGEN_CPU_DESC cd,
44275fd0b74Schristos 	    bfd_vma pc,
44375fd0b74Schristos 	    disassemble_info *info,
44475fd0b74Schristos 	    bfd_byte *buf,
44575fd0b74Schristos 	    unsigned int buflen)
44675fd0b74Schristos {
44775fd0b74Schristos   CGEN_INSN_INT insn_value;
44875fd0b74Schristos   const CGEN_INSN_LIST *insn_list;
44975fd0b74Schristos   CGEN_EXTRACT_INFO ex_info;
45075fd0b74Schristos   int basesize;
45175fd0b74Schristos 
45275fd0b74Schristos   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
45375fd0b74Schristos   basesize = cd->base_insn_bitsize < buflen * 8 ?
45475fd0b74Schristos                                      cd->base_insn_bitsize : buflen * 8;
455*e992f068Schristos   insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
45675fd0b74Schristos 
45775fd0b74Schristos 
45875fd0b74Schristos   /* Fill in ex_info fields like read_insn would.  Don't actually call
45975fd0b74Schristos      read_insn, since the incoming buffer is already read (and possibly
46075fd0b74Schristos      modified a la m32r).  */
46175fd0b74Schristos   ex_info.valid = (1 << buflen) - 1;
46275fd0b74Schristos   ex_info.dis_info = info;
46375fd0b74Schristos   ex_info.insn_bytes = buf;
46475fd0b74Schristos 
46575fd0b74Schristos   /* The instructions are stored in hash lists.
46675fd0b74Schristos      Pick the first one and keep trying until we find the right one.  */
46775fd0b74Schristos 
46875fd0b74Schristos   insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
46975fd0b74Schristos   while (insn_list != NULL)
47075fd0b74Schristos     {
47175fd0b74Schristos       const CGEN_INSN *insn = insn_list->insn;
47275fd0b74Schristos       CGEN_FIELDS fields;
47375fd0b74Schristos       int length;
47475fd0b74Schristos       unsigned long insn_value_cropped;
47575fd0b74Schristos 
47675fd0b74Schristos #ifdef CGEN_VALIDATE_INSN_SUPPORTED
47775fd0b74Schristos       /* Not needed as insn shouldn't be in hash lists if not supported.  */
47875fd0b74Schristos       /* Supported by this cpu?  */
47975fd0b74Schristos       if (! m32r_cgen_insn_supported (cd, insn))
48075fd0b74Schristos         {
48175fd0b74Schristos           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
48275fd0b74Schristos 	  continue;
48375fd0b74Schristos         }
48475fd0b74Schristos #endif
48575fd0b74Schristos 
48675fd0b74Schristos       /* Basic bit mask must be correct.  */
48775fd0b74Schristos       /* ??? May wish to allow target to defer this check until the extract
48875fd0b74Schristos 	 handler.  */
48975fd0b74Schristos 
49075fd0b74Schristos       /* Base size may exceed this instruction's size.  Extract the
49175fd0b74Schristos          relevant part from the buffer. */
49275fd0b74Schristos       if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
49375fd0b74Schristos 	  (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
49475fd0b74Schristos 	insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
49575fd0b74Schristos 					   info->endian == BFD_ENDIAN_BIG);
49675fd0b74Schristos       else
49775fd0b74Schristos 	insn_value_cropped = insn_value;
49875fd0b74Schristos 
49975fd0b74Schristos       if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
50075fd0b74Schristos 	  == CGEN_INSN_BASE_VALUE (insn))
50175fd0b74Schristos 	{
50275fd0b74Schristos 	  /* Printing is handled in two passes.  The first pass parses the
50375fd0b74Schristos 	     machine insn and extracts the fields.  The second pass prints
50475fd0b74Schristos 	     them.  */
50575fd0b74Schristos 
50675fd0b74Schristos 	  /* Make sure the entire insn is loaded into insn_value, if it
50775fd0b74Schristos 	     can fit.  */
50875fd0b74Schristos 	  if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
50975fd0b74Schristos 	      (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
51075fd0b74Schristos 	    {
51175fd0b74Schristos 	      unsigned long full_insn_value;
51275fd0b74Schristos 	      int rc = read_insn (cd, pc, info, buf,
51375fd0b74Schristos 				  CGEN_INSN_BITSIZE (insn) / 8,
51475fd0b74Schristos 				  & ex_info, & full_insn_value);
51575fd0b74Schristos 	      if (rc != 0)
51675fd0b74Schristos 		return rc;
51775fd0b74Schristos 	      length = CGEN_EXTRACT_FN (cd, insn)
51875fd0b74Schristos 		(cd, insn, &ex_info, full_insn_value, &fields, pc);
51975fd0b74Schristos 	    }
52075fd0b74Schristos 	  else
52175fd0b74Schristos 	    length = CGEN_EXTRACT_FN (cd, insn)
52275fd0b74Schristos 	      (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
52375fd0b74Schristos 
52475fd0b74Schristos 	  /* Length < 0 -> error.  */
52575fd0b74Schristos 	  if (length < 0)
52675fd0b74Schristos 	    return length;
52775fd0b74Schristos 	  if (length > 0)
52875fd0b74Schristos 	    {
52975fd0b74Schristos 	      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
53075fd0b74Schristos 	      /* Length is in bits, result is in bytes.  */
53175fd0b74Schristos 	      return length / 8;
53275fd0b74Schristos 	    }
53375fd0b74Schristos 	}
53475fd0b74Schristos 
53575fd0b74Schristos       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
53675fd0b74Schristos     }
53775fd0b74Schristos 
53875fd0b74Schristos   return 0;
53975fd0b74Schristos }
54075fd0b74Schristos 
54175fd0b74Schristos /* Default value for CGEN_PRINT_INSN.
54275fd0b74Schristos    The result is the size of the insn in bytes or zero for an unknown insn
54375fd0b74Schristos    or -1 if an error occured fetching bytes.  */
54475fd0b74Schristos 
54575fd0b74Schristos #ifndef CGEN_PRINT_INSN
54675fd0b74Schristos #define CGEN_PRINT_INSN default_print_insn
54775fd0b74Schristos #endif
54875fd0b74Schristos 
54975fd0b74Schristos static int
default_print_insn(CGEN_CPU_DESC cd,bfd_vma pc,disassemble_info * info)55075fd0b74Schristos default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
55175fd0b74Schristos {
55275fd0b74Schristos   bfd_byte buf[CGEN_MAX_INSN_SIZE];
55375fd0b74Schristos   int buflen;
55475fd0b74Schristos   int status;
55575fd0b74Schristos 
55675fd0b74Schristos   /* Attempt to read the base part of the insn.  */
55775fd0b74Schristos   buflen = cd->base_insn_bitsize / 8;
55875fd0b74Schristos   status = (*info->read_memory_func) (pc, buf, buflen, info);
55975fd0b74Schristos 
56075fd0b74Schristos   /* Try again with the minimum part, if min < base.  */
56175fd0b74Schristos   if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
56275fd0b74Schristos     {
56375fd0b74Schristos       buflen = cd->min_insn_bitsize / 8;
56475fd0b74Schristos       status = (*info->read_memory_func) (pc, buf, buflen, info);
56575fd0b74Schristos     }
56675fd0b74Schristos 
56775fd0b74Schristos   if (status != 0)
56875fd0b74Schristos     {
56975fd0b74Schristos       (*info->memory_error_func) (status, pc, info);
57075fd0b74Schristos       return -1;
57175fd0b74Schristos     }
57275fd0b74Schristos 
57375fd0b74Schristos   return print_insn (cd, pc, info, buf, buflen);
57475fd0b74Schristos }
57575fd0b74Schristos 
57675fd0b74Schristos /* Main entry point.
57775fd0b74Schristos    Print one instruction from PC on INFO->STREAM.
57875fd0b74Schristos    Return the size of the instruction (in bytes).  */
57975fd0b74Schristos 
58075fd0b74Schristos typedef struct cpu_desc_list
58175fd0b74Schristos {
58275fd0b74Schristos   struct cpu_desc_list *next;
58375fd0b74Schristos   CGEN_BITSET *isa;
58475fd0b74Schristos   int mach;
58575fd0b74Schristos   int endian;
586*e992f068Schristos   int insn_endian;
58775fd0b74Schristos   CGEN_CPU_DESC cd;
58875fd0b74Schristos } cpu_desc_list;
58975fd0b74Schristos 
59075fd0b74Schristos int
print_insn_m32r(bfd_vma pc,disassemble_info * info)59175fd0b74Schristos print_insn_m32r (bfd_vma pc, disassemble_info *info)
59275fd0b74Schristos {
59375fd0b74Schristos   static cpu_desc_list *cd_list = 0;
59475fd0b74Schristos   cpu_desc_list *cl = 0;
59575fd0b74Schristos   static CGEN_CPU_DESC cd = 0;
59675fd0b74Schristos   static CGEN_BITSET *prev_isa;
59775fd0b74Schristos   static int prev_mach;
59875fd0b74Schristos   static int prev_endian;
599*e992f068Schristos   static int prev_insn_endian;
60075fd0b74Schristos   int length;
60175fd0b74Schristos   CGEN_BITSET *isa;
60275fd0b74Schristos   int mach;
60375fd0b74Schristos   int endian = (info->endian == BFD_ENDIAN_BIG
60475fd0b74Schristos 		? CGEN_ENDIAN_BIG
60575fd0b74Schristos 		: CGEN_ENDIAN_LITTLE);
606*e992f068Schristos   int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
607*e992f068Schristos                      ? CGEN_ENDIAN_BIG
608*e992f068Schristos                      : CGEN_ENDIAN_LITTLE);
60975fd0b74Schristos   enum bfd_architecture arch;
61075fd0b74Schristos 
61175fd0b74Schristos   /* ??? gdb will set mach but leave the architecture as "unknown" */
61275fd0b74Schristos #ifndef CGEN_BFD_ARCH
61375fd0b74Schristos #define CGEN_BFD_ARCH bfd_arch_m32r
61475fd0b74Schristos #endif
61575fd0b74Schristos   arch = info->arch;
61675fd0b74Schristos   if (arch == bfd_arch_unknown)
61775fd0b74Schristos     arch = CGEN_BFD_ARCH;
61875fd0b74Schristos 
61975fd0b74Schristos   /* There's no standard way to compute the machine or isa number
62075fd0b74Schristos      so we leave it to the target.  */
62175fd0b74Schristos #ifdef CGEN_COMPUTE_MACH
62275fd0b74Schristos   mach = CGEN_COMPUTE_MACH (info);
62375fd0b74Schristos #else
62475fd0b74Schristos   mach = info->mach;
62575fd0b74Schristos #endif
62675fd0b74Schristos 
62775fd0b74Schristos #ifdef CGEN_COMPUTE_ISA
62875fd0b74Schristos   {
62975fd0b74Schristos     static CGEN_BITSET *permanent_isa;
63075fd0b74Schristos 
63175fd0b74Schristos     if (!permanent_isa)
63275fd0b74Schristos       permanent_isa = cgen_bitset_create (MAX_ISAS);
63375fd0b74Schristos     isa = permanent_isa;
63475fd0b74Schristos     cgen_bitset_clear (isa);
63575fd0b74Schristos     cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
63675fd0b74Schristos   }
63775fd0b74Schristos #else
638012573ebSchristos   isa = info->private_data;
63975fd0b74Schristos #endif
64075fd0b74Schristos 
64175fd0b74Schristos   /* If we've switched cpu's, try to find a handle we've used before */
64275fd0b74Schristos   if (cd
64375fd0b74Schristos       && (cgen_bitset_compare (isa, prev_isa) != 0
64475fd0b74Schristos 	  || mach != prev_mach
64575fd0b74Schristos 	  || endian != prev_endian))
64675fd0b74Schristos     {
64775fd0b74Schristos       cd = 0;
64875fd0b74Schristos       for (cl = cd_list; cl; cl = cl->next)
64975fd0b74Schristos 	{
65075fd0b74Schristos 	  if (cgen_bitset_compare (cl->isa, isa) == 0 &&
65175fd0b74Schristos 	      cl->mach == mach &&
65275fd0b74Schristos 	      cl->endian == endian)
65375fd0b74Schristos 	    {
65475fd0b74Schristos 	      cd = cl->cd;
65575fd0b74Schristos  	      prev_isa = cd->isas;
65675fd0b74Schristos 	      break;
65775fd0b74Schristos 	    }
65875fd0b74Schristos 	}
65975fd0b74Schristos     }
66075fd0b74Schristos 
66175fd0b74Schristos   /* If we haven't initialized yet, initialize the opcode table.  */
66275fd0b74Schristos   if (! cd)
66375fd0b74Schristos     {
66475fd0b74Schristos       const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
66575fd0b74Schristos       const char *mach_name;
66675fd0b74Schristos 
66775fd0b74Schristos       if (!arch_type)
66875fd0b74Schristos 	abort ();
66975fd0b74Schristos       mach_name = arch_type->printable_name;
67075fd0b74Schristos 
67175fd0b74Schristos       prev_isa = cgen_bitset_copy (isa);
67275fd0b74Schristos       prev_mach = mach;
67375fd0b74Schristos       prev_endian = endian;
674*e992f068Schristos       prev_insn_endian = insn_endian;
67575fd0b74Schristos       cd = m32r_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
67675fd0b74Schristos 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
67775fd0b74Schristos 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
678*e992f068Schristos                                  CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
67975fd0b74Schristos 				 CGEN_CPU_OPEN_END);
68075fd0b74Schristos       if (!cd)
68175fd0b74Schristos 	abort ();
68275fd0b74Schristos 
68375fd0b74Schristos       /* Save this away for future reference.  */
68475fd0b74Schristos       cl = xmalloc (sizeof (struct cpu_desc_list));
68575fd0b74Schristos       cl->cd = cd;
68675fd0b74Schristos       cl->isa = prev_isa;
68775fd0b74Schristos       cl->mach = mach;
68875fd0b74Schristos       cl->endian = endian;
68975fd0b74Schristos       cl->next = cd_list;
69075fd0b74Schristos       cd_list = cl;
69175fd0b74Schristos 
69275fd0b74Schristos       m32r_cgen_init_dis (cd);
69375fd0b74Schristos     }
69475fd0b74Schristos 
69575fd0b74Schristos   /* We try to have as much common code as possible.
69675fd0b74Schristos      But at this point some targets need to take over.  */
69775fd0b74Schristos   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
69875fd0b74Schristos      but if not possible try to move this hook elsewhere rather than
69975fd0b74Schristos      have two hooks.  */
70075fd0b74Schristos   length = CGEN_PRINT_INSN (cd, pc, info);
70175fd0b74Schristos   if (length > 0)
70275fd0b74Schristos     return length;
70375fd0b74Schristos   if (length < 0)
70475fd0b74Schristos     return -1;
70575fd0b74Schristos 
70675fd0b74Schristos   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
70775fd0b74Schristos   return cd->default_insn_bitsize / 8;
70875fd0b74Schristos }
709