/* Simulation code for the CR16 processor.
   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
   Contributed by M Ranga Swami Reddy <MR.Swami.Reddy@nsc.com>

   This file is part of GDB, the GNU debugger.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program. If not, see <http://www.gnu.org/licenses/>.  */


#include "config.h"
#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include "ansidecl.h"
#include "opcode/cr16.h"

static void write_header PARAMS ((void));
static void write_opcodes PARAMS ((void));
static void write_template PARAMS ((void));

int
main (int argc, char *argv[])
{
  if ((argc > 1) && (strcmp (argv[1],"-h") == 0))
    write_header();
  else if ((argc > 1) && (strcmp (argv[1],"-t") == 0))
    write_template ();
  else
    write_opcodes();
  return 0;
}


static void
write_header ()
{
  int i = 0; 

  /* Start searching from end of instruction table.  */
  const inst *instruction = &cr16_instruction[NUMOPCODES - 1];

  /* Loop over instruction table until a full match is found.  */
  for ( ; i < NUMOPCODES; i++)
  {
   printf("void OP_%X_%X PARAMS ((void));\t\t/* %s */\n",cr16_instruction[i].match, (32 - cr16_instruction[i].match_bits), cr16_instruction[i].mnemonic);
  }
}


/* write_template creates a file all required functions, 
   ready to be filled out.  */

static void
write_template ()
{
  int i = 0,j, k, flags;

  printf ("#include \"cr16_sim.h\"\n");
  printf ("#include \"simops.h\"\n\n");

  for ( ; i < NUMOPCODES; i++)
    {
      if (cr16_instruction[i].size != 0)
{
  printf("/* %s */\nvoid\nOP_%X_%X ()\n{\n",cr16_instruction[i].mnemonic,cr16_instruction[i].match,(32 - cr16_instruction[i].match_bits));
  
  /* count operands.  */
  j = 0;
  for (k=0;k<5;k++)
    {
      if (cr16_instruction[i].operands[k].op_type == dummy)
                break;
              else
                j++;
    }
  switch (j)
    {
    case 0:
      printf ("printf(\"   %s\\n\");\n",cr16_instruction[i].mnemonic);
      break;
    case 1:
      printf ("printf(\"   %s\\t%%x\\n\",OP[0]);\n",cr16_instruction[i].mnemonic);
      break;
    case 2:
      printf ("printf(\"   %s\\t%%x,%%x\\n\",OP[0],OP[1]);\n",cr16_instruction[i].mnemonic);
      break;
    case 3:
      printf ("printf(\"   %s\\t%%x,%%x,%%x\\n\",OP[0],OP[1],OP[2]);\n",cr16_instruction[i].mnemonic);
      break;
    default:
      fprintf (stderr,"Too many operands: %d\n",j);
    }
  printf ("}\n\n");
}
    }
}


long Opcodes[512];
static int curop=0;

check_opcodes( long op)
{
  int i;

  for (i=0;i<curop;i++)
    if (Opcodes[i] == op)
      fprintf(stderr,"DUPLICATE OPCODES: %x\n",op);
}


static void
write_opcodes ()
{
  int i = 0, j = 0, k;
  
  /* write out opcode table.  */
  printf ("#include \"cr16_sim.h\"\n");
  printf ("#include \"simops.h\"\n\n");
  printf ("struct simops Simops[] = {\n");
  
  for (i = NUMOPCODES-1; i >= 0; --i)
    {
      if (cr16_instruction[i].size != 0)
{
           printf ("  { \"%s\", %ld, %d, %d, %d, \"OP_%X_%X\", OP_%X_%X, ", 
                    cr16_instruction[i].mnemonic, cr16_instruction[i].size, 
                    cr16_instruction[i].match_bits, cr16_instruction[i].match,
                     cr16_instruction[i].flags, ((BIN(cr16_instruction[i].match, cr16_instruction[i].match_bits))>>(cr16_instruction[i].match_bits)),
             (32 - cr16_instruction[i].match_bits),
                     ((BIN(cr16_instruction[i].match, cr16_instruction[i].match_bits))>>(cr16_instruction[i].match_bits)), (32 - cr16_instruction[i].match_bits));
      
  j = 0;
  for (k=0;k<5;k++)
    {
      if (cr16_instruction[i].operands[k].op_type == dummy)
                break;
              else
                j++;
    }
  printf ("%d, ",j);
  
  j = 0;
  for (k=0;k<4;k++)
    {
      int optype = cr16_instruction[i].operands[k].op_type;
      int shift = cr16_instruction[i].operands[k].shift;
      if (j == 0)
        printf ("{");
      else
        printf (", ");
      printf ("{");
      printf ("%d,%d",optype, shift);
      printf ("}");
      j = 1;
   }
 if (j)
  printf ("}");
 printf ("},\n");
        }
    }
  printf (" { \"NULL\",1,8,0,0,\"OP_0_20\",OP_0_20,0,{0,0,0}},\n};\n");
}
