1/* Disassembler interface for targets using CGEN. -*- C -*-
2   CGEN: Cpu tools GENerator
3
4   THIS FILE IS MACHINE GENERATED WITH CGEN.
5   - the resultant file is machine generated, cgen-dis.in isn't
6
7   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005
8   Free Software Foundation, Inc.
9
10   This file is part of the GNU Binutils and GDB, the GNU debugger.
11
12   This program is free software; you can redistribute it and/or modify
13   it under the terms of the GNU General Public License as published by
14   the Free Software Foundation; either version 2, or (at your option)
15   any later version.
16
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20   GNU General Public License for more details.
21
22   You should have received a copy of the GNU General Public License
23   along with this program; if not, write to the Free Software Foundation, Inc.,
24   51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
25
26/* ??? Eventually more and more of this stuff can go to cpu-independent files.
27   Keep that in mind.  */
28
29#include "sysdep.h"
30#include <stdio.h>
31#include "ansidecl.h"
32#include "dis-asm.h"
33#include "bfd.h"
34#include "symcat.h"
35#include "libiberty.h"
36#include "mep-desc.h"
37#include "mep-opc.h"
38#include "opintl.h"
39
40/* Default text to print if an instruction isn't recognized.  */
41#define UNKNOWN_INSN_MSG _("*unknown*")
42
43static void print_normal
44  (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
45static void print_address
46  (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
47static void print_keyword
48  (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
49static void print_insn_normal
50  (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
51static int print_insn
52  (CGEN_CPU_DESC, bfd_vma,  disassemble_info *, bfd_byte *, unsigned);
53static int default_print_insn
54  (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
55static int read_insn
56  (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
57   unsigned long *);
58
59/* -- disassembler routines inserted here.  */
60
61/* -- dis.c */
62
63#include "elf/mep.h"
64#include "elf-bfd.h"
65
66#define CGEN_VALIDATE_INSN_SUPPORTED
67
68static void print_tpreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
69static void print_spreg (CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int);
70
71static void
72print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
73	     CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
74	     unsigned int flags ATTRIBUTE_UNUSED)
75{
76  disassemble_info *info = (disassemble_info *) dis_info;
77
78  (*info->fprintf_func) (info->stream, "$tp");
79}
80
81static void
82print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, PTR dis_info,
83	     CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
84	     unsigned int flags ATTRIBUTE_UNUSED)
85{
86  disassemble_info *info = (disassemble_info *) dis_info;
87
88  (*info->fprintf_func) (info->stream, "$sp");
89}
90
91/* begin-cop-ip-print-handlers */
92static void
93print_fmax_cr (CGEN_CPU_DESC cd,
94	void *dis_info,
95	CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
96	long value,
97	unsigned int attrs)
98{
99  print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_fmax, value, attrs);
100}
101static void
102print_fmax_ccr (CGEN_CPU_DESC cd,
103	void *dis_info,
104	CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
105	long value,
106	unsigned int attrs)
107{
108  print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_fmax, value, attrs);
109}
110/* end-cop-ip-print-handlers */
111
112/************************************************************\
113*********************** Experimental *************************
114\************************************************************/
115
116#undef  CGEN_PRINT_INSN
117#define CGEN_PRINT_INSN mep_print_insn
118
119static int
120mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
121		      bfd_byte *buf, int corelength, int copro1length,
122		      int copro2length ATTRIBUTE_UNUSED)
123{
124  int i;
125  int status = 0;
126  /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
127  bfd_byte insnbuf[64];
128
129  /* If corelength > 0 then there is a core insn present. It
130     will be at the beginning of the buffer.  After printing
131     the core insn, we need to print the + on the next line.  */
132  if (corelength > 0)
133    {
134      int my_status = 0;
135
136      for (i = 0; i < corelength; i++ )
137	insnbuf[i] = buf[i];
138      cd->isas = & MEP_CORE_ISA;
139
140      my_status = print_insn (cd, pc, info, insnbuf, corelength);
141      if (my_status != corelength)
142	{
143	  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
144	  my_status = corelength;
145	}
146      status += my_status;
147
148      /* Print the + to indicate that the following copro insn is   */
149      /* part of a vliw group.                                      */
150      if (copro1length > 0)
151	(*info->fprintf_func) (info->stream, " + ");
152    }
153
154  /* Now all that is left to be processed is the coprocessor insns
155     In vliw mode, there will always be one.  Its positioning will
156     be from byte corelength to byte corelength+copro1length -1.
157     No need to check for existence.   Also, the first vliw insn,
158     will, as spec'd, always be at least as long as the core insn
159     so we don't need to flush the buffer.  */
160  if (copro1length > 0)
161    {
162      int my_status = 0;
163
164      for (i = corelength; i < corelength + copro1length; i++ )
165	insnbuf[i - corelength] = buf[i];
166
167      switch (copro1length)
168	{
169	case 0:
170	  break;
171	case 2:
172	  cd->isas = & MEP_COP16_ISA;
173	  break;
174	case 4:
175	  cd->isas = & MEP_COP32_ISA;
176	  break;
177	case 6:
178	  cd->isas = & MEP_COP48_ISA;
179	  break;
180	case 8:
181	  cd->isas = & MEP_COP64_ISA;
182	  break;
183	default:
184	  /* Shouldn't be anything but 16,32,48,64.  */
185	  break;
186	}
187
188      my_status = print_insn (cd, pc, info, insnbuf, copro1length);
189
190      if (my_status != copro1length)
191	{
192	  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
193	  my_status = copro1length;
194	}
195      status += my_status;
196    }
197
198#if 0
199  /* Now we need to process the second copro insn if it exists. We
200     have no guarantee that the second copro insn will be longer
201     than the first, so we have to flush the buffer if we are have
202     a second copro insn to process.  If present, this insn will
203     be in the position from byte corelength+copro1length to byte
204     corelength+copro1length+copro2length-1 (which better equal 8
205     or else we're in big trouble.  */
206  if (copro2length > 0)
207    {
208      int my_status = 0;
209
210      for (i = 0; i < 64 ; i++)
211	insnbuf[i] = 0;
212
213      for (i = corelength + copro1length; i < 64; i++)
214	insnbuf[i - (corelength + copro1length)] = buf[i];
215
216      switch (copro2length)
217	{
218	case 2:
219	  cd->isas = 1 << ISA_EXT_COP1_16;
220	  break;
221	case 4:
222	  cd->isas = 1 << ISA_EXT_COP1_32;
223	  break;
224	case 6:
225	  cd->isas = 1 << ISA_EXT_COP1_48;
226	  break;
227	case 8:
228	  cd->isas = 1 << ISA_EXT_COP1_64;
229	  break;
230	default:
231	  /* Shouldn't be anything but 16,32,48,64.  */
232	  break;
233	}
234
235      my_status = print_insn (cd, pc, info, insnbuf, copro2length);
236
237      if (my_status != copro2length)
238	{
239	  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
240	  my_status = copro2length;
241	}
242
243      status += my_status;
244    }
245#endif
246
247  /* Status should now be the number of bytes that were printed
248     which should be 4 for VLIW32 mode and 64 for VLIW64 mode.  */
249
250  if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
251    return -1;
252  else
253    return status;
254}
255
256/* The two functions mep_examine_vliw[32,64]_insns are used find out
257   which vliw combinaion (16 bit core with 48 bit copro, 32 bit core
258   with 32 bit copro, etc.) is present.  Later on, when internally
259   parallel coprocessors are handled, only these functions should
260   need to be changed.
261
262   At this time only the following combinations are supported:
263
264   VLIW32 Mode:
265   16 bit core insn (core) and 16 bit coprocessor insn (cop1)
266   32 bit core insn (core)
267   32 bit coprocessor insn (cop1)
268   Note: As of this time, I do not believe we have enough information
269         to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
270         no 16 bit coprocessor insns have been specified.
271
272   VLIW64 Mode:
273   16 bit core insn (core) and 48 bit coprocessor insn (cop1)
274   32 bit core insn (core) and 32 bit coprocessor insn (cop1)
275   64 bit coprocessor insn (cop1)
276
277   The framework for an internally parallel coprocessor is also
278   present (2nd coprocessor insn is cop2), but at this time it
279   is not used.  This only appears to be valid in VLIW64 mode.  */
280
281static int
282mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
283{
284  int status;
285  int buflength;
286  int corebuflength;
287  int cop1buflength;
288  int cop2buflength;
289  bfd_byte buf[CGEN_MAX_INSN_SIZE];
290  char indicator16[1];
291  char indicatorcop32[2];
292
293  /* At this time we're not supporting internally parallel coprocessors,
294     so cop2buflength will always be 0.  */
295  cop2buflength = 0;
296
297  /* Read in 32 bits.  */
298  buflength = 4; /* VLIW insn spans 4 bytes.  */
299  status = (*info->read_memory_func) (pc, buf, buflength, info);
300
301  if (status != 0)
302    {
303      (*info->memory_error_func) (status, pc, info);
304      return -1;
305    }
306
307  /* Put the big endian representation of the bytes to be examined
308     in the temporary buffers for examination.  */
309
310  if (info->endian == BFD_ENDIAN_BIG)
311    {
312      indicator16[0] = buf[0];
313      indicatorcop32[0] = buf[0];
314      indicatorcop32[1] = buf[1];
315    }
316  else
317    {
318      indicator16[0] = buf[1];
319      indicatorcop32[0] = buf[1];
320      indicatorcop32[1] = buf[0];
321    }
322
323  /* If the two high order bits are 00, 01 or 10, we have a 16 bit
324     core insn and a 48 bit copro insn.  */
325
326  if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
327    {
328      if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
329	{
330          /* We have a 32 bit copro insn.  */
331          corebuflength = 0;
332	  /* All 4 4ytes are one copro insn. */
333          cop1buflength = 4;
334	}
335      else
336	{
337          /* We have a 32 bit core.  */
338          corebuflength = 4;
339          cop1buflength = 0;
340	}
341    }
342  else
343    {
344      /* We have a 16 bit core insn and a 16 bit copro insn.  */
345      corebuflength = 2;
346      cop1buflength = 2;
347    }
348
349  /* Now we have the distrubution set.  Print them out.  */
350  status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
351				 cop1buflength, cop2buflength);
352
353  return status;
354}
355
356static int
357mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
358{
359  int status;
360  int buflength;
361  int corebuflength;
362  int cop1buflength;
363  int cop2buflength;
364  bfd_byte buf[CGEN_MAX_INSN_SIZE];
365  char indicator16[1];
366  char indicator64[4];
367
368  /* At this time we're not supporting internally parallel
369     coprocessors, so cop2buflength will always be 0.  */
370  cop2buflength = 0;
371
372  /* Read in 64 bits.  */
373  buflength = 8; /* VLIW insn spans 8 bytes.  */
374  status = (*info->read_memory_func) (pc, buf, buflength, info);
375
376  if (status != 0)
377    {
378      (*info->memory_error_func) (status, pc, info);
379      return -1;
380    }
381
382  /* We have all 64 bits in the buffer now.  We have to figure out
383     what combination of instruction sizes are present.  The two
384     high order bits will indicate whether or not we have a 16 bit
385     core insn or not.  If not, then we have to look at the 7,8th
386     bytes to tell whether we have 64 bit copro insn or a 32 bit
387     core insn with a 32 bit copro insn.  Endianness will make a
388     difference here.  */
389
390  /* Put the big endian representation of the bytes to be examined
391     in the temporary buffers for examination.  */
392
393  /* indicator16[0] = buf[0];  */
394  if (info->endian == BFD_ENDIAN_BIG)
395    {
396      indicator16[0] = buf[0];
397      indicator64[0] = buf[0];
398      indicator64[1] = buf[1];
399      indicator64[2] = buf[2];
400      indicator64[3] = buf[3];
401    }
402  else
403    {
404      indicator16[0] = buf[1];
405      indicator64[0] = buf[1];
406      indicator64[1] = buf[0];
407      indicator64[2] = buf[3];
408      indicator64[3] = buf[2];
409    }
410
411  /* If the two high order bits are 00, 01 or 10, we have a 16 bit
412     core insn and a 48 bit copro insn.  */
413
414  if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
415    {
416      if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
417	  && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
418	{
419          /* We have a 64 bit copro insn.  */
420          corebuflength = 0;
421	  /* All 8 bytes are one copro insn.  */
422          cop1buflength = 8;
423	}
424      else
425	{
426          /* We have a 32 bit core insn and a 32 bit copro insn.  */
427          corebuflength = 4;
428          cop1buflength = 4;
429	}
430    }
431  else
432    {
433      /* We have a 16 bit core insn and a 48 bit copro insn.  */
434      corebuflength = 2;
435      cop1buflength = 6;
436    }
437
438  /* Now we have the distrubution set.  Print them out. */
439  status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
440				 cop1buflength, cop2buflength);
441
442  return status;
443}
444
445static int
446mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
447{
448  int status;
449
450  /* Extract and adapt to configuration number, if available. */
451  if (info->section && info->section->owner)
452    {
453      bfd *abfd = info->section->owner;
454      mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
455      /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
456    }
457
458  /* Picking the right ISA bitmask for the current context is tricky.  */
459  if (info->section)
460    {
461      if (info->section->flags & SEC_MEP_VLIW)
462	{
463	  /* Are we in 32 or 64 bit vliw mode?  */
464	  if (MEP_VLIW64)
465	    status = mep_examine_vliw64_insns (cd, pc, info);
466	  else
467	    status = mep_examine_vliw32_insns (cd, pc, info);
468	  /* Both the above branches set their own isa bitmasks.  */
469	}
470      else
471	{
472	  cd->isas = & MEP_CORE_ISA;
473	  status = default_print_insn (cd, pc, info);
474	}
475    }
476  else /* sid or gdb */
477    {
478      status = default_print_insn (cd, pc, info);
479    }
480
481  return status;
482}
483
484
485/* -- opc.c */
486
487void mep_cgen_print_operand
488  (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
489
490/* Main entry point for printing operands.
491   XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
492   of dis-asm.h on cgen.h.
493
494   This function is basically just a big switch statement.  Earlier versions
495   used tables to look up the function to use, but
496   - if the table contains both assembler and disassembler functions then
497     the disassembler contains much of the assembler and vice-versa,
498   - there's a lot of inlining possibilities as things grow,
499   - using a switch statement avoids the function call overhead.
500
501   This function could be moved into `print_insn_normal', but keeping it
502   separate makes clear the interface between `print_insn_normal' and each of
503   the handlers.  */
504
505void
506mep_cgen_print_operand (CGEN_CPU_DESC cd,
507			   int opindex,
508			   void * xinfo,
509			   CGEN_FIELDS *fields,
510			   void const *attrs ATTRIBUTE_UNUSED,
511			   bfd_vma pc,
512			   int length)
513{
514  disassemble_info *info = (disassemble_info *) xinfo;
515
516  switch (opindex)
517    {
518    case MEP_OPERAND_ADDR24A4 :
519      print_normal (cd, info, fields->f_24u8a4n, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
520      break;
521    case MEP_OPERAND_CALLNUM :
522      print_normal (cd, info, fields->f_callnum, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
523      break;
524    case MEP_OPERAND_CCCC :
525      print_normal (cd, info, fields->f_rm, 0, pc, length);
526      break;
527    case MEP_OPERAND_CCRN :
528      print_keyword (cd, info, & mep_cgen_opval_h_ccr, fields->f_ccrn, 0|(1<<CGEN_OPERAND_VIRTUAL));
529      break;
530    case MEP_OPERAND_CDISP8 :
531      print_normal (cd, info, fields->f_8s24, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
532      break;
533    case MEP_OPERAND_CDISP8A2 :
534      print_normal (cd, info, fields->f_8s24a2, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
535      break;
536    case MEP_OPERAND_CDISP8A4 :
537      print_normal (cd, info, fields->f_8s24a4, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
538      break;
539    case MEP_OPERAND_CDISP8A8 :
540      print_normal (cd, info, fields->f_8s24a8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
541      break;
542    case MEP_OPERAND_CIMM4 :
543      print_normal (cd, info, fields->f_rn, 0, pc, length);
544      break;
545    case MEP_OPERAND_CIMM5 :
546      print_normal (cd, info, fields->f_5u24, 0, pc, length);
547      break;
548    case MEP_OPERAND_CODE16 :
549      print_normal (cd, info, fields->f_16u16, 0, pc, length);
550      break;
551    case MEP_OPERAND_CODE24 :
552      print_normal (cd, info, fields->f_24u4n, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
553      break;
554    case MEP_OPERAND_CP_FLAG :
555      print_keyword (cd, info, & mep_cgen_opval_h_ccr, 0, 0);
556      break;
557    case MEP_OPERAND_CRN :
558      print_keyword (cd, info, & mep_cgen_opval_h_cr, fields->f_crn, 0);
559      break;
560    case MEP_OPERAND_CRN64 :
561      print_keyword (cd, info, & mep_cgen_opval_h_cr64, fields->f_crn, 0);
562      break;
563    case MEP_OPERAND_CRNX :
564      print_keyword (cd, info, & mep_cgen_opval_h_cr, fields->f_crnx, 0|(1<<CGEN_OPERAND_VIRTUAL));
565      break;
566    case MEP_OPERAND_CRNX64 :
567      print_keyword (cd, info, & mep_cgen_opval_h_cr64, fields->f_crnx, 0|(1<<CGEN_OPERAND_VIRTUAL));
568      break;
569    case MEP_OPERAND_CSRN :
570      print_keyword (cd, info, & mep_cgen_opval_h_csr, fields->f_csrn, 0|(1<<CGEN_OPERAND_VIRTUAL));
571      break;
572    case MEP_OPERAND_CSRN_IDX :
573      print_normal (cd, info, fields->f_csrn, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
574      break;
575    case MEP_OPERAND_DBG :
576      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
577      break;
578    case MEP_OPERAND_DEPC :
579      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
580      break;
581    case MEP_OPERAND_EPC :
582      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
583      break;
584    case MEP_OPERAND_EXC :
585      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
586      break;
587    case MEP_OPERAND_FMAX_CCRN :
588      print_fmax_ccr (cd, info, & mep_cgen_opval_h_ccr, fields->f_fmax_4_4, 0);
589      break;
590    case MEP_OPERAND_FMAX_FRD :
591      print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frd, 0|(1<<CGEN_OPERAND_VIRTUAL));
592      break;
593    case MEP_OPERAND_FMAX_FRD_INT :
594      print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frd, 0|(1<<CGEN_OPERAND_VIRTUAL));
595      break;
596    case MEP_OPERAND_FMAX_FRM :
597      print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frm, 0|(1<<CGEN_OPERAND_VIRTUAL));
598      break;
599    case MEP_OPERAND_FMAX_FRN :
600      print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frn, 0|(1<<CGEN_OPERAND_VIRTUAL));
601      break;
602    case MEP_OPERAND_FMAX_FRN_INT :
603      print_fmax_cr (cd, info, & mep_cgen_opval_h_cr, fields->f_fmax_frn, 0|(1<<CGEN_OPERAND_VIRTUAL));
604      break;
605    case MEP_OPERAND_FMAX_RM :
606      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_fmax_rm, 0);
607      break;
608    case MEP_OPERAND_HI :
609      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
610      break;
611    case MEP_OPERAND_LO :
612      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
613      break;
614    case MEP_OPERAND_LP :
615      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
616      break;
617    case MEP_OPERAND_MB0 :
618      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
619      break;
620    case MEP_OPERAND_MB1 :
621      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
622      break;
623    case MEP_OPERAND_ME0 :
624      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
625      break;
626    case MEP_OPERAND_ME1 :
627      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
628      break;
629    case MEP_OPERAND_NPC :
630      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
631      break;
632    case MEP_OPERAND_OPT :
633      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
634      break;
635    case MEP_OPERAND_PCABS24A2 :
636      print_address (cd, info, fields->f_24u5a2n, 0|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
637      break;
638    case MEP_OPERAND_PCREL12A2 :
639      print_address (cd, info, fields->f_12s4a2, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
640      break;
641    case MEP_OPERAND_PCREL17A2 :
642      print_address (cd, info, fields->f_17s16a2, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
643      break;
644    case MEP_OPERAND_PCREL24A2 :
645      print_address (cd, info, fields->f_24s5a2n, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
646      break;
647    case MEP_OPERAND_PCREL8A2 :
648      print_address (cd, info, fields->f_8s8a2, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
649      break;
650    case MEP_OPERAND_PSW :
651      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
652      break;
653    case MEP_OPERAND_R0 :
654      print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
655      break;
656    case MEP_OPERAND_R1 :
657      print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
658      break;
659    case MEP_OPERAND_RL :
660      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rl, 0);
661      break;
662    case MEP_OPERAND_RM :
663      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rm, 0);
664      break;
665    case MEP_OPERAND_RMA :
666      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rm, 0);
667      break;
668    case MEP_OPERAND_RN :
669      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
670      break;
671    case MEP_OPERAND_RN3 :
672      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
673      break;
674    case MEP_OPERAND_RN3C :
675      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
676      break;
677    case MEP_OPERAND_RN3L :
678      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
679      break;
680    case MEP_OPERAND_RN3S :
681      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
682      break;
683    case MEP_OPERAND_RN3UC :
684      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
685      break;
686    case MEP_OPERAND_RN3UL :
687      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
688      break;
689    case MEP_OPERAND_RN3US :
690      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn3, 0);
691      break;
692    case MEP_OPERAND_RNC :
693      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
694      break;
695    case MEP_OPERAND_RNL :
696      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
697      break;
698    case MEP_OPERAND_RNS :
699      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
700      break;
701    case MEP_OPERAND_RNUC :
702      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
703      break;
704    case MEP_OPERAND_RNUL :
705      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
706      break;
707    case MEP_OPERAND_RNUS :
708      print_keyword (cd, info, & mep_cgen_opval_h_gpr, fields->f_rn, 0);
709      break;
710    case MEP_OPERAND_SAR :
711      print_keyword (cd, info, & mep_cgen_opval_h_csr, 0, 0);
712      break;
713    case MEP_OPERAND_SDISP16 :
714      print_normal (cd, info, fields->f_16s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
715      break;
716    case MEP_OPERAND_SIMM16 :
717      print_normal (cd, info, fields->f_16s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
718      break;
719    case MEP_OPERAND_SIMM6 :
720      print_normal (cd, info, fields->f_6s8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
721      break;
722    case MEP_OPERAND_SIMM8 :
723      print_normal (cd, info, fields->f_8s8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELOC_IMPLIES_OVERFLOW), pc, length);
724      break;
725    case MEP_OPERAND_SP :
726      print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
727      break;
728    case MEP_OPERAND_SPR :
729      print_spreg (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
730      break;
731    case MEP_OPERAND_TP :
732      print_keyword (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
733      break;
734    case MEP_OPERAND_TPR :
735      print_tpreg (cd, info, & mep_cgen_opval_h_gpr, 0, 0);
736      break;
737    case MEP_OPERAND_UDISP2 :
738      print_normal (cd, info, fields->f_2u6, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
739      break;
740    case MEP_OPERAND_UDISP7 :
741      print_normal (cd, info, fields->f_7u9, 0, pc, length);
742      break;
743    case MEP_OPERAND_UDISP7A2 :
744      print_normal (cd, info, fields->f_7u9a2, 0, pc, length);
745      break;
746    case MEP_OPERAND_UDISP7A4 :
747      print_normal (cd, info, fields->f_7u9a4, 0, pc, length);
748      break;
749    case MEP_OPERAND_UIMM16 :
750      print_normal (cd, info, fields->f_16u16, 0, pc, length);
751      break;
752    case MEP_OPERAND_UIMM2 :
753      print_normal (cd, info, fields->f_2u10, 0, pc, length);
754      break;
755    case MEP_OPERAND_UIMM24 :
756      print_normal (cd, info, fields->f_24u8n, 0|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
757      break;
758    case MEP_OPERAND_UIMM3 :
759      print_normal (cd, info, fields->f_3u5, 0, pc, length);
760      break;
761    case MEP_OPERAND_UIMM4 :
762      print_normal (cd, info, fields->f_4u8, 0, pc, length);
763      break;
764    case MEP_OPERAND_UIMM5 :
765      print_normal (cd, info, fields->f_5u8, 0, pc, length);
766      break;
767    case MEP_OPERAND_UIMM7A4 :
768      print_normal (cd, info, fields->f_7u9a4, 0, pc, length);
769      break;
770    case MEP_OPERAND_ZERO :
771      print_normal (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
772      break;
773
774    default :
775      /* xgettext:c-format */
776      fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
777	       opindex);
778    abort ();
779  }
780}
781
782cgen_print_fn * const mep_cgen_print_handlers[] =
783{
784  print_insn_normal,
785};
786
787
788void
789mep_cgen_init_dis (CGEN_CPU_DESC cd)
790{
791  mep_cgen_init_opcode_table (cd);
792  mep_cgen_init_ibld_table (cd);
793  cd->print_handlers = & mep_cgen_print_handlers[0];
794  cd->print_operand = mep_cgen_print_operand;
795}
796
797
798/* Default print handler.  */
799
800static void
801print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
802	      void *dis_info,
803	      long value,
804	      unsigned int attrs,
805	      bfd_vma pc ATTRIBUTE_UNUSED,
806	      int length ATTRIBUTE_UNUSED)
807{
808  disassemble_info *info = (disassemble_info *) dis_info;
809
810#ifdef CGEN_PRINT_NORMAL
811  CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
812#endif
813
814  /* Print the operand as directed by the attributes.  */
815  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
816    ; /* nothing to do */
817  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
818    (*info->fprintf_func) (info->stream, "%ld", value);
819  else
820    (*info->fprintf_func) (info->stream, "0x%lx", value);
821}
822
823/* Default address handler.  */
824
825static void
826print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
827	       void *dis_info,
828	       bfd_vma value,
829	       unsigned int attrs,
830	       bfd_vma pc ATTRIBUTE_UNUSED,
831	       int length ATTRIBUTE_UNUSED)
832{
833  disassemble_info *info = (disassemble_info *) dis_info;
834
835#ifdef CGEN_PRINT_ADDRESS
836  CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
837#endif
838
839  /* Print the operand as directed by the attributes.  */
840  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
841    ; /* Nothing to do.  */
842  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
843    (*info->print_address_func) (value, info);
844  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
845    (*info->print_address_func) (value, info);
846  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
847    (*info->fprintf_func) (info->stream, "%ld", (long) value);
848  else
849    (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
850}
851
852/* Keyword print handler.  */
853
854static void
855print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
856	       void *dis_info,
857	       CGEN_KEYWORD *keyword_table,
858	       long value,
859	       unsigned int attrs ATTRIBUTE_UNUSED)
860{
861  disassemble_info *info = (disassemble_info *) dis_info;
862  const CGEN_KEYWORD_ENTRY *ke;
863
864  ke = cgen_keyword_lookup_value (keyword_table, value);
865  if (ke != NULL)
866    (*info->fprintf_func) (info->stream, "%s", ke->name);
867  else
868    (*info->fprintf_func) (info->stream, "???");
869}
870
871/* Default insn printer.
872
873   DIS_INFO is defined as `void *' so the disassembler needn't know anything
874   about disassemble_info.  */
875
876static void
877print_insn_normal (CGEN_CPU_DESC cd,
878		   void *dis_info,
879		   const CGEN_INSN *insn,
880		   CGEN_FIELDS *fields,
881		   bfd_vma pc,
882		   int length)
883{
884  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
885  disassemble_info *info = (disassemble_info *) dis_info;
886  const CGEN_SYNTAX_CHAR_TYPE *syn;
887
888  CGEN_INIT_PRINT (cd);
889
890  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
891    {
892      if (CGEN_SYNTAX_MNEMONIC_P (*syn))
893	{
894	  (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
895	  continue;
896	}
897      if (CGEN_SYNTAX_CHAR_P (*syn))
898	{
899	  (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
900	  continue;
901	}
902
903      /* We have an operand.  */
904      mep_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
905				 fields, CGEN_INSN_ATTRS (insn), pc, length);
906    }
907}
908
909/* Subroutine of print_insn. Reads an insn into the given buffers and updates
910   the extract info.
911   Returns 0 if all is well, non-zero otherwise.  */
912
913static int
914read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
915	   bfd_vma pc,
916	   disassemble_info *info,
917	   bfd_byte *buf,
918	   int buflen,
919	   CGEN_EXTRACT_INFO *ex_info,
920	   unsigned long *insn_value)
921{
922  int status = (*info->read_memory_func) (pc, buf, buflen, info);
923
924  if (status != 0)
925    {
926      (*info->memory_error_func) (status, pc, info);
927      return -1;
928    }
929
930  ex_info->dis_info = info;
931  ex_info->valid = (1 << buflen) - 1;
932  ex_info->insn_bytes = buf;
933
934  *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
935  return 0;
936}
937
938/* Utility to print an insn.
939   BUF is the base part of the insn, target byte order, BUFLEN bytes long.
940   The result is the size of the insn in bytes or zero for an unknown insn
941   or -1 if an error occurs fetching data (memory_error_func will have
942   been called).  */
943
944static int
945print_insn (CGEN_CPU_DESC cd,
946	    bfd_vma pc,
947	    disassemble_info *info,
948	    bfd_byte *buf,
949	    unsigned int buflen)
950{
951  CGEN_INSN_INT insn_value;
952  const CGEN_INSN_LIST *insn_list;
953  CGEN_EXTRACT_INFO ex_info;
954  int basesize;
955
956  /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
957  basesize = cd->base_insn_bitsize < buflen * 8 ?
958                                     cd->base_insn_bitsize : buflen * 8;
959  insn_value = cgen_get_insn_value (cd, buf, basesize);
960
961
962  /* Fill in ex_info fields like read_insn would.  Don't actually call
963     read_insn, since the incoming buffer is already read (and possibly
964     modified a la m32r).  */
965  ex_info.valid = (1 << buflen) - 1;
966  ex_info.dis_info = info;
967  ex_info.insn_bytes = buf;
968
969  /* The instructions are stored in hash lists.
970     Pick the first one and keep trying until we find the right one.  */
971
972  insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
973  while (insn_list != NULL)
974    {
975      const CGEN_INSN *insn = insn_list->insn;
976      CGEN_FIELDS fields;
977      int length;
978      unsigned long insn_value_cropped;
979
980#ifdef CGEN_VALIDATE_INSN_SUPPORTED
981      /* Not needed as insn shouldn't be in hash lists if not supported.  */
982      /* Supported by this cpu?  */
983      if (! mep_cgen_insn_supported (cd, insn))
984        {
985          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
986	  continue;
987        }
988#endif
989
990      /* Basic bit mask must be correct.  */
991      /* ??? May wish to allow target to defer this check until the extract
992	 handler.  */
993
994      /* Base size may exceed this instruction's size.  Extract the
995         relevant part from the buffer. */
996      if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
997	  (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
998	insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
999					   info->endian == BFD_ENDIAN_BIG);
1000      else
1001	insn_value_cropped = insn_value;
1002
1003      if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
1004	  == CGEN_INSN_BASE_VALUE (insn))
1005	{
1006	  /* Printing is handled in two passes.  The first pass parses the
1007	     machine insn and extracts the fields.  The second pass prints
1008	     them.  */
1009
1010	  /* Make sure the entire insn is loaded into insn_value, if it
1011	     can fit.  */
1012	  if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
1013	      (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
1014	    {
1015	      unsigned long full_insn_value;
1016	      int rc = read_insn (cd, pc, info, buf,
1017				  CGEN_INSN_BITSIZE (insn) / 8,
1018				  & ex_info, & full_insn_value);
1019	      if (rc != 0)
1020		return rc;
1021	      length = CGEN_EXTRACT_FN (cd, insn)
1022		(cd, insn, &ex_info, full_insn_value, &fields, pc);
1023	    }
1024	  else
1025	    length = CGEN_EXTRACT_FN (cd, insn)
1026	      (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
1027
1028	  /* Length < 0 -> error.  */
1029	  if (length < 0)
1030	    return length;
1031	  if (length > 0)
1032	    {
1033	      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
1034	      /* Length is in bits, result is in bytes.  */
1035	      return length / 8;
1036	    }
1037	}
1038
1039      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1040    }
1041
1042  return 0;
1043}
1044
1045/* Default value for CGEN_PRINT_INSN.
1046   The result is the size of the insn in bytes or zero for an unknown insn
1047   or -1 if an error occured fetching bytes.  */
1048
1049#ifndef CGEN_PRINT_INSN
1050#define CGEN_PRINT_INSN default_print_insn
1051#endif
1052
1053static int
1054default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1055{
1056  bfd_byte buf[CGEN_MAX_INSN_SIZE];
1057  int buflen;
1058  int status;
1059
1060  /* Attempt to read the base part of the insn.  */
1061  buflen = cd->base_insn_bitsize / 8;
1062  status = (*info->read_memory_func) (pc, buf, buflen, info);
1063
1064  /* Try again with the minimum part, if min < base.  */
1065  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
1066    {
1067      buflen = cd->min_insn_bitsize / 8;
1068      status = (*info->read_memory_func) (pc, buf, buflen, info);
1069    }
1070
1071  if (status != 0)
1072    {
1073      (*info->memory_error_func) (status, pc, info);
1074      return -1;
1075    }
1076
1077  return print_insn (cd, pc, info, buf, buflen);
1078}
1079
1080/* Main entry point.
1081   Print one instruction from PC on INFO->STREAM.
1082   Return the size of the instruction (in bytes).  */
1083
1084typedef struct cpu_desc_list
1085{
1086  struct cpu_desc_list *next;
1087  CGEN_BITSET *isa;
1088  int mach;
1089  int endian;
1090  CGEN_CPU_DESC cd;
1091} cpu_desc_list;
1092
1093int
1094print_insn_mep (bfd_vma pc, disassemble_info *info)
1095{
1096  static cpu_desc_list *cd_list = 0;
1097  cpu_desc_list *cl = 0;
1098  static CGEN_CPU_DESC cd = 0;
1099  static CGEN_BITSET *prev_isa;
1100  static int prev_mach;
1101  static int prev_endian;
1102  int length;
1103  CGEN_BITSET *isa;
1104  int mach;
1105  int endian = (info->endian == BFD_ENDIAN_BIG
1106		? CGEN_ENDIAN_BIG
1107		: CGEN_ENDIAN_LITTLE);
1108  enum bfd_architecture arch;
1109
1110  /* ??? gdb will set mach but leave the architecture as "unknown" */
1111#ifndef CGEN_BFD_ARCH
1112#define CGEN_BFD_ARCH bfd_arch_mep
1113#endif
1114  arch = info->arch;
1115  if (arch == bfd_arch_unknown)
1116    arch = CGEN_BFD_ARCH;
1117
1118  /* There's no standard way to compute the machine or isa number
1119     so we leave it to the target.  */
1120#ifdef CGEN_COMPUTE_MACH
1121  mach = CGEN_COMPUTE_MACH (info);
1122#else
1123  mach = info->mach;
1124#endif
1125
1126#ifdef CGEN_COMPUTE_ISA
1127  {
1128    static CGEN_BITSET *permanent_isa;
1129
1130    if (!permanent_isa)
1131      permanent_isa = cgen_bitset_create (MAX_ISAS);
1132    isa = permanent_isa;
1133    cgen_bitset_clear (isa);
1134    cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
1135  }
1136#else
1137  isa = info->insn_sets;
1138#endif
1139
1140  /* If we've switched cpu's, try to find a handle we've used before */
1141  if (cd
1142      && (cgen_bitset_compare (isa, prev_isa) != 0
1143	  || mach != prev_mach
1144	  || endian != prev_endian))
1145    {
1146      cd = 0;
1147      for (cl = cd_list; cl; cl = cl->next)
1148	{
1149	  if (cgen_bitset_compare (cl->isa, isa) == 0 &&
1150	      cl->mach == mach &&
1151	      cl->endian == endian)
1152	    {
1153	      cd = cl->cd;
1154 	      prev_isa = cd->isas;
1155	      break;
1156	    }
1157	}
1158    }
1159
1160  /* If we haven't initialized yet, initialize the opcode table.  */
1161  if (! cd)
1162    {
1163      const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
1164      const char *mach_name;
1165
1166      if (!arch_type)
1167	abort ();
1168      mach_name = arch_type->printable_name;
1169
1170      prev_isa = cgen_bitset_copy (isa);
1171      prev_mach = mach;
1172      prev_endian = endian;
1173      cd = mep_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
1174				 CGEN_CPU_OPEN_BFDMACH, mach_name,
1175				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
1176				 CGEN_CPU_OPEN_END);
1177      if (!cd)
1178	abort ();
1179
1180      /* Save this away for future reference.  */
1181      cl = xmalloc (sizeof (struct cpu_desc_list));
1182      cl->cd = cd;
1183      cl->isa = prev_isa;
1184      cl->mach = mach;
1185      cl->endian = endian;
1186      cl->next = cd_list;
1187      cd_list = cl;
1188
1189      mep_cgen_init_dis (cd);
1190    }
1191
1192  /* We try to have as much common code as possible.
1193     But at this point some targets need to take over.  */
1194  /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
1195     but if not possible try to move this hook elsewhere rather than
1196     have two hooks.  */
1197  length = CGEN_PRINT_INSN (cd, pc, info);
1198  if (length > 0)
1199    return length;
1200  if (length < 0)
1201    return -1;
1202
1203  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1204  return cd->default_insn_bitsize / 8;
1205}
1206