/*
 *      Interactive disassembler (IDA).
 *      Version 3.05
 *      Copyright (c) 1990-95 by Ilfak Guilfanov.
 *      ALL RIGHTS RESERVED.
 *                              FIDO:   2:5020/209
 *                              E-mail: ig@estar.msk.su
 *
 */


#include "java.hpp"
#include <ieee.h>
#include <diskio.hpp>

//--------------------------------------------------------------------------
uchar debugmode = 0;
//--------------------------------------------------------------------------
static int notify(processor_t::idp_notify msgid, ...) { // Various messages:
  va_list va;
  va_start(va, msgid);

// A well behaving processor module should call invoke_callbacks()
// in his notify() function. If this function returns 0, then
// the processor module should process the notification itself
// Otherwise the code should be returned to the caller:

  int code = invoke_callbacks(HT_IDP, msgid, va);
  if ( code ) return code;

  int retcode = 1;

  switch(msgid) {
    case ph.init:
      inf.mf = 1;       //reverse byte!
      break;

    case ph.newfile:
      if ( inf.filetype != f_LOADER )
        error("Only Java files can be disassembled");
      myBase(va_arg(va, char *));
      inf.lowoff = inf.highoff = BADADDR;
      break;

    case ph.oldfile:
      myBase(NULL);
      break;

    case ph.newprc:
      if(va_arg(va, int) == 1) {   // debug mode
        ph.flag &= ~(PR_DEFNUM | PR_NOCHANGE);
        ph.flag |= PRN_HEX;
        if(inf.margin == 77 && !inf.binSize && !inf.s_showpref) {
          ++inf.s_showpref;
          --debugmode;
        } else ++debugmode;
      } else {                  // normal node
        ph.flag &= ~PR_DEFNUM;
        ph.flag |= (PRN_DEC | PR_NOCHANGE);
        if(debugmode == 0xFF && inf.s_showpref && !inf.binSize &&
           inf.margin == 77)                          inf.s_showpref = 0;
        debugmode = 0;
      }
      break;

    case ph.loader:
      {
        linput_t *li = va_arg(va, linput_t *);
        bool  manual = va_argi(va, bool);
        loader(qlfile(li), manual);
        retcode = 0;
      }
      break;

    default:
      break;
  }
  va_end(va);

  return(retcode);
}

//----------------------------------------------------------------------
static void func_header(func_t *) {}
static void func_footer(func_t *) {}
static bool java_specseg(ea_t ea, uchar)    { java_data(ea); return false; }
//----------------------------------------------------------------------
static asm_t jasmin_asm = {
  AS_COLON | ASH_HEXF3 | ASO_OCTF1 | ASD_DECF0 | AS_ONEDUP | ASB_BINF3,
  UAS_JASMIN,
  "Jasmin assembler",
  0,        // no help screen
  NULL,     // header
  NULL,     // bad instructions
  NULL,     // origin
  NULL,     // end of file

  ";",      // comment string
  '"',      // string delimiter
  '\'',     // char delimiter
  "\"'\\",  // special symbols in char and string constants

  "",         // ascii string directive
  "",         // byte directive
  NULL,       // word directive
  NULL,       // double words
  NULL,       // qwords
  NULL,       // oword  (16 bytes)
  NULL,       // float
  NULL,       // double
  NULL,       // no tbytes
  NULL,       // no packreal
  NULL,     // arrays:
            // #h - header(.byte,.word)
            // #d - size of array
            // #v - value of array elements
  NULL,         //".reserv  %s",  // uninited data (reserve space)
  " = ",        // equ
  NULL,         // seg prefix
  NULL,         // preline for checkarg
  NULL,         // checkarg_atomprefix
  NULL,         // checkarg operations
  NULL,         // XlatAsciiOutput
  NULL,         // a_curip
  func_header,  // func header
  func_footer,  // func footer
  NULL,		// public
  NULL,		// weak
  NULL,		// extrn
  NULL,		// comm
  NULL,		// get_type_name
  NULL,		// align
  '(', ')',	// lbrace, rbrace
  NULL,    // mod
  "&",     // and
  "|",     // or
  "^",     // xor
  "!",     // not
  "<<",    // shl
  ">>",    // shr
  NULL,    // sizeof
};

//----------------------------------------------------------------------
static asm_t java_asm = {
  AS_COLON | ASH_HEXF3 | ASO_OCTF1 | ASD_DECF0 | AS_ONEDUP | ASB_BINF3,
  0,
  "Java hypothetical assembler",
  0,        // no help screen
  NULL,     // header
  NULL,     // bad instructions
  NULL,     // origin
  NULL,     // end of file

  "#",      // comment string
  '"',      // string delimiter
  '\'',     // char delimiter
  "\"'\\",  // special symbols in char and string constants

  "",         // ascii string directive
  "",         // byte directive
  NULL,       // word directive
  NULL,       // double words
  NULL,       // qwords
  NULL,       // oword  (16 bytes)
  NULL,       // float
  NULL,       // double
  NULL,       // no tbytes
  NULL,       // no packreal
  NULL,     // arrays:
            // #h - header(.byte,.word)
            // #d - size of array
            // #v - value of array elements
  NULL,         //".reserv  %s",  // uninited data (reserve space)
  " = ",        // equ
  NULL,         // seg prefix
  NULL,         // preline for checkarg
  NULL,         // checkarg_atomprefix
  NULL,         // checkarg operations
  NULL,         // XlatAsciiOutput
  NULL,         // a_curip
  func_header,  // func header
  func_footer,  // func footer
  NULL,		// public
  NULL,		// weak
  NULL,		// extrn
  NULL,		// comm
  NULL,		// get_type_name
  NULL,		// align
  '(', ')',	// lbrace, rbrace
  NULL,    // mod
  "&",     // and
  "|",     // or
  "^",     // xor
  "!",     // not
  "<<",    // shl
  ">>",    // shr
  NULL,    // sizeof
};

//-----------------------------------------------------------------------

static asm_t *asms[] = { &jasmin_asm, &java_asm, NULL };

static char *RegNames[] = { "vars" , "optop", "frame", "cs", "ds" };

static char *shnames[] =
{
  "java",
//  "_javaPC",
  NULL
};
static char *lnames[] =
{
  "java",
//  "java full (IBM PC, debug mode)",
  NULL
};

//--------------------------------------------------------------------------
static uchar retcode_0[] = { j_ret },
             retcode_1[] = { j_ireturn },
             retcode_2[] = { j_lreturn },
             retcode_3[] = { j_freturn },
             retcode_4[] = { j_dreturn },
             retcode_5[] = { j_areturn },
             retcode_6[] = { j_return  },
             retcode_7[] = { j_wide, j_ret };

static bytes_t retcodes[] = {
 { sizeof(retcode_0), retcode_0 },
 { sizeof(retcode_1), retcode_1 },
 { sizeof(retcode_2), retcode_2 },
 { sizeof(retcode_3), retcode_3 },
 { sizeof(retcode_4), retcode_4 },
 { sizeof(retcode_5), retcode_5 },
 { sizeof(retcode_6), retcode_6 },
 { sizeof(retcode_7), retcode_7 },
 { 0, NULL }
};

//-----------------------------------------------------------------------
//      Processor Definition
//-----------------------------------------------------------------------
processor_t LPH =
{
  IDP_INTERFACE_VERSION,
  PLFM_JAVA,
  PRN_DEC | PR_RNAMESOK | PR_NOCHANGE | PR_NO_SEGMOVE,
  8,                    // 8 bits in a byte for code segments
  8,                    // 8 bits in a byte for other segments

  shnames,
  lnames,

  asms,

  notify,

  header,
  footer,

  segstart,
  segend,

  NULL,

  ana,
  emu,

  out,
  outop,
  java_data,
  NULL,          //  cmp_opnd,  // 0 if not cmp 1 if eq
  can_have_type, //(&op)  int : 1 -yes 0-no

  qnumber(RegNames),            // Number of registers
  RegNames,                     // Regsiter names
  NULL,         // get abstract register

  0,          // Number of register files
  NULL,                         // Register file names
  NULL,                         // Register descriptions
  NULL,                         // Pointer to CPU registers

  rVcs,rVds,
  0,                            // size of a segment register
  rVcs,rVds,

  NULL,                         // No known code start sequences
  retcodes,

  0,j_last,
  Instructions,
  NULL,         //isFarJump or Call
  NULL,         //  Offset Generation Function. Usually NULL.
  0,            // size of tbyte
  ieee_realcvt,
  {0,7,15,0},   //real width
  NULL,         // is this instruction switch
  gen_map_file, //generate map-file
  get_ref_addr, //extract address from a string
  NULL,         //is_sp_based
  NULL,         //create_func_frame
  NULL,         //get_func_retsize
  NULL,         //gen_stkvar_def
  java_specseg, //out special segments
  j_ret         //icode_return
};
