home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 357_01 / cstar1.exe / X2.C < prev    next >
C/C++ Source or Header  |  1991-06-18  |  41KB  |  1,527 lines

  1. /*
  2.     C* -- Code generation -- Support routines.
  3.  
  4.     source: x2.c
  5.     started: January 21, 1986
  6.     version:
  7.         February 20, 1987
  8.         March 7, 1989
  9.  
  10.     PUBLIC DOMAIN SOFTWARE
  11.  
  12.     The CSTAR program was placed in    the public domain on June 15, 1991,
  13.     by its author and sole owner,
  14.  
  15.         Edward K. Ream
  16.         1617 Monroe Street
  17.         Madison, WI 53711
  18.         (608) 257-0802
  19.  
  20.     CSTAR may be used for any commercial or non-commercial purpose.
  21.  
  22.     See cstar.h or cstar.c for a DISCLAIMER OF WARRANTIES.
  23. */
  24.  
  25. #include "cstar.h"
  26.  
  27. struct node *    x_addpsi(register struct node *locp,
  28.                 register struct node *loci,
  29.                 register int x_op);
  30. int        x_shift    (register unsigned long scale);
  31. struct node *    x_scale    (register struct node * loc1, unsigned long scale);
  32. struct node *    x_subp    (register struct node *loc1, struct node *loci,
  33.             unsigned long scale);
  34. struct node *    x_cast    (register struct node *loc1,
  35.             int len1, int imod1, int len3, bool dloc_ok);
  36. struct node *    resolve    (register struct node *loc1);
  37. void        x_lookat(register struct node *loc1);
  38. struct node *    x_sspush(register struct node *loc1);
  39. void        gen_pp    (struct node *p);
  40.  
  41. /*
  42.     CAUTION: the following assumptions are made in the arithmetical
  43.     generators:
  44.  
  45.     1. "A" temporaries are assumed to be valid to all 32 bits.  All
  46.        "A" word operations produce sign-extended results, so the
  47.        only way to violate this is to EXG in a D register that has
  48.        trash in the upper word.  Generators that do this are to undo
  49.        it before they exit.
  50.  
  51.     2. A couple of routines depend explicitly on receiving integer
  52.        loc_node arguments that are already set up to be int_type
  53.        or long_type.  Beware.
  54.  
  55.     3. Pointers are everywhere implicitly and explicitly assumed to
  56.        be long (32 bits); there is no short pointer type.  Let's
  57.        hope MacIntosh doesn't have functions that pass a short pointer
  58.        by reference, and intend it to be 16 bits.  (Since the 68000
  59.        is bass-ackwards, in order to slavishly imitate DEC minis,
  60.        the memory address of the 16-bit lower portion of a pointer is
  61.        NOT the same as the memory address of the entire 32-bit
  62.        pointer.   I wonder if the 68020 has to spend extra nanoseconds
  63.        to flip the halves of a word on a long store; I suppose either
  64.        it does or else the memory hardware does.
  65.  
  66.     4. If a loc_node contains two register entries, the first one
  67.        is to be long.  Such nodes are at present pointer nodes
  68.        created by x_addpsi(); so the potential violation is via
  69.        sop_cast().
  70. */
  71.  
  72.  
  73. /*
  74.     Access to register parameter, for unsigned extend in casts and
  75.     in pointer addition
  76. */
  77. extern int na_free;
  78. extern int nd_free;
  79.  
  80. /*
  81.     L O W  L E V E L  L O C _ N O D E  R O U T I N E S
  82. */
  83.  
  84. /*
  85.     add/subtract <<< int_type or long_type only >>> to/from pointer
  86.     loci is resolved prior to entry except when used for subtraction
  87.  
  88.     neither operands nor result are necessarily resolved
  89.  
  90.     loci is typically obtained from an arbitrary int using x_scale;
  91.     use x_scale(loci, 1L) on unknown ints before calling this
  92.  
  93.     loci should NOT be used by the
  94.         caller afterward (its temps will be freed anyhow)
  95.  
  96.     this code attempts to add an integer (already made signed-short
  97.     or signed-long elsewhere) to a pointer, and prefers to do it
  98.     by combination with the already existing node if possible.  the
  99.     sizes of constants are NOT checked here against the size limits
  100.     imposed by the processor; that is resolve's job.  the addition
  101.     or subtraction of two GLOBALS is checked, however, since there
  102.     is no representation for an address containing two independent
  103.     globals, either here or in any typical linker.
  104.  
  105.     this code consists basically of a multitude of special cases
  106. */
  107. struct node *
  108. x_addpsi(    register struct node *locp, register struct node *loci,
  109.         register int x_op)
  110. {
  111.     register struct node *loct, *locx;
  112.     register struct st_node *id;
  113.     
  114.     register int reg;
  115.     register long i_cnst, p_cnst;
  116.     int gi_symbol, gp_symbol;
  117.  
  118.     TRACEPB("x_addpsi",
  119.         printf("(%p, %p, %d)\n", locp, loci, x_op);
  120.         pr_loc(locp); printf("; ");
  121.         pr_loc(loci); printf(";\n"));
  122.  
  123.     /* for addition to zero, do absolutely nothing */
  124.     if (is_zloc(loci)) {
  125.  
  126.         TRACEP("x_addpsi", printf("does nothing\n"));
  127.         RETURN_PTR("x_addpsi", locp);
  128.     }
  129.  
  130.     x_op = (x_op == MINUS_TOK)? X_SUB : X_ADD;
  131.         
  132.     /* we do intend to represent the actual sum, so we must resolve
  133.         pointer EA loc_node. */
  134.     if (is_ea(locp -> n_mode)) {
  135.         locp = resolve(locp);    /* we have to get it */
  136.         if (reg = has_atreg(locp)) {
  137.             loct = locn_reg(reg);
  138.             free_xtemp(locp, loct);
  139.         }
  140.         else if (x_op == X_ADD &&
  141.               (is_atloc(loci) ||
  142.                  (is_dtloc(loci) && loci -> n_cltype == long_type))
  143.                                     ) {
  144.             /* SHORTCUT */
  145.             /* add the EA pointer directly to the xreg int */
  146.             /* areg assumption: all 32 areg bits valid--true if
  147.                 EXG instruction is never used to insert them */
  148.             g_2l1(x_op, locp, loci);
  149.             loci -> n_cltype = locp -> n_cltype;
  150.             RETURN_PTR("x_addpsi", loci);
  151.         }
  152.         else {
  153.             loct = get_atemp();
  154.             free_temp(locp);
  155.             /* ss_push serves no purpose here since it has no atemp */
  156.         }
  157.         loct -> n_cltype = locp -> n_cltype;
  158.         g_2l1(X_MOVEA, locp, loct);    
  159.         locp = locn_dupl(loct);
  160.     }
  161.     else {
  162.         locp = locn_xdupl(locp);
  163.     }
  164.     /* the upshot of the above is that locp is now a VALUE */
  165.  
  166.     if (is_ea(loci -> n_mode) || x_op == X_SUB) {
  167.         loci = resolve(loci);
  168.     }
  169.     loci = locn_xdupl(loci);
  170.  
  171.     /* now attempt combination of constants */
  172.     if (loci -> n_mode == VALUE_MODE) {
  173.         gi_symbol = gp_symbol = FALSE;
  174.         p_cnst = locp -> n_const;
  175.         i_cnst = loci -> n_const;
  176.  
  177.         /* check whether any of the symbols are global */
  178.         if (id = locp -> n_cid) {
  179.             if (is_rstack(id -> st_sclass) ||
  180.                     id -> st_sclass == SUE_CLASS) {
  181.                 p_cnst += id -> st_offset;
  182.             }
  183.             else {
  184.                 gp_symbol = TRUE;
  185.             }
  186.         }
  187.  
  188.         if (id = loci -> n_cid) {
  189.             if (is_rstack(id -> st_sclass) ||
  190.                     id -> st_sclass == SUE_CLASS) {
  191.                 i_cnst += id -> st_offset;
  192.             }
  193.             else {
  194.                 gi_symbol = TRUE;
  195.             }
  196.         }
  197.         if (x_op == X_SUB) {
  198.             i_cnst = -i_cnst;
  199.         }
  200.         /* at this point non-global components are evaluated */
  201.  
  202.         /* NOTE:
  203.             global symbols are not known until link time; they
  204.             can't be combined here, and must be presumed to be longare generally assigned by the linker, and
  205.         */
  206.  
  207.         /* transfer constants from i to p except for two globals */
  208.         locp -> n_const += i_cnst;
  209.         loci -> n_const = 0;
  210.         if (gi_symbol) {
  211.             if (gp_symbol) {
  212.             }
  213.             else {
  214.                 locp -> n_const = i_cnst + p_cnst;
  215.                 locp -> n_cid = loci -> n_cid;
  216.             }
  217.         }
  218.         else {
  219.             loci -> n_cid = NULL;
  220.         }
  221.  
  222.         /* transfer register from i to p as space permits */
  223.         if (x_op == X_ADD) {
  224.             TRACEP("x_addpsi",
  225.                 printf("addition--transfer regs\n"));
  226. #ifdef DEBUG
  227.             if (loci -> n_reg2) {
  228.                 g_error(NULL, "x_addpsi: internal: two i regs");
  229.             }
  230. #endif /* DEBUG */
  231.             if (loci -> n_cltype == int_type) {
  232.                 if (locp -> n_reg1 && !locp -> n_reg2) {
  233.                     locp -> n_reg2 = loci -> n_reg1;
  234.                     loci -> n_reg1 = NULL;
  235.                     locp -> n_scflag = X2_WORD;
  236.                 }
  237.             }
  238.             else {
  239.                 if (!locp -> n_reg1) {
  240.                     locp -> n_reg1 = loci -> n_reg1;
  241.                     loci -> n_reg1 = NULL;
  242.                 }                
  243.                 else if (!locp -> n_reg2) {
  244.                     locp -> n_reg2 = loci -> n_reg1;
  245.                     locp -> n_scflag = X2_LONG;
  246.                     loci -> n_reg1 = NULL;
  247.                 }
  248.             }
  249.         }
  250.     }
  251.     TRACEP("x_addpsi",
  252.         printf("transfers done: ");
  253.         pr_loc(locp); printf("; ");
  254.         pr_loc(loci); printf(";\n"));
  255.  
  256.     if (is_zloc(loci)) {
  257.         /* SHORTCUT */
  258.         RETURN_PTR("x_addpsi", locp);
  259.     }
  260.  
  261.     /* get it all added up; there is a reg or const that didn't move */
  262.     /* now try to add to a register already part of the pointer node */
  263.     if ( 
  264.     (reg = has_atreg(locp)) ||
  265.     (is_dtreg(reg = locp -> n_reg1) && loci -> n_cltype == long_type) ||
  266.     (is_dtreg(reg = locp -> n_reg2) &&
  267.      ((locp->n_scflag == X2_LONG)? long_type : int_type) == loci->n_cltype) 
  268.     ) {
  269.         TRACEP("x_addpsi", printf("locp temporary\n"));
  270.  
  271.         /* do it in the temporary, no cast needed */
  272.         loct = locn_reg(reg);
  273.         if (loci -> n_mode == VALUE_MODE) {
  274.             loct -> n_cltype = loci -> n_cltype;
  275.             if (loci -> n_reg1) {
  276.                 g_2l2(x_op, locn_reg(loci -> n_reg1), loct);
  277.             }
  278.             loci -> n_reg1 = 0;
  279.             if (loci -> n_cid) {
  280.                 g_2l2(x_op, loci, loct);
  281.             }
  282.         }
  283.         else {
  284.             g_2l1(x_op, loci, loct);
  285.         }
  286.         /* all added up */
  287.     }
  288.     else if (x_op == X_ADD && is_atreg(reg = loci -> n_reg1)) {
  289.         /* do it in the integer's areg */
  290.         TRACEP("x_addpsi", printf("loci temporary\n"));
  291.         loct = locn_reg(reg);
  292.         loct -> n_cltype = long_type;
  293.  
  294.         if (is_ea(loci -> n_mode)) {
  295.             g_2l1(X_MOVEA, loci, loct);
  296.             free_reg(loci -> n_reg2);
  297.             loci = loct;
  298.         }
  299.         else if (loci -> n_cid) {
  300.             loci -> n_reg1 = 0;
  301.             g_2l1(X_ADDA, loci, loct);
  302.         }
  303.         if (locp -> n_reg1) {
  304.             g_2l2(X_ADDA, locn_reg(locp -> n_reg1), loct);
  305.         }
  306.         locp -> n_reg1 = reg;
  307.         /* all added up */
  308.     }
  309.     else {
  310.         /*
  311.             loci and locp are both arbitrary combinations of
  312.             registers and constants; loci may not have a
  313.             second register, nor an n_const; it may have
  314.             one register and/or an n_cid
  315.  
  316.             locp is now in VALUE mode but not necessarily
  317.             resolved (usable as an address mode).  if it
  318.             involves a register, that register will be
  319.             substituted with the temporary and the integer
  320.             components added to it or subtracted from it.
  321.             otherwise, the temporary will be inserted, and
  322.             the integer components inserted and added or
  323.             subtracted.  for subtraction, a D temporary may
  324.             be used.
  325.         */
  326.         TRACEP("x_addpsi", printf("temporary required\n"));
  327.         if (x_op == X_SUB && !locp -> n_reg2) {
  328.             loct = get_dtemp();
  329.         }
  330.         else {
  331.             loct = get_atemp();
  332.         }
  333.         loct -> n_cltype = locp -> n_cltype;
  334.  
  335.         if (is_zloc(locp)) {
  336.             locp = loct;
  337.         }
  338.         else {
  339.             if (locp -> n_reg1) {
  340.                 /* substitute the temporary for it */
  341.                 g_2l2(X_MOVE, locn_reg(locp -> n_reg1), loct);
  342.                 free_reg(locp -> n_reg1);
  343.                 locp -> n_reg1 = loct -> n_reg1;
  344.             }
  345.             else {
  346.                 g_2l1(X_MOVE, locp, loct);
  347.                 locp = loct;
  348.             }
  349.             if (is_ea(loci -> n_mode)) {
  350.                 g_2l1(x_op, loci, loct);
  351.                 free_temp(loci);
  352.             }
  353.             else {
  354.                 if (loci -> n_cid) {
  355.                     /* loci -> n_const should have been
  356.                                 transferred */
  357.                     locx = locn_dupl(loci);
  358.                     locx -> n_reg1 = 0;
  359.                     loci -> n_cid = 0;
  360.                     g_2l1(x_op, locx, loct);
  361.                 }
  362.                 if (loci -> n_reg1) {
  363.                     g_2l1(x_op, loci ,loct);
  364.                 }
  365.             }
  366.             if (is_dreg(locp -> n_reg1) && !is_dloc(locp)) {
  367.                 /* don't return a composite D-value node */
  368.                 /* note that the conditions above for drawing
  369.                    a D temp restrict the combinations
  370.                    possible here */
  371.                 locp -> n_reg1 = 0;
  372.                 g_2l1(x_op, locp, loct);
  373.                 locp = loct;
  374.             }
  375.         }
  376.         /* all added up */
  377.         if (x_op == X_SUB) {
  378.             locp -> n_cltype = long_type;
  379.         }
  380.     }
  381.     TRACEP("x_addpsi",
  382.         printf("returns: ");
  383.         pr_loc(locp); printf("; ");
  384.         pr_loc(loci); printf(";\n"));
  385.  
  386.     RETURN_PTR("x_addpsi", locp);
  387. }
  388.  
  389. /*
  390.     return a shift counter if a particular scaling can be done as a shift
  391. */
  392. int
  393. x_shift(register unsigned long scale)
  394. {
  395.     register int count;
  396.     register unsigned long x;
  397.  
  398.     TRACEPB("x_shift", printf("(%lu)\n", scale));
  399.  
  400.     x = 1;
  401.     count = 0;
  402.     while (x && x < scale) {
  403.         count++;
  404.         x <<= 1;
  405.     }
  406.     if (x == scale) {
  407.         RETURN_INT("x_shift", count);
  408.     }
  409.     else {
  410.         RETURN_INT("x_shift", -1);
  411.     }
  412. }
  413.  
  414. /*
  415.     Given a location containing an unscaled integer of any sort,
  416.     return a location containing the integer multiplied by
  417.     the scale argument, and which is always either int_type
  418.     (signed word) or else long_type (signed vs. unsigned makes no
  419.     difference).
  420.  
  421.     The returned node is ALWAYS modifiable; that is, it is never
  422.     a node which is already attached to something in the code list.
  423.  
  424.     CAUTION: the postponement of scaling, if any, is someone else's
  425.     problem.
  426.  
  427.     This code contains a multitude of special cases; the scaling
  428.     process does not take quite so long as the size of this function
  429.     suggests.
  430. */
  431. struct node *
  432. x_scale(register struct node * loc1, unsigned long scale)
  433. {
  434.     register int imod, in_place, shift, dloc_ok;
  435.     register struct node *loc3, *loc4;
  436.     int cast;
  437.  
  438.     TRACEPB("x_scale",
  439.         printf("(%p by %lu)\n", loc1, scale);
  440.         pr_loc(loc1); printf(";\n"));
  441.  
  442.     /* ------ if it's a constant, life is very simple ------ */
  443.     if (loc3 = fix_cloc(loc1)) {
  444.         /* loc3 is a copy if necessary (locn_xdupl) */
  445.         loc3 -> n_const *= (long) scale;
  446.         if (loc3 -> n_const <= 32767 && loc3 -> n_const >= -32768L) {
  447.             loc3 -> n_cltype = int_type;
  448.         }
  449.         else {
  450.             loc3 -> n_cltype = long_type;
  451.         }
  452.         TRACEP("x_scale",
  453.             printf("returns (const): ");
  454.             pr_loc(loc3); printf(";\n"));
  455.  
  456.         RETURN_PTR("x_scale", loc3);
  457.     }
  458.  
  459.     /* ------ decide whether a cast is necessary ------ */
  460.     shift = x_shift(scale);
  461.  
  462.     imod = loc1->n_cltype->t_mclass & (LONG_MOD | CHAR_MOD | UNSIGNED_MOD);
  463.  
  464.     if (imod & LONG_MOD) {
  465.         imod &= ~UNSIGNED_MOD; /* ignore sign of long */
  466.     }
  467.     cast = imod & (CHAR_MOD | UNSIGNED_MOD);
  468.             /* chars and non-long unsigneds have to be exteneded */
  469.  
  470.     /* ------ perform special areg cast and scaling by 2 or 4 ------ */
  471.     if (shift && na_free && !cast) { if (
  472.         (shift == 1) ||
  473.         (shift == 2 && (!is_dtloc(loc1) || !(imod & LONG_MOD)) )
  474.        ) {
  475.  
  476.         TRACEP("x_scale", printf("special scale\n"));
  477.  
  478.         loc1 = resolve(loc1);
  479.         /* SHORTCUT */
  480.         if (!is_atloc(loc1)) {
  481.             ss_push(loc1);
  482.             loc3 = get_atemp();
  483.             loc1 = ss_pop();
  484.             g_2l1(X_MOVEA, loc1, loc3);
  485.             free_temp(loc1);
  486.         }
  487.         else {
  488.             loc3 = locn_xdupl(loc1);
  489.         }
  490.         loc3 -> n_cltype = long_type;
  491.         
  492.         while (shift--) {
  493.             g_2l1(X_ADDA, loc3, loc3);
  494.         }
  495.  
  496.         TRACEP("x_scale",
  497.             printf("returns (areg): ");
  498.             pr_loc(loc3); printf(";\n"));
  499.  
  500.         RETURN_PTR("x_scale", loc3);
  501.     } }
  502.  
  503.     /* ------ cast index and scale as necessary ------ */
  504.     if (cast || scale != 1) {
  505.         TRACEP("x_scale", printf("cast or scale\n"));
  506.  
  507.         dloc_ok = (scale == 1 && EXCESSLENOK);
  508.  
  509.         /* perform the appropriate cast */
  510.         if (imod & LONG_MOD) {
  511.             loc3 = x_cast(loc1, 4, imod, 4, dloc_ok);
  512.         }
  513.         else if (imod & CHAR_MOD) {
  514.             /* char to int or long in dreg */
  515.             if (shift >= 8 ||
  516.                 ( (~imod & UNSIGNED_MOD) && scale > 32767) ||
  517.                             scale > 65535L) {
  518.                 loc3 = x_cast(loc1, 1, imod, 4, dloc_ok);
  519.             }
  520.             else {
  521.                 loc3 = x_cast(loc1, 1, imod, 2, dloc_ok);
  522.             }
  523.         }
  524.         else if (shift > 0 || ((imod & UNSIGNED_MOD) && scale == 1) ||
  525.                             scale > 32767) {
  526.             loc3 = x_cast(loc1, 2, imod, 4, dloc_ok);
  527.         }
  528.         else {
  529.             loc3 = x_cast(loc1, 2, imod, 2, dloc_ok);
  530.         }
  531.  
  532.         /* the index is now loc3, and loc1 is discarded */
  533.  
  534.         /* now carry out the scaling */
  535.         if (scale != 1) {
  536.  
  537.             TRACEP("x_scale",
  538.                 printf("scaling required: %lx\n", scale));
  539.  
  540.             if (shift > 0) {
  541.                 if (shift == 1) {
  542.                     g_2l1(X_ADD, loc3, loc3);
  543.                 }
  544.                 else if (nd_free) {
  545.                     loc4 = get_dtemp();
  546.                     loc4 -> n_cltype = int_type;
  547.                     g_2l2(X_MOVE, locn_xconst((long)shift),
  548.                                     loc4);
  549.                     g_2l2(X_ASL, loc4, loc3);
  550.                     free_temp(loc4);
  551.                 }
  552.                 else {
  553.                     while (shift > 8) {
  554.                         g_2l2(X_ASL, locn_xconst(8L),
  555.                                     loc3);
  556.                         shift -= 8;
  557.                     }
  558.                     if (shift) {
  559.                         g_2l2(X_ASL, locn_xconst((long)shift),
  560.                                     loc3);
  561.                     }
  562.                 }
  563.             }
  564.             /* NOTE: in CHAR_MOD with scale < 256, these
  565.                multiplies really ought to return a sort-of
  566.                long-or-int type */
  567.  
  568.             /* SIDE EFFECT: */
  569.             else if (loc4 = locn_xconst(scale),
  570.                 (imod & UNSIGNED_MOD) && scale < 65536L) {
  571.                 g_2(X_MULU, loc4, loc3);
  572.                 loc3 -> n_cltype = long_type;
  573.             }
  574.             else if ((~imod & LONG_MOD) && scale <= 32767L) {
  575.                 g_2(X_MULS, loc4, loc3);
  576.                 loc3 -> n_cltype = long_type;
  577.             }
  578.             else {
  579.                 g_2call(loc4, loc3,
  580.                     ((imod & UNSIGNED_MOD) ||
  581.                     scale >= (unsigned long) 0x80000000L) ?
  582.                         "lmulu" : "lmul" );
  583.                 loc3 = d0_loc;
  584.                 loc3 -> n_cltype = long_type;
  585.             }
  586.         }
  587.     }
  588.     else {
  589.         /* no cast and no scaling */
  590.         loc3 = locn_xdupl(loc1);
  591.         loc3 -> n_cltype = (imod & LONG_MOD)? long_type : int_type;
  592.     }
  593.  
  594.     TRACEP("x_scale",
  595.         printf("returns: ");
  596.         pr_loc(loc3); printf(";\n"));
  597.  
  598.     RETURN_PTR("x_scale", loc3);
  599. }
  600.  
  601. /*
  602.     Subtract two pointers and descale according to given scale (do not
  603.     take scale from either pointer)
  604.  
  605.     This function generates code for a LONG WORD.
  606. */
  607. struct node *
  608. x_subp(register struct node *loc1, struct node *loci, unsigned long scale)
  609. {
  610.     register int imod, in_place, shift;
  611.     register struct node *loc3, *loc4;
  612.     int cast;
  613.  
  614.     /* this subtraction always gets done at runtime and always gets
  615.        done in a Dreg and nothing gets moved from one node to the other */
  616.  
  617.     TRACEPB("x_subp", printf("(%p, %p, %lu)\n", loc1, loci, scale));
  618.  
  619.     loci = resolve(loci);
  620.     loc1 = resolve(loc1);
  621.  
  622.     if (!is_dtloc(loc1)) {
  623.         loc3 = get_dtemp();
  624.         loc3 -> n_cltype = loc1 -> n_cltype;
  625.         g_2l1(X_MOVE, loc1, loc3);
  626.         loc1 = loc3;
  627.     }
  628.     loc1 = locn_xdupl(loc1);
  629.     loc1 -> n_cltype = long_type;
  630.  
  631.     /* the following subtraction yields a 33-bit result */
  632.     /* see lint.doc on folded variables */
  633.     g_2l2(X_SUB, loci, loc1);
  634.  
  635.     if (scale <= 1) {
  636.         /* SHORTCUT */
  637.         if (scale == 1) {
  638.             RETURN_PTR("x_subp", loc1);    /* and the context better know bit 32 */
  639.         }
  640.         else {
  641.             g_error(NULL, "subtraction of pointers to void");
  642.             RETURN_PTR("x_subp", zero_loc);
  643.         }
  644.     }
  645.  
  646.     /* ------ do a shift if possible ------ */
  647.     shift = x_shift(scale);
  648.  
  649.     if (shift > 0) {
  650.         /* SHORTCUT */
  651.         TRACEP("x_subp", printf("arithmetic shift"));
  652.  
  653.         g_2l2(X_ROXR, one_loc, loc1);
  654.         shift--;
  655.         while (shift > 8) {
  656.             g_2l2(X_ASR, locn_xconst(8L), loc1);
  657.             shift -= 8;
  658.         }
  659.         if (shift) {
  660.             g_2l2(X_ASR, locn_xconst((long)shift), loc1);
  661.         }
  662.         RETURN_PTR("x_subp", loc1);
  663.     }
  664.     /* WARNING: this does not deal with the 33rd bit! */
  665.     loci = locn_xconst(scale);
  666.     loci -> n_cltype = long_type;
  667.     g_2call(loc1, loci, "ldiv");
  668.     d0_loc -> n_cltype = long_type;
  669.  
  670.     RETURN_PTR("x_subp", d0_loc);
  671. }
  672.  
  673. /*
  674.     Extend something and leave the result in a D temporary
  675.     If dloc_ok, leave the result in-place even if the D
  676.     location is not a temporary; this must be used with caution!
  677.     
  678.     Result type is set to int_type or long_type, for use in the
  679.     pointer scaling routines.  For sop_cast and other uses, the
  680.     result type should be set to the cast operator type.
  681.  
  682.     If the extension is nil (len1 == len3), it still gets loaded.
  683. */
  684. struct node *
  685. x_cast(register struct node *loc1, int len1, int imod1, int len3, bool dloc_ok)
  686. {
  687.     register int reg, in_place;
  688.     register struct node *loc3;
  689.  
  690.     TRACEPB("x_cast", printf("(%p, %d, %d, %d, %s)\n", 
  691.         loc1, len1, imod1, len3, sl_sbout(dloc_ok)));
  692.  
  693.     loc1 = resolve(loc1);
  694.  
  695.     if (((reg = has_dtreg(loc1)) || (dloc_ok && is_dloc(loc1))) &&
  696.         !(nd_free && len3 == 4 && (imod1 & UNSIGNED_MOD))  ) {
  697.  
  698.         /* dloc or dtloc and do in place */
  699.         in_place = TRUE;
  700.         if (is_dloc(loc1)) {
  701.             loc3 = locn_xdupl(loc1);
  702.         }
  703.         else {
  704.             loc3 = locn_reg(reg);
  705.             g_2l1(X_MOVE, loc1, loc3);
  706.         }
  707.     }
  708.     else {
  709.         /* draw a D temp if none in node, or if unsigned-to-long */
  710.         /* unsigned-to-16-bit is just as fast in_place */
  711.         ss_push(loc1);
  712.         loc3 = get_dtemp();
  713.         loc1 = ss_pop();
  714.         in_place = FALSE;
  715.     }
  716.     loc3 -> n_cltype = (len3 > 2)? long_type : int_type;
  717.  
  718.     /* perform actual extension in D register */
  719.     if (len3 <= len1) {
  720.         /* no extension */
  721.         if (!in_place) {
  722.             /*
  723.                 for a shrink, this moves more than needed,
  724.                 but it gets the address alignment correct 
  725.                 and this is not the shrink routine anyhow;
  726.                 see sop_cast
  727.             */
  728.             g_2l1(X_MOVE, loc1, loc3);
  729.         }
  730.     }
  731.     /* various extension operations in each case */
  732.     /* caller is responsible for special areg casts */
  733.     else if (imod1 & UNSIGNED_MOD) {
  734.         if (in_place) {
  735.             /* in place */
  736.             if (len1 == 1) {
  737.                 g_2l2(X_AND, locn_xconst(255L), loc3);
  738.                 if (len3 > 2) {
  739.                     g_1l(X_EXT, loc3);
  740.                 }
  741.             }
  742.             else {
  743.                 /* len1 == 2 */
  744.                 /* andi long takes 16 clocks; this takes 12 */
  745.                 /* clearly a 68000 botch! */
  746.                 g_1(X_SWAP, loc3);
  747.                 loc3 -> n_cltype = int_type;
  748.                 g_1l(X_CLR, loc3);
  749.                 loc3 -> n_cltype = long_type;
  750.                 g_1(X_SWAP, loc3);
  751.             }
  752.         }
  753.         else {
  754.             g_1l(X_CLR, loc3);
  755.             g_2l1(X_MOVE, loc1, loc3);
  756.         }
  757.     }
  758.     else {
  759.         /* signed extension */
  760.         if (!in_place) {
  761.             g_2l1(X_MOVE, loc1, loc3);
  762.         }
  763.         if (len1 == 1 && len3 > 2) {
  764.             /* then: will need two extends */
  765.             loc3 -> n_cltype = int_type;
  766.             g_1l(X_EXT, loc3);
  767.             loc3 -> n_cltype = long_type;
  768.         }
  769.         g_1l(X_EXT, loc3);
  770.     }
  771.     RETURN_PTR("x_cast", loc3);
  772. }
  773.  
  774. /*
  775.     Evaluate a node to the point where it could be used as
  776.     an <EA> mode in a 68000 machine instruction.  For EA mode
  777.     nodes, this will typically mean adding the constant to
  778.     one or another of the registers, or adding into a temporary,
  779.     if the constant is out of range.  For VAL mode, it means
  780.     adding everything up, into a register if a register is
  781.     already involved.
  782.  
  783.     The second register in a loc_node is never to be set up except
  784.     by x_addpsi() and is to be X2_WORD or X2_LONG.
  785.  
  786.     This code is a multitude of special cases.
  787. */
  788. struct node *
  789. resolve(register struct node *loc1)
  790. {
  791.     register struct node *locp, *locc, *loc3;
  792.     register struct st_node *id;
  793.     register int reg, g_symbol;
  794.     register long i_cnst;
  795.  
  796.     TRACEPB("resolve",
  797.         printf("(%p)\n", loc1);
  798.         pr_loc(loc1); printf("\n"));
  799.  
  800.     g_symbol = FALSE;
  801.     i_cnst = loc1 -> n_const;
  802.     if (id = loc1 -> n_cid) {
  803.         if (is_rstack(id -> st_sclass) || id->st_sclass == SUE_CLASS) {
  804.             /* i_cnst is the true value of the const if known */
  805.             i_cnst += id -> st_offset;
  806.         }
  807.         else {
  808.             /* the true value is unknown and long */
  809.             g_symbol = TRUE;
  810.         }
  811.     }
  812.  
  813.     if (!loc1 -> n_reg1) {
  814.         /* constant */
  815.  
  816.         TRACEP("resolve",
  817.                 printf("returns (constant/constant EA): "); 
  818.             pr_loc(loc1); printf("\n"));
  819.  
  820.         RETURN_PTR("resolve", loc1);
  821.     }
  822.  
  823.     /* from here on the node must represent a variable involving a reg */
  824.     if (!g_symbol && i_cnst == 0 && loc1 -> n_cid) {
  825.         loc1 = locn_xdupl(loc1);
  826.         loc1 -> n_cid = NULL;
  827.         loc1 -> n_const = 0;
  828.  
  829.         TRACEP("resolve", printf("consolidate zero\n"));
  830.     }
  831.  
  832.     /* for dual-reg node: rearrange to put the "A" register first */
  833.     /* the node was to have been set up by x_addpsi and was pointer at
  834.                             that time */
  835.     reg = loc1 -> n_reg2;
  836.     if (  (is_atreg(reg) && !is_atreg(loc1 -> n_reg1)) ||
  837.         (is_areg(reg) && !is_areg(loc1 -> n_reg1))  ) {
  838.  
  839.         /* switch */
  840.         loc1 = locn_xdupl(loc1);
  841.         loc1 -> n_reg2 = loc1 -> n_reg1;
  842.         loc1 -> n_reg1 = reg;    /* the areg can be taken as long */
  843.         loc1 -> n_scflag = X2_LONG;    /* first item always long */
  844.     }
  845.     
  846.     if (is_ea(loc1 -> n_mode)) {
  847.         /* force an areg into the mode; it is otherwise unusable */
  848.         if (!is_areg(loc1 -> n_reg1)) {
  849.             loc3 = get_atemp();
  850.             loc3 -> n_cltype = long_type;
  851.             g_2l2(X_MOVEA, locn_reg(loc1 -> n_reg1), loc3);
  852.             loc1 = locn_xdupl(loc1);
  853.             loc1 -> n_reg1 = loc3 -> n_reg1;
  854.         }
  855.  
  856.         /* now see if it is OK as is */
  857.         if (!g_symbol &&
  858.             ((!loc1->n_reg2 && i_cnst<=32767 && i_cnst >= -32768L) 
  859.                 ||
  860.             (i_cnst <= 127 && i_cnst >= -128))
  861.         ) {
  862.             /* it is a valid mode as is */
  863.             TRACEP("resolve",
  864.                 printf("returns ");
  865.                 pr_loc(loc1); printf("\n"));
  866.  
  867.             RETURN_PTR("resolve", loc1);
  868.         }
  869.  
  870.         /* areg node doesn't work as is; must start adding */
  871.         /* the constant must be too big */
  872.         locc = locn_xdupl(loc1);
  873.         locc -> n_reg1 = locc -> n_reg2 = 0;
  874.         locc -> n_mode = 0;
  875.         if (g_symbol ||
  876.           locc -> n_const <= -32768L || locc -> n_const >= 32767) {
  877.             locc -> n_cltype = long_type;
  878.         }
  879.         else {
  880.             locc -> n_cltype = int_type;
  881.         }
  882.         
  883.         /* we WILL now add, so we either shortcut or else get an
  884.             atreg in which to add */
  885.         if (!is_atreg(loc1 -> n_reg1)) {
  886.             /* first reg is therefore a DESIGNATED areg */
  887.             /* WARNING:
  888.                 after we have postponement of scaling,
  889.                 we will probably want to do an ext.l
  890.                 on the D temporary in the X2_WORD case
  891.                 instead of skipping to the get-atemp
  892.                 code.  For now, however, doing that produces
  893.                 silly cascades of extends and additions into
  894.                 the D register.
  895.             */
  896.             if (is_dtreg(loc1 -> n_reg2) &&
  897.                         loc1 -> n_scflag == X2_LONG) {
  898.                 /* SHORTCUT */
  899.                 /* add the constant to the already long dreg */
  900.                 locc -> n_cltype = long_type;
  901.                 g_2l1(X_ADD, locc, locn_reg(loc1 -> n_reg2));
  902.                 loc1 = locn_xdupl(loc1);
  903.                 loc1 -> n_cid = NULL;
  904.                 loc1 -> n_const = 0L;
  905.  
  906.                 TRACEP("resolve",
  907.                     printf("returns (dreg): ");
  908.                     pr_loc(loc1);printf("\n"));
  909.  
  910.                 RETURN_PTR("resolve", loc1);
  911.             }
  912.             loc3 = get_atemp();
  913.             loc3 -> n_cltype = long_type;
  914.             g_2l2(X_MOVEA, locn_reg(loc1 -> n_reg1), loc3);
  915.             loc1 = locn_xdupl(loc1);
  916.             loc1 -> n_reg1 = loc3 -> n_reg1;
  917.         }
  918.  
  919.         /* now we have an atreg node, so all we need do is add const */
  920.         /* 3/6/89 !loc1 was !locp */
  921.         if (!loc1 -> n_reg2 || g_symbol ||
  922.                 i_cnst < -32768L || i_cnst > 32767) {
  923.             /* one or two registers including an atemp */
  924.             /* add the constant to the atemp */
  925.             g_2l1(X_ADDA, locc, locn_reg(loc1 -> n_reg1));
  926.             loc1 = locn_xdupl(loc1);
  927.             loc1 -> n_cid = NULL;
  928.             loc1 -> n_const = 0L;
  929.         }
  930.         else {
  931.             /* two registers with atemp, and word constant */
  932.             /* add the other register to the atemp */
  933.             /* this is a judgment call; the register-to-register
  934.                add in a sense wastes two clock cycles in some
  935.                cases.  we could add the constant to the atemp;
  936.                in many cases that would produce an 0(a,x) mode
  937.                that would have nothing more added to the constant,
  938.                or tend to trigger more of the same since it's
  939.                almost full-up; that may also in effect waste
  940.                a couple of cycles
  941.             */
  942.             loc3 = locn_reg(loc1 -> n_reg2);
  943.             loc3 -> n_cltype = (loc1 -> n_scflag == X2_WORD)?
  944.                             int_type : long_type;
  945.             g_2l1(X_ADDA, loc3, locn_reg(loc1 -> n_reg1));
  946.             loc1 = locn_xdupl(loc1);
  947.             loc1 -> n_reg2 = 0;
  948.             free_xtemp(loc3, loc1);
  949.         }
  950.         TRACEP("resolve",
  951.             printf("returns: ");
  952.             pr_loc(loc1); printf("\n"));
  953.  
  954.         RETURN_PTR("resolve", loc1);
  955.     }
  956.     else {
  957.         /* the node is required as a value, so it has to be
  958.            added up to yield an actual number in a single register */
  959.         if (i_cnst == 0 && !g_symbol && !loc1 -> n_reg2) {
  960.  
  961.             TRACEP("resolve",
  962.                 printf("returns (as is): ");
  963.                 pr_loc(loc1); printf("\n"));
  964.  
  965.             RETURN_PTR("resolve", loc1);
  966.         }
  967. #ifdef DEBUG
  968.         /* the shortening cast is to resolve its target, so this
  969.             is not to happen */
  970.         if (mlen(loc1) < 4) {
  971.             g_error(loc1, "resolve: internal: must not happen");
  972.  
  973.             TRACEP("resolve",
  974.                 printf("short combined node: ");
  975.                 pr_loc(loc1); printf("\n");
  976.                 pr_type(loc1 -> n_cltype); printf("\n"));
  977.         }
  978. #endif /* DEBUG */
  979.  
  980.         /* find a destination */
  981.         if (reg = has_atreg(loc1)) {
  982.             loc3 = locn_reg(reg);
  983.         }
  984.         else if (is_dtreg(reg = loc1 -> n_reg1)) {
  985.             loc3 = locn_reg(reg);
  986.         }
  987.         else if (loc1 -> n_scflag == X2_LONG &&
  988.                     is_dtreg(reg = loc1 -> n_reg2)) {
  989.             loc3 = locn_reg(reg);
  990.         }
  991.         else {
  992.             loc3 = get_atemp();
  993.             /* try to pick it up with LEA in one fell swoop */
  994.             if (!g_symbol && is_areg(loc1 -> n_reg1) &&
  995.                 (
  996.                 (!loc1->n_reg2 && i_cnst<=32767 && i_cnst >= -32768L) ||
  997.                 (i_cnst <= 127 && i_cnst >= -128) )
  998.                                     ) {
  999.                 /* it is a valid mode */
  1000.                 g_2(X_LEA, locn_chmod(loc1, EA_MODE), loc3);
  1001.                 
  1002.                 TRACEP("resolve",
  1003.                     printf("returns (LEA): ");
  1004.                     pr_loc(loc3);printf("\n"));
  1005.  
  1006.                 free_temp(loc1);
  1007.                 loc3 -> n_cltype = loc1 -> n_cltype;
  1008.                 RETURN_PTR("resolve", loc3);
  1009.             }
  1010.             /* otherwise move and add */
  1011.             /* LEA of the two registers into the temp is not
  1012.                 any faster, so we won't try it */
  1013.             loc3 -> n_cltype = loc1 -> n_cltype;
  1014.             g_2l2(X_MOVEA, locn_reg(loc1 -> n_reg1), loc3);
  1015.             loc3 -> n_cltype = long_type;
  1016.             free_reg(loc1 -> n_reg1);
  1017.             loc1 = locn_xdupl(loc1);
  1018.             loc1 -> n_reg1 = reg = loc3 -> n_reg1;
  1019.         }
  1020.  
  1021.         /* see if it can be obtained with LEA as is */
  1022.         /* NOTE: double-check timing & make sure this never harms */
  1023.         if (!g_symbol && is_areg(reg) &&
  1024.             (
  1025.             (!loc1->n_reg2 && i_cnst<=32767 && i_cnst >= -32768L) ||
  1026.             (i_cnst <= 127 && i_cnst >= -128) )
  1027.                                 ) {
  1028.             /* it is a valid mode */
  1029.             g_2(X_LEA, locn_chmod(loc1, EA_MODE), loc3);
  1030.             free_xtemp(loc1, loc3);
  1031.             
  1032.             TRACEP("resolve",
  1033.                 printf("returns (LEA): ");
  1034.                 pr_loc(loc3);printf("\n"));
  1035.  
  1036.             loc3 -> n_cltype = loc1 -> n_cltype;
  1037.             RETURN_PTR("resolve", loc3);
  1038.         }
  1039.  
  1040.         /* must add the other register and the constant into loc3 */
  1041.         locc = locn_xdupl(loc1);
  1042.         locc -> n_reg1 = locc -> n_reg2 = 0;
  1043.         if (g_symbol || is_dreg(reg) ||
  1044.           locc -> n_const <= -32768L || locc -> n_const >= 32767) {
  1045.             locc -> n_cltype = long_type;
  1046.         }
  1047.         else {
  1048.             locc -> n_cltype = int_type;
  1049.         }
  1050.         
  1051.         /* add the "other" register to the result */
  1052.         if (reg == loc1 -> n_reg2) {
  1053.             loc3 -> n_cltype = long_type;
  1054.             g_2l2(X_ADD, locn_reg(loc1 -> n_reg1), loc3);
  1055.         }
  1056.         else {
  1057.             if (loc1 -> n_reg2) {
  1058.                 loc3->n_cltype = (loc1 -> n_scflag == X2_WORD)?
  1059.                             int_type : long_type;
  1060.                 g_2l2(X_ADD, locn_reg(loc1 -> n_reg2), loc3);
  1061.             }
  1062.         }
  1063.  
  1064.         /* now we have an atreg node, so all we need do is add const */
  1065.         if (g_symbol || i_cnst) {
  1066.             g_2l1(X_ADD, locc, loc3);
  1067.         }
  1068.  
  1069.         TRACEP("resolve",
  1070.             printf("returns (add): ");
  1071.             pr_loc(loc3); printf("\n"));
  1072.  
  1073.         loc3 -> n_cltype = loc1 -> n_cltype;
  1074.         free_xtemp(loc1, loc3);
  1075.         RETURN_PTR("resolve", loc3);
  1076.     }
  1077. }
  1078.  
  1079. /*
  1080.     Touch a loc_node in order to make sure the side effects get
  1081.     done.  Typically what this does is increment the areg involved
  1082.     in a dangling EA_PRD or EA_PSI node, as when the programmer
  1083.     writes
  1084.     *x++;
  1085.     as a complete statement.  This is called by the expression entry
  1086.     point routines on the item which always dangles on the stack when they
  1087.     are about to return.
  1088. */
  1089. void
  1090. x_lookat(register struct node *loc1)
  1091. {
  1092.     register struct node *loc3;
  1093.     long x;
  1094.  
  1095.     TRACEPB("x_lookat", printf("(%p)\n", loc1));
  1096.  
  1097.     switch (loc1 -> n_mode) {
  1098.     case EAPRD_MODE:
  1099.         x = (long) mlen(loc1);
  1100.         if (x == 1 && loc1 -> n_reg1 == R_A7) {
  1101.             x = 2;
  1102.         }
  1103.         loc3 = locn_reg(loc1 -> n_reg1);
  1104.         loc3 -> n_cltype = int_type;
  1105.         g_2l2(X_SUBQ, locn_xconst(x), loc3);
  1106.         break;
  1107.  
  1108.     case EAPSI_MODE:
  1109.         x = (long) mlen(loc1);
  1110.         if (x == 1 && loc1 -> n_reg1 == R_A7) {
  1111.             x = 2;
  1112.         }
  1113.         loc3 = locn_reg(loc1 -> n_reg1);
  1114.         loc3 -> n_cltype = int_type;
  1115.         g_2l2(X_ADDQ, locn_xconst(x), loc3);
  1116.         break;
  1117.     }
  1118.  
  1119.     TICKX("x_lookat");
  1120. }
  1121.  
  1122. /*
  1123.     Conditionally push a node onto the physical stack and return
  1124.     an adjusted node which will work later when popped from the
  1125.     SIMULATION stack.  Unlike resolve(), this is not to draw a temporary.
  1126.  
  1127.     Any node containing no temporary returns NULL.
  1128.  
  1129.     Any node containing a temporary gets resolved and pushed,
  1130.     possibly by PEA.  The temporary is then freed, and the caller
  1131.     may inspect nd_free/na_free to see what it is.
  1132.  
  1133.     The second register is never to be set up except
  1134.     by x_addpsi() and is signed: X2_WORD or X2_LONG.
  1135. */
  1136. struct node *
  1137. x_sspush(register struct node *loc1)
  1138. {
  1139.     register struct node *locx, *locp, *locc, *loc3;
  1140.     register struct st_node *id;
  1141.     register int reg, g_symbol;
  1142.     register long i_cnst;
  1143.     struct type_node *type1;
  1144.  
  1145.     TRACEPB("x_sspush",
  1146.         printf("(%p)\n", loc1);
  1147.         pr_loc(loc1); printf("\n"));
  1148.  
  1149.     if (!has_atreg(loc1) && !has_dtreg(loc1)) {
  1150.         TRACEP("x_sspush", printf("no temp to free\n"));
  1151.         RETURN_PTR("x_sspush", NULL);
  1152.     }
  1153.  
  1154.     /* node contains at least one temporary */
  1155.     loc1 = locn_dupl(loc1);
  1156.         /* this routine might be called again on loc1, so
  1157.             it should not alter loc1 ever */
  1158.  
  1159.     locx = NULL;            /* for exit adjustment !!! */
  1160.     locp = NULL;            /* for addition */
  1161.  
  1162.     /* check symbols */
  1163.     g_symbol = FALSE;
  1164.     i_cnst = loc1 -> n_const;
  1165.     if (id = loc1 -> n_cid) {
  1166.         if (is_rstack(id -> st_sclass) || id->st_sclass == SUE_CLASS) {
  1167.             /* i_cnst is the true value of the const if known */
  1168.             i_cnst += id -> st_offset;
  1169.         }
  1170.         else {
  1171.             /* the true value is unknown and long */
  1172.             g_symbol = TRUE;
  1173.         }
  1174.     }
  1175.     if (!g_symbol && i_cnst == 0 && loc1 -> n_cid) {
  1176.         loc1 -> n_cid = NULL;
  1177.         loc1 -> n_const = 0;
  1178.         TRACEP("x_sspush", printf("consolidate zero\n"));
  1179.     }
  1180.  
  1181.     /* pure register push */
  1182.     if (loc1 -> n_mode == VALUE_MODE && !loc1 -> n_cid &&
  1183.                     !loc1 -> n_const && !loc1 -> n_reg2) {
  1184.         g_2l1(X_MOVE, loc1, push_loc);
  1185.         goto push_adj;
  1186.     }
  1187.  
  1188.     /* at this point, it is shown to be a combined or EA node and 
  1189.         reg1 must be long */
  1190. #ifdef DEBUG
  1191.     if (loc1 -> n_mode == VALUE_MODE && mlen(loc1) < 4) {
  1192.         g_error(loc1, "x_sspush: internal: must not happen");
  1193.  
  1194.         TRACEP("x_sspush",
  1195.             printf("short combined node: ");
  1196.             pr_loc(loc1); printf("\n");
  1197.             pr_type(loc1 -> n_cltype); printf("\n"));
  1198.     }
  1199. #endif /* DEBUG */
  1200.  
  1201.     /* if dual-reg node, put the temporary first; put the areg first
  1202.         if two temporaries */
  1203.     if ( !(is_atreg(loc1 -> n_reg1) || is_dtreg(loc1 -> n_reg1)) || 
  1204.         (is_atreg(loc1 -> n_reg2) && !is_atreg(loc1 -> n_reg1))
  1205.                                 ) {
  1206.         /* switch */
  1207.         reg = loc1 -> n_reg2;
  1208.         loc1 -> n_reg2 = loc1 -> n_reg1;
  1209.         loc1 -> n_reg1 = reg;    /* the areg can be taken as long */
  1210.         if (loc1 -> n_scflag != X2_LONG) {
  1211.             loc1 -> n_scflag = X2_LONG;
  1212.             if (is_dreg(reg)) {
  1213.                 locp = locn_reg(reg);
  1214.                 locp -> n_cltype = long_type;
  1215.                 g_1l2(X_EXT, locp); /* 3/5/89: was g_2l1() */
  1216.             }
  1217.         }
  1218.     }
  1219.     /* a temporary is always first, and is always long */
  1220.  
  1221.     /* if it is EA, we MUST have an areg */
  1222.     /* if second register is short, we must have areg since we may
  1223.         not be able to cast the second register */
  1224.     if (is_dreg(loc1 -> n_reg1) &&
  1225.       (loc1 -> n_scflag != X2_LONG || is_ea(loc1 -> n_mode)) ) {
  1226.         locx = locn_reg(reg);
  1227.         a0_loc -> n_cltype = long_type;
  1228.         g_2(X_EXG, locx, a0_loc);
  1229.         loc1 -> n_reg1 = R_A0;
  1230.     }
  1231.         
  1232.     /* try to pick it up with EA/PEA in one fell swoop */
  1233.     if (!g_symbol && is_areg(loc1 -> n_reg1) &&
  1234.         ( (!loc1->n_reg2 && i_cnst<=32767 && i_cnst >= -32768L) ||
  1235.         (i_cnst <= 127 && i_cnst >= -128) )
  1236.                                     ) {
  1237.         if (is_ea(loc1 -> n_mode)) {
  1238.             g_2l1(X_MOVE, loc1, push_loc);
  1239.         }
  1240.         else {
  1241.             loc1 -> n_mode = EA_MODE;
  1242.             g_2(X_PEA, loc1, push_loc);
  1243.         }
  1244.         goto push_adj;
  1245.     }
  1246.  
  1247.     /* otherwise add it up */
  1248.     if (locp == 0) {
  1249.         locp = locn_reg(loc1 -> n_reg1); /* destination */
  1250.     }
  1251.     if (reg = loc1 -> n_reg2) {
  1252.         locc = locn_reg(reg);
  1253.         locc -> n_cltype = (loc1 -> n_scflag == X2_WORD)?
  1254.                         int_type : long_type;
  1255.         g_2l1(X_ADD, locc, locp);
  1256.     }
  1257.     if (g_symbol || i_cnst) {
  1258.         locc = locn_dupl(loc1);
  1259.         locc -> n_reg1 = locc -> n_reg2 = 0;
  1260.         if (is_areg(locp -> n_reg1) && !g_symbol &&
  1261.                 i_cnst <= 32767 && i_cnst >= -32768L) {
  1262.             locc -> n_cltype = int_type;
  1263.         }
  1264.         else {
  1265.             locc -> n_cltype = long_type;
  1266.         }
  1267.         g_2l1(X_ADD, locc, locp);
  1268.     }
  1269.     locp -> n_cltype = long_type;
  1270.     g_2l1(X_MOVE, locp, push_loc);
  1271.  
  1272. push_adj:
  1273.     if (locx) {
  1274.         g_2(X_EXG, locx, a0_loc);
  1275.         free_reg(locx -> n_reg1);
  1276.     }
  1277.     else {
  1278.         free_reg(loc1 -> n_reg1);
  1279.     }
  1280.  
  1281.     TRACEP("x_sspush",
  1282.         printf("frees %p: ", loc1);
  1283.         pr_loc(loc1); printf("\n"));
  1284.  
  1285.     free_reg(loc1 -> n_reg2);
  1286.     loc1 = locn_xdupl(loc1);
  1287.     loc1 -> n_reg2 = 0;
  1288.     loc1 -> n_reg1 = R_A7;
  1289.     loc1 -> n_mode = EAPSI_MODE;
  1290.     loc1 -> n_cid = NULL;
  1291.     loc1 -> n_const = 0;
  1292.     RETURN_PTR("x_sspush", loc1);
  1293. }
  1294.  
  1295. /*
  1296.  
  1297.     Make markings on the tree as follows:
  1298.  
  1299.     process array into * and + with possible reassociation
  1300.     the tree may be null
  1301. */
  1302. void
  1303. gen_pp(struct node *p)
  1304. {
  1305.     register struct node *q, *r, *r1;
  1306.     register struct type_node *qt;
  1307.     register int op, class;
  1308.  
  1309.     SL_DISABLE();
  1310.  
  1311.     if (p == NULL) {
  1312.         return;
  1313.     }
  1314.     
  1315.     op = p -> n_type;
  1316.  
  1317.     TRACEPB("gen_pp",
  1318.         printf("node = %p->%p: %d %s: ",
  1319.             p, p -> n_cltype, op, ps_tok(op));
  1320.         pr_type(p -> n_cltype); printf("\n"));
  1321.  
  1322.         switch(op = p -> n_type) {
  1323.  
  1324. case CALL_TOK:
  1325.     TRACEP("gen_pp", printf("call\n"));
  1326.     gen_pp(p -> n_arg1);
  1327.     gen_pp(p -> n_arg2);    
  1328.     break;
  1329.  
  1330. case SEPARATOR_TOK:
  1331.     TRACEP("gen_pp", printf("separator\n"));
  1332.     gen_pp(p -> n_car);
  1333.     gen_pp(p -> n_next);    /* the separator */
  1334.     break;
  1335.  
  1336. case ID_TOK:
  1337.     /*
  1338.         place the correct address mode into the id node
  1339.         according to the storage class; the symbol table
  1340.         must of course be correct by now!
  1341.  
  1342.         if there is no ID, the item ought to be a c-language
  1343.         numeric constant, and must be of VALUE_MODE with
  1344.         no registers, and is left unaltered
  1345.     */
  1346.     TRACEP("gen_pp", printf("id: "); pr_loc(p); printf("\n"));
  1347.     if (p -> n_cid) {
  1348.         class = p -> n_cid -> st_sclass;
  1349.         if (p -> n_reg1 == 0) switch(class) {
  1350.         case SUE_CLASS:
  1351.             /* no register content */
  1352.             break;
  1353.  
  1354.         case FORMREG_CLASS:
  1355.             TRACEP("gen_pp", printf("formal register class\n"));
  1356.  
  1357.             p -> n_mode = VALUE_MODE;
  1358.             if (p -> n_cltype && 
  1359.                 p -> n_cltype -> t_typtok != INT_TYPE &&
  1360.                 p -> n_cltype -> t_typtok != POINTER_TYPE) {
  1361.                 g_error(p, "register declared aggregate");
  1362.             }
  1363.             else {
  1364.                 if (p -> n_cid) {
  1365.                     p -> n_reg1 =
  1366.                         p -> n_cid -> st_misc & ST_REG;
  1367.                     p -> n_cid = 0;
  1368.                 }
  1369.                 break;
  1370.             }
  1371.             /* FALL_THROUGH */
  1372.  
  1373.         case FORMAL_CLASS:
  1374.             /*
  1375.                 all FORMALS including arrays are literally 
  1376.                 effective addresses; a formal array is
  1377.                 literally an lvalue pointer to a[0], while
  1378.                 a local or global array is a virtual pointer
  1379.                 having no lvalue.
  1380.             */
  1381.             p -> n_mode = EA_MODE;
  1382.             p -> n_reg1 = R_A6;
  1383.             break;
  1384.  
  1385.         case REGISTER_CLASS:
  1386.             TRACEP("gen_pp", printf("register class\n"));
  1387.             p -> n_mode = VALUE_MODE;
  1388.             if (p -> n_cltype && 
  1389.                 p -> n_cltype -> t_typtok != INT_TYPE &&
  1390.                 p -> n_cltype -> t_typtok != POINTER_TYPE
  1391.                 ) {
  1392.                 g_error(p, "register declared aggregate");
  1393.             }
  1394.             else {
  1395.                 if (p -> n_cid) {
  1396.                     p -> n_reg1 =
  1397.                         p -> n_cid -> st_misc & ST_REG;
  1398.                     p -> n_cid = 0;
  1399.                 }
  1400.                 break;
  1401.             }
  1402.             /* FALL_THROUGH */
  1403.  
  1404.         case AUTO_CLASS:
  1405.             p -> n_reg1 = R_A6;
  1406.             /* FALL_THROUGH */
  1407.         default:
  1408.             if (p -> n_cltype &&
  1409.                 p -> n_cltype -> t_typtok == ARRAY_TYPE) {
  1410.                 p -> n_mode = VALUE_MODE;
  1411.             }
  1412.             else {
  1413.                 p -> n_mode = EA_MODE;
  1414.             }
  1415.         }
  1416.  
  1417.         if (    no_local && p -> n_cid &&
  1418.             (is_rstack(class) || class == SUE_CLASS)
  1419.            ) {
  1420.             TRACEP("gen_pp",printf("fix local/element\n"));
  1421.             p -> n_const += p -> n_cid -> st_offset;
  1422.             p -> n_cid = NULL;
  1423.         }
  1424.     }
  1425.     else if (p -> n_reg1) {
  1426.         TRACEP("gen_pp", printf("manifest register\n"));
  1427.     }
  1428.     TRACEP("gen_pp", printf("->  "); pr_loc(p); printf("\n"));
  1429.     break;
  1430.  
  1431. case ARRAY_TOK:
  1432.     gen_pp(p -> n_arg1);
  1433.     gen_pp(p -> n_arg2);
  1434.  
  1435.     TRACEP("gen_pp", printf("replace ARRAY with * and +\n"));
  1436.     q = node_dupl( (byte *) p, sizeof(struct binop_node));
  1437.     q -> n_type = PLUS_TOK;
  1438.  
  1439.     /* EXISTING node gets CHANGED to * to avoid dangling ptrs */
  1440.     p -> n_type = USTAR_TOK;
  1441.     q -> n_cltype = qt = q -> n_arg1 -> n_cltype;
  1442.  
  1443.     /*
  1444.         CAUTION: there is a tacit assumption here that
  1445.         a unop_node is the same as a binop_node, except
  1446.         for the second arg!!!
  1447.  
  1448.         NOTE: K & R are silent as to which of the following
  1449.         two associations for this operation is correct.
  1450.         They differ in the case that the i + j sum overflows,
  1451.         and the differences depend on one's interpretation
  1452.         of the automatic casting rules.  The DRI compiler
  1453.         does not follow a consistent interpretation.
  1454.     */
  1455.     if (array_opt) {
  1456.         /* association: p[i + j] = *(p + (i + j)) */
  1457.         TRACEP("gen_pp", printf("array strict\n"));
  1458.         p -> n_arg1 = q;
  1459.     }
  1460.     else {
  1461.         /* association: p[i + j] = *(p + i + j) */
  1462.         TRACEP("gen_pp", printf("array reassociation\n"));
  1463.         r1 = NULL;
  1464.         r = p -> n_arg2;    /* the int tree */
  1465.         while (r -> n_type == PLUS_TOK ||
  1466.           (r -> n_type == MINUS_TOK &&
  1467.            r -> n_arg1 -> n_cltype -> t_typtok == INT_TYPE)) {
  1468.             r1 = r;
  1469.             r = r1 -> n_arg1;
  1470.         }
  1471.         if (r1) {
  1472.             q -> n_arg2 = r;
  1473.             r1 -> n_arg1 = q;
  1474.  
  1475.             /* propagate type */
  1476.             for (r = p -> n_arg2; r != q; r = r -> n_arg1) {
  1477.                 r -> n_cltype = qt;
  1478.             }
  1479.  
  1480.             /* set argument of USTAR */
  1481.             p -> n_arg1 = p -> n_arg2;
  1482.         }
  1483.         else {
  1484.             p -> n_arg1 = q;
  1485.         }
  1486.     }
  1487.     break;
  1488.  
  1489. case QUESTION_TOK:
  1490.     TRACEP("gen_pp", printf("ternop\n"));
  1491.     gen_pp(p -> n_arg1);
  1492.     gen_pp(p -> n_arg2);
  1493.     gen_pp(p -> n_arg3);
  1494.  
  1495.     TRACEP("gen_pp",
  1496.         printf("node = %p again: %d %s\n", p, op, ps_tok(op));
  1497.         pr_expr(p);printf("\n"));
  1498.  
  1499. default:
  1500.     if (is_unop(op)) {
  1501.         TRACEP("gen_pp", printf("unop\n"));
  1502.         gen_pp(p -> n_arg1);
  1503.  
  1504.         TRACEP("gen_pp",
  1505.             printf("node = %p again: %d %s\n", p, op, ps_tok(op));
  1506.             pr_expr(p);printf("\n"));
  1507.     }
  1508.     else if (is_binop(op)) {
  1509.         TRACEP("gen_pp", printf("binop\n"));
  1510.         gen_pp(p -> n_arg1);
  1511.         gen_pp(p -> n_arg2);
  1512.  
  1513.         TRACEP("gen_pp",
  1514.             printf("node = %p again: %d %s\n", p, op, ps_tok(op));
  1515.             pr_expr(p); printf("\n");
  1516.             pr_type(p -> n_cltype); printf("\n"));
  1517.     }
  1518.     else {
  1519.         TRACEP("gen_pp", printf("unknown op"));
  1520.     }
  1521.     break;
  1522.  
  1523.     } /* End switch. */
  1524.  
  1525.     TICKX("gen_pp");
  1526. }
  1527.