/*
 *      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 "78k_0.hpp"
#include <ints.hpp>
#include <diskio.hpp>

#define far
#define near

inline void OutReg(int rgnum)
{
  out_register(ph.regNames[rgnum]);
}


//----------------------------------------------------------------------
static int near OutVarName(op_t &x, int iscode, int relative)
{
  char *ptr;
  ushort addr = x.addr;
  if(relative)
  {
    addr += (ushort)cmd.ip;
    addr += cmd.size;           // ig: this is tested only for 6809
  }

  ulong toea = toEA((iscode || relative) ? codeSeg(addr,x.n) : dataSeg_op(x.n), addr);

  if((ptr=get_name_expr(cmd.ea+x.offb, x.n, toea, addr)) != NULL)
  {
    //вывод имен переменных и меток перехода
    OutLine(ptr);
//    char tt[100];
//    qsnprintf(tt, sizeof(tt), "VARNAME %s\n", ptr);
//    msg(tt);

    return(1);
  }
  return(0);
}

//----------------------------------------------------------------------
bool outop(op_t &x)
{
  switch(x.type)
  {
  case o_void:
    return 0;


  case o_reg:
     if(x.Prepost & FTR_SCOBKI) out_symbol('[');

     //Вывод регистра по номеру в регистре
     OutReg(x.reg);

     if(x.Prepost & FTR_PLUS) out_symbol('+');

     if(x.Prepost & FTR_VALUE)
       //Вывод данных(тип o_imm)
       OutValue(x, OOFW_IMM );

     if(x.Prepost & FTR_REGISTR)
       //Вывод регистра по номеру в регистре
       out_keyword( ph.regNames[x.Registr] );


     if(x.Prepost & FTR_SCOBKI) out_symbol(']');
    break;

  case o_phrase:
      {
        char tmp[100];
        qsnprintf(tmp, sizeof(tmp), "br%d", x.Prepost);
        out_keyword(tmp);
      }
    break;

  case o_bit:
     {
       switch(x.TypeOperand)
       {
        case TBO_SADDR:
        case TBO_SFR:
            if(!OutVarName(x, 1, 0) )
               OutValue(x, OOF_ADDR | OOFW_16);
            out_symbol('.');
            //Ичем название бита по указанному адрессу
            if( !nec_find_ioport_bit(x.addr, x.value) )
                 //Вывод данных(тип o_imm)
                 OutValue(x, OOFW_IMM);
           break;

        case TBO_A:
               OutLine( "A." );
               //Вывод данных(тип o_imm)
               OutValue(x, OOFW_IMM);
            break;

        case TBO_PSW:
             OutLine( "PSW." );
             //Вывод данных(тип o_imm)
             OutValue(x, OOFW_IMM);
            break;

        case TBO_HL:
            out_symbol('[');
            OutReg(rHL);
            out_symbol(']');
            out_symbol('.');
            //Вывод данных(тип o_imm)
            OutValue(x, OOFW_IMM);

            break;

       }//       switch(x.regmode)
     }

    break;

  case o_imm:
   if(x.Form & 0x1)  out_symbol('!');
   else  out_symbol('#');

   //Вывод данных(тип o_imm)
   OutValue(x, OOFW_IMM );
    break;

  case o_mem:
   //выводит имя переменной из памяти(например byte_98)

   //Вывод имени переменной
   if(!OutVarName(x, 1, 0) )
    //Вывод данных
    OutValue(x, OOF_ADDR | OOFW_16);
    break;

  case o_displ:
    break;

  case o_near:
       {
        ulong v;
        const char *ptr;

            if(x.Form & 0x1) out_symbol('[');

            if(x.Form & 0x2) out_symbol('!');

            //Получить линейный адресс
	    v = toEA(cmd.cs,x.addr);
            ptr = get_name_expr(cmd.ea+x.offb, x.n, v, x.addr);
            if( ptr == NULL )
            {
	      //Вывести значение
              OutValue(x, OOF_ADDR | OOF_NUMBER | OOFW_16);
              QueueMark(Q_noName, cmd.ea);
	    }
	    else
	     OutLine(ptr);

            if(x.Form & 0x1) out_symbol(']');
         }
    break;

  default:
    warning("out: %a: bad optype %d", cmd.ip, x.type);
    break;
  }

  return(1);
}

//----------------------------------------------------------------------
void out(void) {
  char buf[MAXSTR];

   init_output_buffer(buf, sizeof(buf)); // setup the output pointer
   OutMnem();                            // output instruction mnemonics

   out_one_operand(0);                   // output the first operand

    //Вывод операнда
   if(cmd.Op2.type != o_void) {
     out_symbol(',');//вывод разделителя между операндами
     //если неуказан флаг UAS_NOSPA ставим пробел
     if(!(ash.uflag & UAS_NOSPA)) OutChar(' ');
     out_one_operand(1);
   }

   if(cmd.Op3.type != o_void) {
     out_symbol(',');
     if(!(ash.uflag & UAS_NOSPA)) OutChar(' ');
     out_one_operand(2);
   }

   if(isVoid(cmd.ea, uFlag, 0)) OutImmChar(cmd.Op1);
   if(isVoid(cmd.ea, uFlag, 1)) OutImmChar(cmd.Op2);
   if(isVoid(cmd.ea, uFlag, 2)) OutImmChar(cmd.Op3);

   term_output_buffer();

   gl_comm = 1;
   MakeLine(buf);

}

//--------------------------------------------------------------------------
void header(void) {
  gen_cmt_line("Processor:       %s [%s]", device[0] ? device : inf.procName, deviceparams);
  gen_cmt_line("Target assebler: %s", ash.name);
  if (ash.header != NULL )
    for (const char **ptr=ash.header; *ptr != NULL; ptr++ ) MakeLine(*ptr, 0);
}

//--------------------------------------------------------------------------
void segstart(ea_t /*ea*/)
{
}

//--------------------------------------------------------------------------
void footer(void)
{
  char buf[MAXSTR];
  char *const end = buf + sizeof(buf);
  if (ash.end != NULL)
  {
    MakeNull();
    char *ptr = tag_addstr(buf, end, COLOR_ASMDIR, ash.end);
    char name[MAXSTR];
    if (get_colored_name(BADADDR, inf.beginEA, name, sizeof(name)) != NULL)
    {
      register int i = strlen(ash.end);
      do APPCHAR(ptr, end, ' '); while(++i < 8);
      APPEND(ptr, end, name);
    }
    MakeLine(buf);
  } else gen_cmt_line("end of file");
}

//--------------------------------------------------------------------------


