Subversion Repositories pentevo

Rev

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

  1. /* decpseudo.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS                                                                        */
  6. /*                                                                           */
  7. /* Commonly Used VAX/PDP-11 Pseudo Instructions                              */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. /*****************************************************************************
  12.  * Includes
  13.  *****************************************************************************/
  14.  
  15. #include "stdinc.h"
  16. #include <string.h>
  17.  
  18. #include "strutil.h"
  19. #include "asmdef.h"
  20. #include "asmpars.h"
  21. #include "asmerr.h"
  22. #include "errmsg.h"
  23.  
  24. #include "decpseudo.h"
  25.  
  26. /*****************************************************************************
  27.  * Global Types
  28.  *****************************************************************************/
  29.  
  30. /*!------------------------------------------------------------------------
  31.  * \fn     decode_dec_packed(Word index)
  32.  * \brief  encode number or decimal string in packed decimal format
  33.  * ------------------------------------------------------------------------ */
  34.  
  35. static void append_digit(Byte digit, Boolean *p_half)
  36. {
  37.   if (*p_half)
  38.   {
  39.     BAsmCode[CodeLen] |= (digit & 15);
  40.     CodeLen++;
  41.     switch (ListGrans[ActPC])
  42.     {
  43.       case 1:
  44.         break;
  45.       case 2:
  46.         if (!(CodeLen & 1))
  47.           WAsmCode[(CodeLen / 2) - 1] = ((Word)BAsmCode[CodeLen - 1]) << 8 | BAsmCode[CodeLen - 2];
  48.         break;
  49.     }
  50.   }
  51.   else
  52.   {
  53.     SetMaxCodeLen(CodeLen + 1);
  54.     BAsmCode[CodeLen] = (digit & 15) << 4;
  55.   }
  56.   *p_half = !*p_half;
  57. }
  58.  
  59. void decode_dec_packed(Word index)
  60. {
  61.   TempResult value;
  62.   const char *p_str = NULL;
  63.   char tmp_dec_str[33];
  64.  
  65.   UNUSED(index);
  66.  
  67.   if (!ChkArgCnt(1, 2))
  68.     return;
  69.  
  70.   as_tempres_ini(&value);
  71.   EvalStrExpression(&ArgStr[1], &value);
  72.   switch (value.Typ)
  73.   {
  74.     case TempNone:
  75.       break;
  76.     case TempInt:
  77.       as_snprintf(tmp_dec_str, sizeof(tmp_dec_str), "%lld", value.Contents.Int);
  78.       p_str = tmp_dec_str;
  79.       goto writeout;
  80.     case TempString:
  81.       p_str = value.Contents.str.p_str;
  82.       goto writeout;
  83.     case TempFloat:
  84.       WrStrErrorPos(ErrNum_StringOrIntButFloat, &ArgStr[1]);
  85.       break;
  86.     default:
  87.       WrStrErrorPos(ErrNum_ExpectIntOrString, &ArgStr[1]);
  88.       break;
  89.     writeout:
  90.     {
  91.       size_t num_digits = 0, l;
  92.       Boolean half, negative;
  93.  
  94.       switch (*p_str)
  95.       {
  96.         case '-':
  97.           negative = True;
  98.           p_str++;
  99.           break;
  100.         case '+':
  101.           negative = False;
  102.           p_str++;
  103.           break;
  104.         default:
  105.           negative = False;
  106.       }
  107.  
  108.       l = strlen(p_str);
  109.       half = False;
  110.       /* leading zero padding digit is not counted into num_digits: */
  111.       if (!(l & 1))
  112.         append_digit(0, &half);
  113.       for (; *p_str; p_str++)
  114.       {
  115.         if (!isdigit(*p_str))
  116.         {
  117.           WrStrErrorPos(ErrNum_InvalidDecDigit, &ArgStr[1]);
  118.           CodeLen = 0; half = False;
  119.           break;
  120.         }
  121.         append_digit(*p_str - '0', &half);
  122.         if (++num_digits > 31)
  123.         {
  124.           WrStrErrorPos(ErrNum_DecStringTooLong, &ArgStr[1]);
  125.           CodeLen = 0; half = False;
  126.           break;
  127.         }
  128.       }
  129.       if (CodeLen || half)
  130.       {
  131.         append_digit(negative ? 13 : 12, &half);
  132.         if (2 == ArgCnt)
  133.           EnterIntSymbol(&ArgStr[2], num_digits, SegNone, False);
  134.       }
  135.     }
  136.   }
  137.  
  138.   as_tempres_free(&value);
  139. }
  140.