Top secrets sources NedoPC pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

/* asmlist.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
/*                                                                           */
/* AS Port                                                                   */
/*                                                                           */
/* Generate Listing                                                          */
/*                                                                           */
/*****************************************************************************/

#include "stdinc.h"
#include <string.h>
#include <assert.h>
#include "be_le.h"
#include "strutil.h"
#include "dynstr.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmif.h"
#include "asmcode.h"
#include "asmlist.h"

/* NOTE: Keep this to a value of the form 8*n, so the overall 'prefix'
         in front of the source line in the listing is a multiple of 8.
         This way, Tabs in the source do not break up: */


#define LISTLINE_PREFIX_TOTAL 40

static unsigned SystemListLen8, SystemListLen16, SystemListLen32;

static as_dynstr_t list_buf;

static int max_pc_len;

/*!------------------------------------------------------------------------
 * \fn     as_list_set_max_pc(LargeWord max_pc)
 * \brief  compute maximum width of PC field in listing
 * ------------------------------------------------------------------------ */


void as_list_set_max_pc(LargeWord max_pc)
{
  String tmp;

  as_snprintf(tmp, sizeof(tmp), "%1.*lllu", ListRadixBase, max_pc);
  max_pc_len = strlen(tmp);
  if (max_pc_len > 8)
    max_pc_len = 8;
}

/*!------------------------------------------------------------------------
 * \fn     MakeList()
 * \brief  generate listing for one line, including generated code
 * ------------------------------------------------------------------------ */


void MakeList(const char *pSrcLine)
{
  String h2, Tmp;
  Word EffLen, Gran = Granularity();
  Boolean ThisDoLst;

  EffLen = CodeLen * Gran;

#if 0
  fprintf(stderr, "[%s] WasIF %u WasMACRO %u DoLst %u\n", OpPart.Str, WasIF, WasMACRO, DoLst);
#endif
  if (WasIF)
    ThisDoLst = !!(DoLst & eLstMacroExpIf);
  else if (WasMACRO)
    ThisDoLst = !!(DoLst & eLstMacroExpMacro);
  else
  {
    if (!IfAsm && (!(DoLst & eLstMacroExpIf)))
      ThisDoLst = False;
    else
      ThisDoLst = !!(DoLst & eLstMacroExpRest);
  }

  if (!ListToNull && ThisDoLst && (ListMask & 1) && !IFListMask())
  {
    LargeWord ListPC;
    size_t sum_len;
    int inc_and_line_length;
    const char *p_pc_and_colon_format = ListPCZeroPad ? "%0*.*lllu %c" : "%*.*lllu %c";

    /* Zeilennummer / Programmzaehleradresse: */

    as_sdprintf(&list_buf, "");
    if (MaxIncDepth > 0)
    {
      int digits = (MaxIncDepth > 99) ? 3 : ((MaxIncDepth > 9) ? 2 : 1);

      if (IncDepth > 0)
      {
        as_snprintf(Tmp, sizeof(Tmp), IntegerFormat, IncDepth);
        as_sdprcatf(&list_buf, "(%*s)", digits, Tmp);
      }
      else
        as_sdprcatf(&list_buf, Blanks(2 + digits));
    }
    if (ListMask & ListMask_LineNums)
    {
      DecString(h2, sizeof(h2), CurrLine, 0);
      as_sdprcatf(&list_buf, "%5s/", h2);
    }
    inc_and_line_length = strlen(list_buf.p_str);
    ListPC = EProgCounter() - CodeLen;
    as_sdprcatf(&list_buf, p_pc_and_colon_format,
                max_pc_len, ListRadixBase, ListPC,
                Retracted? 'R' : ':');
    sum_len = strlen(list_buf.p_str);
    assert(sum_len + 2 < LISTLINE_PREFIX_TOTAL);

    /* Extrawurst in Listing ? */

    if (*ListLine)
    {
      size_t rem_space = LISTLINE_PREFIX_TOTAL - sum_len - 2;
      int num_pad = rem_space - strlen(ListLine);

      /* If too long, truncate and add ..
         If shorter than space, pad with spaces: */


      if (num_pad < 0)
        ListLine[rem_space - 2] = '\0';
      as_sdprcatf(&list_buf, " %s%s %s", ListLine,
                  (num_pad >= 0) ? Blanks(num_pad) : "..", pSrcLine);
      WrLstLine(list_buf.p_str);
      *ListLine = '\0';
    }

    /* Code ausgeben */

    else
    {
      Word Index = 0, CurrListGran, SystemListLen;
      Boolean First = True;
      LargeInt ThisWord;

      /* Not enough code to display even on 16/32 bit word?
         Then start dumping bytes right away: */


      if (EffLen < ActListGran)
      {
        CurrListGran = 1;
        SystemListLen = SystemListLen8;
      }
      else
      {
        CurrListGran = ActListGran;
        switch (CurrListGran)
        {
          case 4:
            SystemListLen = SystemListLen32;
            break;
          case 2:
            SystemListLen = SystemListLen16;
            break;
          default:
            SystemListLen = SystemListLen8;
        }
      }

      if (TurnWords && (Gran != ActListGran) && (1 == ActListGran))
        DreheCodes();

      do
      {
        /* If not the first code line, prepend blanks to fill up space below line number: */

        if (!First)
        {
          if (inc_and_line_length > 0)
            as_sdprintf(&list_buf, "%*s", inc_and_line_length, "");
          else
            as_sdprintf(&list_buf, "");
          as_sdprcatf(&list_buf, p_pc_and_colon_format,
                      max_pc_len, ListRadixBase, ListPC,
                      Retracted? 'R' : ':');
          sum_len = strlen(list_buf.p_str);
        }
        do
        {
          /* We checked initially there is at least one full word,
             and we check after every word whether there is another
             full one: */


          if ((Index < EffLen) && !DontPrint)
          {
            switch (CurrListGran)
            {
              case 4:
                ThisWord = DAsmCode[Index >> 2];
                break;
              case 2:
                ThisWord = WAsmCode[Index >> 1];
                break;
              default:
                ThisWord = BAsmCode[Index];
            }
            as_sdprcatf(&list_buf, " %0*.*lllu", (int)SystemListLen, (int)ListRadixBase, ThisWord);
          }
          else
            as_sdprcatf(&list_buf, "%*s", (int)(1 + SystemListLen), "");

          /* advance pointers & keep track of # of characters printed */

          ListPC += (Gran == CurrListGran) ? 1 : CurrListGran;
          Index += CurrListGran;
          sum_len += 1 + SystemListLen;

          /* Less than one full word remaining? Then switch to dumping bytes. */

          if (Index + CurrListGran > EffLen)
          {
            CurrListGran = 1;
            SystemListLen = SystemListLen8;
          }
        }
        while (sum_len + 1 + SystemListLen < LISTLINE_PREFIX_TOTAL);

        /* If first line, pad to max length and append source line */

        if (First)
          as_sdprcatf(&list_buf, "%*s%s", (int)(LISTLINE_PREFIX_TOTAL - sum_len), "", pSrcLine);
        WrLstLine(list_buf.p_str);
        First = False;
      }
      while ((Index < EffLen) && !DontPrint);

      if (TurnWords && (Gran != ActListGran) && (1 == ActListGran))
        DreheCodes();
    }
  }
}

/*!------------------------------------------------------------------------
 * \fn     asmlist_init(void)
 * \brief  setup stuff at program startup
 * ------------------------------------------------------------------------ */


void asmlist_init(void)
{
  String Dummy;

  as_dynstr_ini(&list_buf, STRINGSIZE);

  SysString(Dummy, sizeof(Dummy), 0xff, ListRadixBase, 0, False, HexStartCharacter, SplitByteCharacter);
  SystemListLen8 = strlen(Dummy);
  SysString(Dummy, sizeof(Dummy), 0xffffu, ListRadixBase, 0, False, HexStartCharacter, SplitByteCharacter);
  SystemListLen16 = strlen(Dummy);
  SysString(Dummy, sizeof(Dummy), 0xfffffffful, ListRadixBase, 0, False, HexStartCharacter, SplitByteCharacter);
  SystemListLen32 = strlen(Dummy);
}