home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 1 / crawlyvol1.bin / program / compiler / nasm20b / nasm_src / expr.c < prev    next >
Text File  |  1993-01-19  |  20KB  |  622 lines

  1. /* ---------------------------------------------------------------------- */
  2. /*                   Copyright (C) 1991 by Natuerlich!                    */
  3. /*                      This file is copyrighted!                         */
  4. /*                Refer to the documentation for details.                 */
  5. /* ---------------------------------------------------------------------- */
  6. #include "defines.h"
  7.  
  8. #include "nasm.h"
  9. #include "debug.h"
  10. #include "labels.h"
  11. #include NMALLOC_H
  12. #include OSBIND
  13. #include "code.h"
  14. #define _EXPR_ 1
  15. #include "exprfast.h"
  16. #include "op.h"
  17. #include "ldebug.h"
  18.  
  19. #if VERSION
  20. ref huge    *rp;
  21. expr huge   *ep;
  22. lexpr huge  *lp;
  23. #endif
  24.  
  25. #if DEBUG
  26. # define xreturn   \
  27.     LEAVE();       \
  28.     return
  29. #else
  30. #  define xreturn   return
  31. #endif
  32.  
  33. exp_m huge  *ex_h;
  34.  
  35. #if ! LINKER
  36. unsigned    branch_line;
  37. #endif
  38.  
  39. #if ! DORECLAIM
  40. # define          expr_tryfree( x)
  41. #endif
  42.  
  43. /* ---------------------------------------------------------- */
  44. /*   Entrefern von den der referenz list. Ist mal ein Label   */
  45. /*   mit ner value versehen worden, kann die ref abgehakt     */
  46. /*   werden. Danach brauch dieses label nie wieder 'ne ref    */
  47. /* ---------------------------------------------------------- */
  48. void entrefer( p)
  49. label huge  *p;
  50. {
  51.    ref huge             *q;
  52.    register expr huge   *r;
  53.  
  54.    POINTER_CHECK( p);
  55.    ENTER("entrefer");
  56.    for( q = p->refs; q ; q = q->next)
  57.    {
  58.  
  59.       POINTER_CHECK( q);
  60.       (r = q->ref)->val = p->val;   /* init expression */
  61.       POINTER_CHECK( r);
  62.       r->label = 0;
  63. #if DEBUG
  64.       dump_expr( r);
  65. #endif
  66. #if ! LINKER
  67.       branch_line = q->line;
  68. #else
  69.       INTEGRITY_CHECK();
  70. #endif
  71.       if( r)
  72.          recalc( r);
  73.    }
  74.    p->refs = 0;
  75.    LEAVE();
  76. }
  77.  
  78. #if ! LINKER
  79. # define xe_pcrel( x)  ! runnable && e_pcrel( x)
  80. extern int  runnable;
  81. static char fwd_loss[] = "label already known as PC-relative";
  82. #else
  83. # define xe_pcrel       e_pcrel
  84. #endif
  85.  
  86. /* ---------------------------------------------------------- */
  87. /* Jaja, mal wat in deutsch. Falls ein Label endlich einen    */
  88. /* Wert bekommen hat und inner ref ein entry auf eine expr    */
  89. /* pointed, dann wird versucht von da aus soviel wie möglich  */
  90. /* von unten nach oben auszuwerten. Hat alles geklappt, dann  */
  91. /* kann man endlich die s-expr dahin schreiben, wo sie eigen- */
  92. /* lich längst sein sollte (Backpatching).                    */
  93. /* Da wir übrigens für jeden Scheiß einen eigenen Mallocer    */
  94. /* haben ist es eigentlich kein Problem in NASM65 einen       */
  95. /* GarbageCollector einzubauen. Das wärs noch!!               */
  96. /* For our befuddled english-speaking readers. The various    */
  97. /* MESS messages are gibberish.                               */
  98. /* ---------------------------------------------------------- */
  99. void recalc( p)
  100. register expr huge *p;
  101. {
  102.    register fix huge  *f;
  103.    register byte huge *q;
  104.  
  105.    ENTER("recalc");
  106.    for(;;)
  107.    {
  108. #if DEBUG
  109.       dump_expr( p);
  110. #endif
  111.       if( ! p->fix)
  112.          goto nofix;
  113.  
  114.       f = p->zonk.fixp;
  115.       POINTER_CHECK( f);
  116.       switch( p->fix)       /* Mmmh sind wir schon so weit ?? */
  117.       {
  118.          case FIX_NOTHING:
  119.             LEAVE();
  120.             return;
  121.  
  122.          case FIX_WCODE  :
  123.             MESS("Preferring the (1) wonderful");
  124.             q = __program + f->poof.block->index + f->index;
  125.             POINTER_CHECK( q);
  126.             adpoke( q, p->val);   /* pack den Wert rein */
  127.             LEAVE();
  128.             return;
  129.  
  130.          case FIX_DCODE  :
  131.             MESS("Preferring the wonderful");
  132.             q = __program + f->poof.block->index + f->index;
  133.             POINTER_CHECK( q);
  134.             adbyte( q, p->val);   /* pack den Wert rein */
  135.             LEAVE();
  136.             return;
  137.  
  138.          case FIX_BRANCH  :
  139.          {
  140.             register sword  i;
  141.  
  142.             MESS("The worx");
  143.             i = p->val - p->aux;
  144. #if ! LINKER
  145.             if( i < -128 || i > 127)
  146.                nberror("Branch too long", branch_line);
  147. #else
  148.             if( i < -128 || i > 127)
  149.                nerror("Branch too long");
  150. #endif
  151.             q = __program + f->poof.block->index + f->index;
  152.             POINTER_CHECK( q);
  153.             apoke( q, i);       /* pack den Wert rein */
  154.             LEAVE();
  155.             return;
  156.          }
  157.  
  158.          case FIX_ZCODE  :
  159.          case FIX_SZCODE :
  160.             MESS("Admiring very small wonders");
  161.             q = __program + f->poof.block->index + f->index;
  162.             POINTER_CHECK( q);
  163.             if( xe_pcrel( p))
  164.                cure_patch( f->imm, p->aux);
  165.             if( p->fix == FIX_ZCODE)
  166.             {
  167.                MESS("+");
  168.                apoke( q, p->val);               /* pack den Wert rein */
  169.             }
  170.             else
  171.             {
  172.                extern byte    scrtab[];
  173.  
  174.                MESS("*");
  175.                apoke( q, scrtab[ p->val]);   /* pack'n Wert rein */
  176.             }
  177.             MESS("-");
  178.             LEAVE();
  179.             return;
  180.  
  181.          case FIX_LABEL :
  182.          {
  183.             register label huge  *q = f->poof.label;
  184.  
  185.             MESS("Doing the strange first");
  186.             IMESS("p->t @$%lX", (lword) p->zonk.t, 4);
  187.             q->val = p->val;                    /* ok mach's dem */
  188. #if ! LINKER
  189.             if( ! runnable && (q->type & L_EQU))
  190.             {
  191.                nserror( fwd_loss, q->name);
  192.                goto skip;
  193.             }
  194. #endif
  195.             entrefer( q);
  196. skip:
  197.             LEAVE();
  198.             return;
  199.          }
  200.  
  201.          default :
  202.             nierror("Invalid fix request");
  203.  
  204. nofix:
  205.          case 0 :
  206.             MESS("doing gods work 'ere, yessir!");
  207.             p = p->zonk.t;
  208.          {
  209.             register expr huge *l = p->l,
  210.                           huge *r = p->r;
  211.  
  212.             if( unvalued( l) || (r && unvalued( r)))  /* if L or R */
  213.             {
  214.                LEAVE();
  215.                return;                       /* USED TO BE A BREAK */
  216.             }
  217.             do_calc( l, r, p->op & O_BITS);
  218.             p->val  = l->val;
  219.             if( is_lsbmsb( p->op))
  220.                p->aux = l->aux;
  221.             p->op = l->op;
  222.             p->l  = p->r = 0;       /* leave kids to the garbage man */
  223.          }
  224.       }
  225.    }
  226. }
  227.  
  228. /* ---------------------------------------------------------- */
  229. /*  Do the expression calculation that needs to be done for   */
  230. /*  statements like     LDA #>FOO&[$FF+NMIEN]/2               */
  231. /*  (never mind the sense...)                                 */
  232. /* ---------------------------------------------------------- */
  233. void  do_calc( l, r, op)
  234. register expr huge   *l, huge *r;
  235. int                  op;
  236. {
  237. #if ! LINKER
  238.    extern int  runnable;
  239. #endif
  240.    static char err[]      = "Can't use arithemtic w/relocatable address",
  241.                div_zero[] = "You can't / or \\ with zero";
  242.  
  243.    ENTER("do_calc");
  244.    POINTER_CHECK( l);
  245.    POINTER_CHECK( r);
  246. #if ! LINKER
  247.    if( runnable)
  248.       if( r)
  249.          switch( op)
  250.          {
  251.             case O_ADD : l->val += r->val; xreturn;
  252.             case O_SUB : l->val -= r->val; xreturn;
  253.             case O_MUL : l->val *= r->val; xreturn;
  254.             case O_DIV : if( ! r->val)
  255.                             nerror( div_zero);
  256.                          else
  257.                             l->val /= r->val;
  258.                          xreturn;
  259.             case O_MOD : if( ! r->val)
  260.                             nerror( div_zero);
  261.                          else
  262.                             l->val %= r->val;
  263.                          xreturn;
  264.             case O_AND : l->val &= r->val; xreturn;
  265.             case O_EOR : l->val ^= r->val; xreturn;
  266.             case O_OR  : l->val |= r->val; xreturn;
  267.             case O_EQ  : l->val  = l->val == r->val; xreturn;
  268.             case O_BAND: l->val  = l->val && r->val; xreturn;
  269.             case O_BOR : l->val  = l->val || r->val; xreturn;
  270.             case O_NEQ : l->val  = l->val != r->val; xreturn;
  271.             case O_GEQ : l->val  = l->val >= r->val; xreturn;
  272.             case O_LEQ : l->val  = l->val <= r->val; xreturn;
  273.             case O_GT  : l->val  = l->val >  r->val; xreturn;
  274.             case O_LT  : l->val  = l->val <  r->val; xreturn;
  275.          }
  276.       else
  277.          switch( op)
  278.          {
  279.             case O_INC : l->val++; xreturn;
  280.             case O_DEC : l->val--; xreturn;
  281.             case O_BNOT: l->val   = ! l->val; xreturn;
  282.             case O_MIN : l->val   = - l->val; xreturn;
  283.             case O_LSB : l->aux   = l->val;        /* stands for LSB O_LT */
  284.                          l->val  &= 0xFF;
  285.                          xreturn;
  286.             case O_MSB : l->aux   = l->val;        /* stands for MSB O_GT */
  287.             {
  288.                byte huge   *p = (byte huge *) &l->val;
  289. #if ! BIGENDIAN
  290.                p[1] = *p;
  291.                *p   = 0;
  292. #else
  293.                *p   = p[1];
  294.                p[1] = 0;
  295. #endif
  296.                xreturn;
  297.             }
  298.          }
  299. #endif
  300.    if( r)
  301.       switch( (e_pcrel( l) << 1) | e_pcrel( r))
  302.       {
  303.          case 0 :                        /* value  op  value  ->  value */
  304.             MESS("valü op valü");
  305.             switch( op)
  306.             {
  307.                case O_ADD : l->val += r->val; goto iszerop;
  308.                case O_SUB : l->val -= r->val; 
  309.                             if( r->val & O_ZEROP)
  310.                                goto isvalue;  
  311.                             goto issame;
  312.                case O_MUL : l->val *= r->val; goto isvalue;
  313.                case O_DIV : if( ! r->val)
  314.                                nerror( div_zero);
  315.                             else
  316.                                l->val /= r->val;
  317.                             goto isvalue;
  318.                case O_MOD : if( ! r->val)
  319.                                nerror( div_zero);
  320.                             else
  321.                                l->val %= r->val;
  322.                             goto isvalue;
  323.                case O_AND : l->val &= r->val; goto isvalue;
  324.                case O_EOR : l->val ^= r->val; goto isvalue;
  325.                case O_OR  : l->val |= r->val; goto isvalue;
  326.                case O_EQ  : l->val  = l->val == r->val; goto isvalue;
  327.                case O_BAND: l->val  = l->val && r->val; goto isvalue;
  328.                case O_BOR : l->val  = l->val || r->val; goto isvalue;
  329.                case O_NEQ : l->val  = l->val != r->val; goto isvalue;
  330.                case O_GEQ : l->val  = l->val >= r->val; goto isvalue;
  331.                case O_LEQ : l->val  = l->val <= r->val; goto isvalue;
  332.                case O_GT  : l->val  = l->val >  r->val; goto isvalue;
  333.                case O_LT  : l->val  = l->val <  r->val; goto isvalue;
  334.             }
  335.  
  336.          case 1 :                        /*  value  op  reladr  ->  ??? */
  337.             MESS("valü op reladr");
  338.             switch( op)
  339.             {
  340.                case O_ADD : l->val += r->val; goto ispcrel;
  341.                case O_SUB :
  342.                case O_MUL :
  343.                case O_DIV :
  344.                case O_MOD :
  345.                case O_AND :
  346.                case O_EOR :
  347.                case O_OR  : nerror( err);   l->val = 0; goto isvalue;
  348.                case O_EQ  : l->val  = l->val == r->val; goto isvalue;
  349.                case O_BAND: l->val  = l->val && r->val; goto isvalue;
  350.                case O_BOR : l->val  = l->val || r->val; goto isvalue;
  351.                case O_NEQ : l->val  = l->val != r->val; goto isvalue;
  352.                case O_GEQ : l->val  = l->val >= r->val; goto isvalue;
  353.                case O_LEQ : l->val  = l->val <= r->val; goto isvalue;
  354.                case O_GT  : l->val  = l->val >  r->val; goto isvalue;
  355.                case O_LT  : l->val  = l->val <  r->val; goto isvalue;
  356.             }
  357.  
  358.          case 2 :                        /*  reladr  op  value  ->  ??? */
  359.             MESS("reladr op valü");
  360.             switch( op)
  361.             {
  362.                case O_ADD : l->val += r->val; goto ispcrel;
  363.                case O_SUB : l->val -= r->val; goto ispcrel;
  364.                case O_MUL :
  365.                case O_DIV :
  366.                case O_MOD :
  367.                case O_AND :
  368.                case O_EOR :
  369.                case O_OR  : nerror( err);   l->val = 0; goto isvalue;
  370.                case O_EQ  : l->val  = l->val == r->val; goto isvalue;
  371.                case O_BAND: l->val  = l->val && r->val; goto isvalue;
  372.                case O_BOR : l->val  = l->val || r->val; goto isvalue;
  373.                case O_NEQ : l->val  = l->val != r->val; goto isvalue;
  374.                case O_GEQ : l->val  = l->val >= r->val; goto isvalue;
  375.                case O_LEQ : l->val  = l->val <= r->val; goto isvalue;
  376.                case O_GT  : l->val  = l->val >  r->val; goto isvalue;
  377.                case O_LT  : l->val  = l->val <  r->val; goto isvalue;
  378.             }
  379.  
  380.          case 3 :
  381.             MESS("reladr op reladr");
  382.             switch( op)
  383.             {
  384.                case O_SUB : l->val -= r->val; goto isvalue;
  385.                case O_ADD :
  386.                case O_MUL :
  387.                case O_DIV :
  388.                case O_MOD :
  389.                case O_AND :
  390.                case O_EOR :
  391.                case O_OR  : nerror( err);   l->val = 0; goto isvalue;
  392.                case O_EQ  : l->val  = l->val == r->val; goto isvalue;
  393.                case O_BAND: l->val  = l->val && r->val; goto isvalue;
  394.                case O_BOR : l->val  = l->val || r->val; goto isvalue;
  395.                case O_NEQ : l->val  = l->val != r->val; goto isvalue;
  396.                case O_GEQ : l->val  = l->val >= r->val; goto isvalue;
  397.                case O_LEQ : l->val  = l->val <= r->val; goto isvalue;
  398.                case O_GT  : l->val  = l->val >  r->val; goto isvalue;
  399.                case O_LT  : l->val  = l->val <  r->val; goto isvalue;
  400.             }
  401.          default:
  402.             nierror("Algorithmic fuck up!");
  403.       }
  404.    else
  405.       if( e_pcrel( l))
  406.          switch( op)
  407.          {
  408.             case O_INC : l->val++; goto ispcrel;
  409.             case O_DEC : l->val--; goto ispcrel;
  410.             case O_BNOT:
  411.             case O_MIN : l->val   = 0;
  412.                          nerror( err);
  413.                          goto isvalue;
  414.  
  415.             case O_LSB : l->aux   = l->val;        
  416.                          l->val  &= 0xFF;
  417.                          goto ispcrel;
  418.             case O_MSB : l->aux   = l->val;        
  419.             {
  420.                          byte huge  *p = (byte huge *) &l->val;
  421. #if ! BIGENDIAN
  422.                          p[1] = *p;
  423.                          *p   = 0;
  424. #else
  425.                          *p   = p[1];
  426.                          p[1] = 0;
  427. #endif
  428.                          goto ispcrel;
  429.             }
  430.          }
  431.       else
  432.          switch( op)
  433.          {
  434.             case O_INC   : l->val++; goto issame;
  435.             case O_DEC   : l->val--; goto issame;
  436.             case O_BNOT  : l->val = ! l->val; goto isvalue;
  437.             case O_MIN   : nerror( err); l->val = 0; goto isvalue;
  438.             case O_LSB   : l->val  &= 0xFF; goto issame;
  439.             case O_MSB   :                           
  440.             {
  441.                byte huge  *p = (byte huge *) &l->val;
  442. #if ! BIGENDIAN
  443.                p[1] = *p;
  444.                *p   = 0;
  445. #else
  446.                *p   = p[1];
  447.                p[1] = 0;
  448. #endif
  449.             }
  450.             goto isvalue;
  451.          }
  452.  
  453. ispcrel:
  454.    l->op = O_PCREL | op;
  455.    xreturn;
  456.    
  457. iszerop:
  458.    l->op |= r->op & O_ZEROP;
  459.  
  460. issame:
  461.    l->op = (l->op & O_BITS) | op;
  462.    xreturn;
  463.    
  464. isvalue:   
  465.    l->op = op;
  466.    xreturn;
  467. }
  468.  
  469. /* ---------------------------------------------------------- */
  470. /*                   Mallocer for the reflist                 */
  471. /*                                                            */
  472. /*   (Keeping the fingers crossed that this is faster than a) */
  473. /*                       (simple malloc)                      */
  474. /*       For added speed put the first "if" into a #define    */
  475. /* ---------------------------------------------------------- */
  476.    make_mallocer( ref, REFMAX, ref_alloc);
  477.  
  478. /* ---------------------------------------------------------- */
  479. /*                   Mallocer for expressions                 */
  480. /*                                                            */
  481. /*   (Keeping the fingers crossed that this is faster than a) */
  482. /*                       (simple malloc)                      */
  483. /* ---------------------------------------------------------- */
  484.  
  485. expr *sexp_alloc()
  486. {
  487.    register exp_m huge   *p;
  488.    extern word          _a_expr, _m_expr;
  489.    extern lword         _s_expr;
  490.  
  491. #if STATISTICS
  492.    _a_expr++;
  493. #endif
  494.    if( (p = ex_h) && p->free--)
  495.       return( p->tab++);
  496.  
  497. #if STATISTICS
  498.    _m_expr++;
  499.    _s_expr = sizeof(exp_m) + EXPMAX * sizeof( expr);
  500. #endif
  501.    p         = (exp_m huge *) nmalloc( (long) sizeof(exp_m) +
  502.                                          EXPMAX * sizeof( expr));
  503.    p->free   = (int) EXPMAX - 1;
  504.    p->tab    = (expr huge *) ((char huge *) p + sizeof( exp_m));
  505.    bzero(  p->tab, (long) EXPMAX * sizeof( expr));    /* Clear memory */
  506.    p->before = (exp_m huge *) ex_h;
  507.    ex_h      = p;
  508.    return( p->tab++);
  509. }
  510.  
  511. /* ---------------------------------------------------------- */
  512. /* Try to free the expression. This will work easily in cases */
  513. /* like  LDA #2  or STA WSYNC (where WSYNC is already known   */
  514. /* Unless we are going to use GC we have to do this 'cause I  */
  515. /* expect approx. 2 expr/line (makes 60 bytes per line)       */
  516. /*    We clear it so that it can be properly reused again     */
  517. /* ---------------------------------------------------------- */
  518. #if DORECLAIM
  519. void    expr_tryfree( e)
  520. register expr huge   *e;
  521. {
  522.    extern word _efrees, _erfrees;
  523.  
  524. #if STATISTICS
  525.    _efrees++;
  526. #endif
  527.    if( e == (ex_h->tab - 1))
  528.    {
  529.       register lword huge  *q = (lword huge *) e;
  530. #if LINKER
  531. # if EXPRSIZE != 26
  532.       bzero( q, (long) sizeof( expr));
  533. # else
  534. #  if ! LATEPLUSPLUS /* like the good book says/be quick or dead [DLR] */
  535.       *(word huge *)q = (word) (*q++ = *q++ = *q++ = *q++ = *q++ = *q++ = 0);
  536. #  else
  537.       {
  538.          register lword  zero = 0;
  539.  
  540.          *q++ = zero; *q++ = zero; *q++ = zero; *q++ = zero;
  541.          *q++ = zero; *q++ = zero; *(word huge *)q = 0;
  542.       }
  543. #  endif
  544. # endif
  545. #else
  546. # if EXPRSIZE != 24 || LATEPLUSPLUS
  547.       bzero( q, (long) sizeof( expr));
  548. # else
  549. #  if ! LATEPLUSPLUS
  550.       *q = *q++ = *q++ = *q++ = *q++ = *q++ = 0;
  551. #  else
  552.       {
  553.          register lword  zero = 0;
  554.  
  555.          *q++ = zero; *q++ = zero; *q++ = zero; *q++ = zero;
  556.          *q++ = zero; *q++ = zero;
  557.       }
  558. #  endif
  559. # endif
  560. #endif
  561.       --ex_h->tab;
  562.       ++ex_h->free;
  563. #if STATISTICS
  564.       _erfrees++;
  565. #endif
  566.       if( e->l)
  567.       {
  568.          if( e->r)
  569.             expr_tryfree( e->r);
  570.          expr_tryfree( e->l);
  571.       }
  572.    }
  573. }
  574. #endif
  575.  
  576. #if DEBUG
  577. #include <stdio.h>
  578.  
  579. dump_expr( p)
  580. expr huge   *p;
  581. {
  582.    if( p)
  583.    {
  584.       fprintf( ESTREAM, "\t\tEXPR @$%8.8lX\n", p);
  585.       fprintf( ESTREAM, "\t\tOp='%c'  Val=$%4.4X  Label=$%8.8X  ",
  586.                   p->op, p->val, p->label);
  587.       fprintf( ESTREAM, "Aux=$%4.4X Fixtype=%d\n",
  588.                   p->aux, p->fix);
  589.       fprintf( ESTREAM, "\t\tTop/Left/Rite [ $%8.8lX | $%8.8lX | $%8.8lX ]\n\n",
  590.                   p->zonk.t, p->l, p->r);
  591.       if( ! p->fix)
  592.          dump_expr( p->zonk.t);
  593.    }
  594. }
  595. #endif
  596.  
  597.  
  598. /* [EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF][EOF]
  599.  
  600. -- Kleiner Diskurs
  601.  
  602.    Deutschland heute (1/1990):
  603.  
  604.        "Ich _weiß_ nicht ob 2+2 4 oder 5 ist
  605.         Ich _will_ es auch gar nicht wissen
  606.         Aus dieser Art der Fragestellung  dringt
  607.         doch schon wieder diese rationale
  608.         Einstellung zur Umwelt auf, von der wir doch wissen
  609.         wo sie uns hin führt.
  610.  
  611.         Es ist doch jetzt einmal an der Zeit zu begreifen,
  612.         daß wichtige Veränderungen durchgeführt werden m⇧ssen.
  613.         Und wenn die Herren Politiker sich mal wieder
  614.         nicht dazu entschließen können, die Probleme der
  615.         heutigen Zeit konkret anzufassen, dann muss eben der
  616.         Druck von der Strasse kommen" <schluck> <schnief>
  617.                <heul>
  618.  
  619.                   APPLAUS!!
  620. */
  621.  
  622.