/*
 *      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_0s.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) out_symbol('[');
	  //Вывод регистра по номеру в регистре
          OutReg(x.reg);
          if(x.xmode)
          {
            out_symbol('+');
            OutValue(x, OOF_ADDR | OOF_NUMBER | OOFW_8);
          }
	  if(x.prepost) out_symbol(']');
    break;

  case o_phrase:
       OutLine(ph.regNames[x.reg]);
    break;

  case o_bit:
     {
//       char txt[100];

       switch(x.regmode)
       {
        case SADDR:
        case 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 A:
               OutLine( "A." );
               //Вывод данных(тип o_imm)
               OutValue(x, OOFW_IMM);
            break;

        case PSW:
             OutLine( "PSW." );
             //Вывод данных(тип o_imm)
             OutValue(x, OOFW_IMM);
            break;

        case HL:
            out_symbol('[');
            OutReg(rHL);
            out_symbol(']');
            out_symbol('.');
            //Вывод данных(тип o_imm)
            OutValue(x, OOFW_IMM);

            break;

        case CY:
            OutLine( "CY" );
            break;

       }//       switch(x.regmode)
     }
    break;

  case o_imm:
      if(x.addr16) out_symbol('!');
      //Вывод символа
      else out_symbol('#');
      //Вывод данных(тип o_imm)
      OutValue(x, OOFW_IMM );
    break;

  case o_mem: //2
	{
	  //выводит имя переменной из памяти(например byte_98)

	  //Вывод имени переменной
          if(!OutVarName(x, 1, 0) )
             //Вывод данных
             OutValue(x, OOF_ADDR | OOFW_16);
	}

    break;


  case o_near:
	  {
	    ulong v;
            const char *ptr;

            if(x.form) 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) 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");
}

//--------------------------------------------------------------------------


