Subversion Repositories pentevo

Rev

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

  1. /* asmlist.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS Port                                                                   */
  6. /*                                                                           */
  7. /* Generate Listing                                                          */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <string.h>
  13. #include <assert.h>
  14. #include "be_le.h"
  15. #include "strutil.h"
  16. #include "dynstr.h"
  17. #include "asmdef.h"
  18. #include "asmsub.h"
  19. #include "asmif.h"
  20. #include "asmcode.h"
  21. #include "asmlist.h"
  22.  
  23. /* NOTE: Keep this to a value of the form 8*n, so the overall 'prefix'
  24.          in front of the source line in the listing is a multiple of 8.
  25.          This way, Tabs in the source do not break up: */
  26.  
  27. #define LISTLINE_PREFIX_TOTAL 40
  28.  
  29. static unsigned SystemListLen8, SystemListLen16, SystemListLen32;
  30.  
  31. static as_dynstr_t list_buf;
  32.  
  33. static int max_pc_len;
  34.  
  35. /*!------------------------------------------------------------------------
  36.  * \fn     as_list_set_max_pc(LargeWord max_pc)
  37.  * \brief  compute maximum width of PC field in listing
  38.  * ------------------------------------------------------------------------ */
  39.  
  40. void as_list_set_max_pc(LargeWord max_pc)
  41. {
  42.   String tmp;
  43.  
  44.   as_snprintf(tmp, sizeof(tmp), "%1.*lllu", ListRadixBase, max_pc);
  45.   max_pc_len = strlen(tmp);
  46.   if (max_pc_len > 8)
  47.     max_pc_len = 8;
  48. }
  49.  
  50. /*!------------------------------------------------------------------------
  51.  * \fn     MakeList()
  52.  * \brief  generate listing for one line, including generated code
  53.  * ------------------------------------------------------------------------ */
  54.  
  55. void MakeList(const char *pSrcLine)
  56. {
  57.   String h2, Tmp;
  58.   Word EffLen, Gran = Granularity();
  59.   Boolean ThisDoLst;
  60.  
  61.   EffLen = CodeLen * Gran;
  62.  
  63. #if 0
  64.   fprintf(stderr, "[%s] WasIF %u WasMACRO %u DoLst %u\n", OpPart.Str, WasIF, WasMACRO, DoLst);
  65. #endif
  66.   if (WasIF)
  67.     ThisDoLst = !!(DoLst & eLstMacroExpIf);
  68.   else if (WasMACRO)
  69.     ThisDoLst = !!(DoLst & eLstMacroExpMacro);
  70.   else
  71.   {
  72.     if (!IfAsm && (!(DoLst & eLstMacroExpIf)))
  73.       ThisDoLst = False;
  74.     else
  75.       ThisDoLst = !!(DoLst & eLstMacroExpRest);
  76.   }
  77.  
  78.   if (!ListToNull && ThisDoLst && (ListMask & 1) && !IFListMask())
  79.   {
  80.     LargeWord ListPC;
  81.     size_t sum_len;
  82.     int inc_and_line_length;
  83.     const char *p_pc_and_colon_format = ListPCZeroPad ? "%0*.*lllu %c" : "%*.*lllu %c";
  84.  
  85.     /* Zeilennummer / Programmzaehleradresse: */
  86.  
  87.     as_sdprintf(&list_buf, "");
  88.     if (MaxIncDepth > 0)
  89.     {
  90.       int digits = (MaxIncDepth > 99) ? 3 : ((MaxIncDepth > 9) ? 2 : 1);
  91.  
  92.       if (IncDepth > 0)
  93.       {
  94.         as_snprintf(Tmp, sizeof(Tmp), IntegerFormat, IncDepth);
  95.         as_sdprcatf(&list_buf, "(%*s)", digits, Tmp);
  96.       }
  97.       else
  98.         as_sdprcatf(&list_buf, Blanks(2 + digits));
  99.     }
  100.     if (ListMask & ListMask_LineNums)
  101.     {
  102.       DecString(h2, sizeof(h2), CurrLine, 0);
  103.       as_sdprcatf(&list_buf, "%5s/", h2);
  104.     }
  105.     inc_and_line_length = strlen(list_buf.p_str);
  106.     ListPC = EProgCounter() - CodeLen;
  107.     as_sdprcatf(&list_buf, p_pc_and_colon_format,
  108.                 max_pc_len, ListRadixBase, ListPC,
  109.                 Retracted? 'R' : ':');
  110.     sum_len = strlen(list_buf.p_str);
  111.     assert(sum_len + 2 < LISTLINE_PREFIX_TOTAL);
  112.  
  113.     /* Extrawurst in Listing ? */
  114.  
  115.     if (*ListLine)
  116.     {
  117.       size_t rem_space = LISTLINE_PREFIX_TOTAL - sum_len - 2;
  118.       int num_pad = rem_space - strlen(ListLine);
  119.  
  120.       /* If too long, truncate and add ..
  121.          If shorter than space, pad with spaces: */
  122.  
  123.       if (num_pad < 0)
  124.         ListLine[rem_space - 2] = '\0';
  125.       as_sdprcatf(&list_buf, " %s%s %s", ListLine,
  126.                   (num_pad >= 0) ? Blanks(num_pad) : "..", pSrcLine);
  127.       WrLstLine(list_buf.p_str);
  128.       *ListLine = '\0';
  129.     }
  130.  
  131.     /* Code ausgeben */
  132.  
  133.     else
  134.     {
  135.       Word Index = 0, CurrListGran, SystemListLen;
  136.       Boolean First = True;
  137.       LargeInt ThisWord;
  138.  
  139.       /* Not enough code to display even on 16/32 bit word?
  140.          Then start dumping bytes right away: */
  141.  
  142.       if (EffLen < ActListGran)
  143.       {
  144.         CurrListGran = 1;
  145.         SystemListLen = SystemListLen8;
  146.       }
  147.       else
  148.       {
  149.         CurrListGran = ActListGran;
  150.         switch (CurrListGran)
  151.         {
  152.           case 4:
  153.             SystemListLen = SystemListLen32;
  154.             break;
  155.           case 2:
  156.             SystemListLen = SystemListLen16;
  157.             break;
  158.           default:
  159.             SystemListLen = SystemListLen8;
  160.         }
  161.       }
  162.  
  163.       if (TurnWords && (Gran != ActListGran) && (1 == ActListGran))
  164.         DreheCodes();
  165.  
  166.       do
  167.       {
  168.         /* If not the first code line, prepend blanks to fill up space below line number: */
  169.  
  170.         if (!First)
  171.         {
  172.           if (inc_and_line_length > 0)
  173.             as_sdprintf(&list_buf, "%*s", inc_and_line_length, "");
  174.           else
  175.             as_sdprintf(&list_buf, "");
  176.           as_sdprcatf(&list_buf, p_pc_and_colon_format,
  177.                       max_pc_len, ListRadixBase, ListPC,
  178.                       Retracted? 'R' : ':');
  179.           sum_len = strlen(list_buf.p_str);
  180.         }
  181.         do
  182.         {
  183.           /* We checked initially there is at least one full word,
  184.              and we check after every word whether there is another
  185.              full one: */
  186.  
  187.           if ((Index < EffLen) && !DontPrint)
  188.           {
  189.             switch (CurrListGran)
  190.             {
  191.               case 4:
  192.                 ThisWord = DAsmCode[Index >> 2];
  193.                 break;
  194.               case 2:
  195.                 ThisWord = WAsmCode[Index >> 1];
  196.                 break;
  197.               default:
  198.                 ThisWord = BAsmCode[Index];
  199.             }
  200.             as_sdprcatf(&list_buf, " %0*.*lllu", (int)SystemListLen, (int)ListRadixBase, ThisWord);
  201.           }
  202.           else
  203.             as_sdprcatf(&list_buf, "%*s", (int)(1 + SystemListLen), "");
  204.  
  205.           /* advance pointers & keep track of # of characters printed */
  206.  
  207.           ListPC += (Gran == CurrListGran) ? 1 : CurrListGran;
  208.           Index += CurrListGran;
  209.           sum_len += 1 + SystemListLen;
  210.  
  211.           /* Less than one full word remaining? Then switch to dumping bytes. */
  212.  
  213.           if (Index + CurrListGran > EffLen)
  214.           {
  215.             CurrListGran = 1;
  216.             SystemListLen = SystemListLen8;
  217.           }
  218.         }
  219.         while (sum_len + 1 + SystemListLen < LISTLINE_PREFIX_TOTAL);
  220.  
  221.         /* If first line, pad to max length and append source line */
  222.  
  223.         if (First)
  224.           as_sdprcatf(&list_buf, "%*s%s", (int)(LISTLINE_PREFIX_TOTAL - sum_len), "", pSrcLine);
  225.         WrLstLine(list_buf.p_str);
  226.         First = False;
  227.       }
  228.       while ((Index < EffLen) && !DontPrint);
  229.  
  230.       if (TurnWords && (Gran != ActListGran) && (1 == ActListGran))
  231.         DreheCodes();
  232.     }
  233.   }
  234. }
  235.  
  236. /*!------------------------------------------------------------------------
  237.  * \fn     asmlist_init(void)
  238.  * \brief  setup stuff at program startup
  239.  * ------------------------------------------------------------------------ */
  240.  
  241. void asmlist_init(void)
  242. {
  243.   String Dummy;
  244.  
  245.   as_dynstr_ini(&list_buf, STRINGSIZE);
  246.  
  247.   SysString(Dummy, sizeof(Dummy), 0xff, ListRadixBase, 0, False, HexStartCharacter, SplitByteCharacter);
  248.   SystemListLen8 = strlen(Dummy);
  249.   SysString(Dummy, sizeof(Dummy), 0xffffu, ListRadixBase, 0, False, HexStartCharacter, SplitByteCharacter);
  250.   SystemListLen16 = strlen(Dummy);
  251.   SysString(Dummy, sizeof(Dummy), 0xfffffffful, ListRadixBase, 0, False, HexStartCharacter, SplitByteCharacter);
  252.   SystemListLen32 = strlen(Dummy);
  253. }
  254.