home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / nasm20b / nasm_src / exprasm.c < prev    next >
C/C++ Source or Header  |  1993-01-19  |  11KB  |  396 lines

  1. /* ---------------------------------------------------------------------- */
  2. /*                   Copyright (C) 1991 by Natürlich!                     */
  3. /*                      This file is copyrighted!                         */
  4. /*                Refer to the documentation for details.                 */
  5. /* ---------------------------------------------------------------------- */
  6. #include "defines.h"
  7. #include "nasm.h"
  8. #include "debug.h"
  9. #include "labels.h"
  10. #include  NMALLOC_H
  11. #include "exprfast.h"
  12. #include OSBIND
  13. #include "code.h"
  14. #include "op.h"
  15.  
  16. extern byte    scrtab[];
  17. extern int     runnable;
  18. int            _in_doteq;
  19.  
  20. #if ! DORECLAIM
  21. #define  expr_tryfree( p)
  22. #endif
  23.  
  24. #if ! VERSION
  25. /* ---------------------------------------------------------- */
  26. /* There is this unfortunate problems with labels. They might */
  27. /* be defined anywhere and with nasm65 even unknown (linked   */
  28. /* from elsewhere). That leads to problems when generating    */
  29. /* code. REFER and DREFER (pronounce REEFER and DEEREEFER)    */
  30. /*    "Don't fear the REFER" (Blue Oyster Cult (almost))      */
  31. /* build up lists of places, where labels have been used and  */
  32. /* whether the label had a value then.                        */
  33. /*    drefer means define and refer                           */
  34. /* ---------------------------------------------------------- */
  35. /* I NEVER USE XREFs                                          */
  36. /* I NEVER LOOK AT THE SYMBOLTABLE AT THE END OF THE LISTING  */
  37. /* WHY SHOULD I WASTE MEMORY FOR FEATURES I DON'T WANT        */
  38. /* Therefore I don't need drefer just refer. That also means  */
  39. /* I can compress the "ref" to 8 bytes. Now if I could get */
  40. /* rid of that one pointer.                                   */
  41. /* ---------------------------------------------------------- */
  42. void refer( l, ex)
  43. label huge  *l;
  44. expr huge   *ex;
  45. {
  46.    register ref huge    *p = ref_alloc();
  47.    extern buffer huge   *bp;
  48.  
  49.    ENTER("refer");
  50.    IMESS("label @$%lX", (lword) l, 4);
  51.    p->ref   = ex;       /* Note expression that needs fixing  */
  52.    p->line  = bp->line; /* (*) */
  53.    p->next  = l->refs;  /* put it in the first slot...        */
  54.    l->refs  = p;
  55.    l->type |= L_REF;
  56.    LEAVE();
  57. }
  58. #endif
  59.  
  60. /* ---------------------------------------------------------- */
  61. /* Recursively copy expression (deep copy or shallow copy ?)  */
  62. /* and if needed refer as of yet unkown labels.               */
  63. /* code looks very nice, but can conceivably use some optimi- */
  64. /* zation.                                                    */
  65. /* ---------------------------------------------------------- */
  66. expr *copyexpr( p)
  67. register expr huge  *p;
  68. {
  69.    ENTER("copyexpr");
  70.    if( ! p)
  71.    {
  72.       LEAVE();
  73.       return( 0);
  74.    }
  75.  
  76.    {
  77.       register expr huge *q = exp_alloc();
  78.  
  79. #if EXPRSIZE != 24 || PHILOSOPHICAL_PROBLEM
  80.       bcopy( p, q, (lword) sizeof( expr));
  81. #else
  82.       *((lword huge *) q)++ = *((lword huge *) p)++;  /* label          */
  83.       *((lword huge *) q)++ = *((lword huge *) p)++;  /* no & val       */
  84.       *((lword huge *) q)   = *(lword huge *) p;      /* aux & op & fix */
  85.       (char huge *) q -= 8;
  86.       (char huge *) p -= 8;
  87. #endif
  88.       if( q->label)                        /* Tell label that we need a  */
  89.          refer( q->label, q);              /* fix (if we need a fix)     */
  90.       if( q->l = copyexpr( p->l))
  91.          q->l->zonk.t = q;
  92.       if( q->r = copyexpr( p->r))
  93.          q->r->zonk.t = q;
  94.       LEAVE();
  95.       return( q);
  96.    }
  97. }
  98.  
  99. #if ! VERSION
  100. /* ----------------------------------------------------------- */
  101. /*        Create an s_expression node by planting a value      */
  102. /*                   (could be a label as well)                */
  103. /* ----------------------------------------------------------- */
  104. expr *ival_pl( value)
  105. word  value;
  106. {
  107.    expr huge   *p = exp_alloc();
  108.  
  109.    ENTER("ival_pl");
  110.    MESS("Wolf! Right here and now!");
  111.    p->val = value;
  112.    LEAVE();
  113.    return( p);
  114. }
  115. #endif
  116.  
  117. expr *lval_pl( name)
  118. char huge   *name;
  119. {
  120.    register expr huge   *p = exp_alloc();
  121.    register label huge  *q;
  122.  
  123.    ENTER("lval_pl");
  124.    MESS("Wolf! Right here and now!");
  125.    if( q = find_label( name))
  126.    {
  127.       if( q->refs)
  128.       {
  129.          p->label = q;
  130.          refer( q, p);
  131.       }
  132.       else
  133.          p->val = q->val;
  134.       IMESS("p->op %u", (lword) p->op, 2);
  135.       p->op  = ((q->type & L_PC)   ? O_PCREL : 0) |
  136.                ((q->type & L_ZERO) ? O_ZEROP : 0);
  137.    }
  138.    else
  139.       if( runnable && _in_doteq)
  140.          enter_elabel( name, ival_pl( __pc), L_NORMAL);
  141.       else
  142.       {
  143.          p->label = enter_flabel( name, p);
  144.          if( ! runnable)
  145.             p->op = O_PCREL;       /* cause fwd then is PC rel */
  146.       }
  147.    LEAVE();
  148.    return( p);
  149. }
  150.  
  151. /* ----------------------------------------------------------- */
  152. /*     Create an s_expression node by planting an operation    */
  153. /*   There is still a bug in this as expressions like foo+2+3  */
  154. /*            are not simplified if foo is unvalued            */
  155. /* ----------------------------------------------------------- */
  156. expr *op_pl( op, left, rite)
  157. register int         op;
  158. register expr huge   *left, huge *rite;
  159. {
  160.    register int   lop;
  161.    int            rop;
  162.  
  163.    ENTER("op_pl");
  164.    if( (lop = left->op) == (O_PCREL | (O_MSB & O_LSB)) ||
  165.        (rite && (rop = rite->op) == (O_PCREL | (O_MSB & O_LSB))))
  166.    {
  167.       nerror("You can't calculate with a short PC relative expression");
  168.       return( left);
  169.    }
  170.    if( valued( left))         /* if left is value */
  171.    {
  172.       if( ! rite || valued( rite))
  173.       {
  174.          MESS("Just calcing it");
  175.          do_calc( left, rite, op);                      /* calc it */
  176.          expr_tryfree( rite);
  177.          IMESS("After do_calc %ld", (lword) lop, 4);
  178.          LEAVE();
  179.          return( left);
  180.       }
  181.    }
  182.    else
  183.       if( rite && valued( rite))
  184.          switch( lop)
  185.          {
  186.             case O_ADD :
  187.                if( is_addsub( op))
  188.                {
  189.                   if( valued( left->l))
  190.                      do_calc( left->l, rite, op);
  191.                   else
  192.                      if( valued( left->r))
  193.                         do_calc( left->r, rite, op);
  194.                      else
  195.                         break;
  196.                   expr_tryfree( rite);
  197.                   return( left);
  198.                }
  199.                break;
  200.                
  201.             case O_SUB :
  202.                if( op == O_ADD)
  203.                {
  204.                   if( valued( left->l))
  205.                      do_calc( left->l, rite, O_ADD);
  206.                   else
  207.                      if( valued( left->r))
  208.                         do_calc( left->r, rite, O_SUB);
  209.                      else
  210.                         break;
  211.                }
  212.                else
  213.                   if( op == O_SUB)
  214.                   {
  215.                      if( valued( left->l))
  216.                         do_calc( left->l, rite, O_SUB);
  217.                      else
  218.                         if( valued( left->r))
  219.                            do_calc( left->r, rite, O_ADD);
  220.                         else
  221.                            break;
  222.                   }
  223.                   else
  224.                      break;
  225.                expr_tryfree( rite);
  226.                return( left);
  227.  
  228.             case O_MUL :
  229.                if( op == O_MUL)
  230.                {
  231.                   if( valued( left->l))
  232.                      do_calc( left->l, rite, op);
  233.                   else
  234.                      if( valued( left->r))
  235.                         do_calc( left->r, rite, op);
  236.                      else
  237.                         break;
  238.                   expr_tryfree( rite);
  239.                   return( left);
  240.                }
  241.                break;
  242.  
  243.             case O_DIV :
  244.                if( op == O_DIV)
  245.                {
  246.                   if( valued( left->l))
  247.                      do_calc( left->l, rite, op);
  248.                   else
  249.                      if( valued( left->r))
  250.                         do_calc( left->r, rite, O_MUL);
  251.                      else
  252.                         break;
  253.                   expr_tryfree( rite);
  254.                   return( left);
  255.                }
  256.          }
  257.  
  258.    MESS("Creating a node");
  259.    {
  260.       register expr huge   *p;
  261.  
  262.       if( rite && valued( rite) && rite->val == 1)
  263.       {
  264.          if( is_addsub( op))
  265.          {
  266.             p    = rite;
  267.             rite = 0;
  268.             op   = op == O_ADD ? O_INC : O_DEC;
  269.             goto asusual;
  270.          }
  271.       }
  272.       p = exp_alloc();
  273.       
  274. asusual:
  275.       lop &= O_PCREL;
  276.       rop &= O_PCREL;
  277.       switch( op)
  278.       {
  279.          case O_INC :
  280.          case O_DEC :
  281.          case O_MSB :
  282.          case O_LSB :
  283.             p->op = lop;
  284.             break;
  285.    
  286.          case O_ADD :
  287.             p->op = lop ^ rop;
  288.             break;
  289.    
  290.          case O_SUB :
  291.          {
  292.             static char what[] = { 0, 0, 0x80, 0 };
  293.             
  294.             p->op = what[ ((lop != 0) << 1) | (rop != 0) ];
  295.          }
  296.       }
  297.          
  298.       if( (left->op | (rite ? rite->op : 0)) & O_ZEROP)
  299.          switch( op)
  300.          {
  301.             case O_SUB :
  302.                if( rite->op & O_ZEROP)
  303.                   break;
  304.             case O_ADD :
  305.                if( ! p->op)
  306.             case O_INC :
  307.             case O_DEC :
  308.             case O_LSB :
  309.                   p->op |= O_ZEROP;
  310.          }
  311.          
  312.       p->op        |= op;
  313.       p->l          = left;
  314.       left->fix     = 0;         /* for macros */
  315.       left->zonk.t  = p;
  316.       if( p->r = rite)
  317.          rite->zonk.t = p;
  318.       LEAVE();
  319.       return( p);
  320.    }
  321. }
  322.  
  323. #if ! VERSION
  324. lexpr *lex_pl( s, ex)
  325. expr huge   *ex;
  326. char        *s;
  327. {
  328.    register lexpr    *p = lex_alloc();
  329.  
  330.    ENTER("lex_pl");
  331.    IMESS("planting string $%8.8lX", (lword) s, 4);
  332.    IMESS("    with expr   $%8.8lX", (lword) ex, 4);
  333.    p->string = s;
  334.    p->expr   = ex;
  335.    p->next   = 0;
  336.    LEAVE();
  337.    return( p);
  338. }
  339. #endif
  340.  
  341. lexpr *slex_ch( l, r)
  342. register lexpr huge  *l, huge *r;
  343. {
  344.    ENTER("slex_ch");
  345.    IMESS("Chaining $%8.8lX", (lword) r, 4);
  346.    IMESS("      to $%8.8lX", (lword) l, 4);
  347.    l->next = r;
  348.    LEAVE();
  349.    return( l);
  350. }
  351.  
  352.  
  353. int   lex_cnt( l)
  354. register lexpr huge  *l;
  355. {
  356.    register int   i = 0;
  357.  
  358.    ENTER("lex_cnt");
  359.    while( l)
  360.    {
  361.       i++;
  362.       l = l->next;
  363.    }
  364.    LEAVE();
  365.    return( i);
  366. }
  367.  
  368. /* ---------------------------------------------------------- */
  369. /*                       Should be a macro                    */
  370. /*                   Error checking elsewhere                 */
  371. /* ---------------------------------------------------------- */
  372. lexpr *lex_get( l, no)
  373. register lexpr huge  *l;
  374. register word  no;
  375. {
  376.    ENTER("lex_get");
  377.    while( l && no--)
  378.       l = l->next;
  379.    IMESS("Returning L-expression @$%lx", (lword) l, 4);
  380.    LEAVE();
  381.    return( l);
  382. }
  383.  
  384. /* ---------------------------------------------------------- */
  385. /*                   Mallocer for lexpressions                */
  386. /* make this mallocing scheme a macro sometime in the future..*/
  387. /*                                                            */
  388. /*   (Keeping the fingers crossed that this is faster than a) */
  389. /*                       (simple malloc)                      */
  390. /* ---------------------------------------------------------- */
  391.    make_mallocer( lexpr, LEXPMAX, lex_alloc);
  392.  
  393. /* (*) This isn't correct and fails when branches are made out of
  394.        a buffer (like macro) or the buffer was changed.
  395. */
  396.