home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Harvest C 1.3 / Source Code / genexpr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-15  |  37.9 KB  |  1,204 lines  |  [TEXT/ALFA]

  1. /*
  2.     Harvest C
  3.     Copyright 1992 Eric W. Sink.  All rights reserved.
  4.     
  5.     This file is part of Harvest C.
  6.     
  7.     Harvest C is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU Generic Public License as published by
  9.     the Free Software Foundation; either version 2, or (at your option)
  10.     any later version.
  11.     
  12.     Harvest C is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.     
  17.     You should have received a copy of the GNU General Public License
  18.     along with Harvest C; see the file COPYING.  If not, write to
  19.     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.     
  21.     Harvest C is not in any way a product of the Free Software Foundation.
  22.     Harvest C is not GNU software.
  23.     Harvest C is not public domain.
  24.  
  25.     This file may have other copyrights which are applicable as well.
  26.  
  27. */
  28.  
  29. /*
  30.  * Harvest C
  31.  * 
  32.  * Copyright 1991 Eric W. Sink   All rights reserved.
  33.  * 
  34.  * This file contains routines for 68k code generation. These routines generate
  35.  * code for expressions.
  36.  * 
  37.  * 
  38.  * 
  39.  */
  40.  
  41.  
  42. #include "conditcomp.h"
  43. #include <stdio.h>
  44. #include <string.h>
  45. #include "structs.h"
  46.  
  47. #include "CHarvestDoc.h"
  48. #include "CHarvestOptions.h"
  49.  
  50. extern CHarvestDoc *gProject;
  51.  
  52. #pragma segment GenExpr
  53.  
  54.  
  55. void
  56. GenTrapWordsRecurse(ParseTreeVia_t init, InstListVia_t Codes)
  57. {
  58.     FoldValue_t                     thek;
  59.     if (init) {
  60.         if (Via(init)->b) {
  61.             GenTrapWordsRecurse(Via(init)->b,Codes);
  62.         }
  63.         ConstExprValue(init, &thek);
  64.         GenInst(M68op_DC, M68sz_word,BuildAbsolute(thek.intval), NULL, Codes);
  65.     }
  66. }
  67.  
  68. void
  69. GenTrapWords(ParseTreeVia_t init, InstListVia_t Codes)
  70. {
  71.     FoldValue_t                     thek;
  72.     if (Via(init)->kind == PTF_multi_initializer) {
  73.         init = Via(init)->a;
  74.         GenTrapWordsRecurse(init,Codes);    /* They're backwards */
  75.     } else {
  76.         ConstExprValue(init, &thek);
  77.         GenInst(M68op_DC, M68sz_word,BuildAbsolute(thek.intval), NULL, Codes);
  78.     }
  79. }
  80.  
  81. LocAMVia_t
  82. ParamLoc(int x)
  83. {
  84.     switch (x) {
  85.     case param__A0:
  86.     return BuildARegDirect(0);
  87.     break;
  88.     case param__A1:
  89.     return BuildARegDirect(1);
  90.     break;
  91.     case param__D0:
  92.     return BuildDRegLocation(0);
  93.     break;
  94.     case param__D1:
  95.     return BuildDRegLocation(0);
  96.     break;
  97.     case param__D2:
  98.     return BuildDRegLocation(0);
  99.     break;
  100.     case 0:
  101.     default:
  102.     return NULL;
  103.     }
  104. }
  105.  
  106. LocAMVia_t
  107. GenFunctionCall(ParseTreeVia_t expr, InstListVia_t Codes)
  108. {
  109.     LocAMVia_t                      result;
  110.     LocAMVia_t                      ParamReturn;
  111.     LabSYMVia_t                     funcname;
  112.     TypeRecordVia_t                 functype;
  113.     LocAMVia_t                      funcloc;
  114.     int                             SumArgs;
  115.     SpillSlotVia_t                  bigresult;
  116.     SpillSlotVia_t                  ptrslot;
  117.     int                             discardit;
  118.     discardit = 0;
  119.     result = NULL;
  120.     ParamReturn = NULL;
  121.     /*
  122.      * Discarded function call indicates that the result of this function is
  123.      * not needed, so we will not bother to allocate a place to store it.
  124.      */
  125.     if (DiscardedFunctionCall) {
  126.         DiscardedFunctionCall = 0;
  127.         discardit = 1;
  128.     }
  129.     /*
  130.      * Struct valued functions are tricky.  We cannot return a struct in D0,
  131.      * so we pass the called function a pointer to a place to put it.
  132.      */
  133.     bigresult = NULL;
  134.     if (isStructUnionType(GetTreeTP(expr)) && (GetTPSize(GetTreeTP(expr)) > 4)) {
  135.         bigresult = GetSpillSlot(GetTPSize(GetTreeTP(expr)));
  136.     }
  137.     functype = Via(expr)->data.TP;
  138.     if (!functype) {
  139.         Gen68Error("Generating function call for non function");
  140.     }
  141.     SaveTheRegisters(Codes);
  142.     if (GetTPParam(functype)) {
  143.         if (Via(GetTPParam(functype))->returnreg)
  144.             ParamReturn = ParamLoc(Via(GetTPParam(functype))->returnreg);
  145.     }
  146.     if (GetTPFlags(functype) & ISPASCALMASK) {
  147.     /*
  148.      * If this is a pascal function, we must allocate space on the stack
  149.      * for the result
  150.      */
  151.     if (!ParamReturn)
  152.         if (!(isVoidType(GetTreeTP(expr)))) {
  153.         if (GetTPSize(GetTreeTP(expr))) {    /* TODO Disallow returns
  154.                              * of struct/double for
  155.                              * pascal */
  156.             if (GetTPSize(GetTreeTP(expr)) == 1)
  157.             GenInst(M68op_SUB, M68sz_long,
  158.                 BuildImmediate(2, M68sz_long),
  159.                 BuildARegDirect(7), Codes);
  160.             else
  161.             GenInst(M68op_SUB, M68sz_long,
  162.                 BuildImmediate(GetTPSize(GetTreeTP(expr)), M68sz_long),
  163.                 BuildARegDirect(7), Codes);
  164.         }
  165.         }
  166.     }
  167.     /*
  168.      * Push arguments onto the stack.  Each argument is evaluated before
  169.      * being pushed, in PushArguments()
  170.      */
  171.     SumArgs = PushArguments(expr, (GetTPFlags(functype) &
  172.                 ISPASCALMASK), GetTPParam(functype), Codes);
  173.     /* Here, all registers should be free. */
  174.     /*
  175.      * Generate the jsr instruction. The handling of relative branches is not
  176.      * currently done here. For the Mac, this jsr will have to be converted
  177.      * to a jsr (jumptable)a5 address.
  178.      */
  179.     /*
  180.      * If the routine is struct/double valued function, we allocate a spill
  181.      * zone to contain the result, and push a pointer to that spill zone as
  182.      * the LAST argument pushed.  The Sun handles this by moving the pointer
  183.      * into A1 instead.
  184.      */
  185.     if (isStructUnionType(GetTreeTP(expr)) && (GetTPSize(GetTreeTP(expr)) > 4)) {
  186.         GenPushEA(Via(bigresult)->SlotLoc, Codes);
  187.         SumArgs += 4;
  188.     }
  189.     funcname = NULL;
  190.     funcloc = NULL;
  191.     /* This code is UGLY */
  192.     if (Via(Via(expr)->a)->kind == PTF_gen_addrof) {
  193.         if (Via(Via(Via(expr)->a)->a)->kind == PTF_identifier) {
  194.             funcloc = Via(Via(Via(Via(expr)->a)->a)->data.thesymbol)->M68kDef.Loc;
  195.         }
  196.     }
  197.     if (!funcloc) {
  198.         LocAMVia_t                      thru;
  199.         LocAMVia_t                      ind;
  200.         thru = GenExpression(Via(expr)->a, Codes);
  201.         ind = TempAddrReg(Codes);
  202.         Genmove(GetLocSZ(thru), thru, ind, Codes);
  203.         funcloc = BuildARegIndirect(GetLocAReg(ind));
  204.     }
  205.     if (!(GetTPTrap(functype))) {
  206.         GenInst(M68op_JSR, M68sz_none,funcloc, NULL, Codes);
  207.     } else {
  208.         GenTrapWords(GetTPTrap(functype), Codes);
  209.     }
  210.     FreeTemp(funcloc);
  211.     /* Fix the stack... */
  212.     if (SumArgs) {
  213.         if (!(GetTPFlags(functype) & ISPASCALMASK)) {
  214.             /* MOTOM ADD Should be ADDA */
  215.             GenInst(M68op_ADD, M68sz_long,
  216.                 BuildImmediate(SumArgs, M68sz_long),
  217.                 BuildARegDirect(7), Codes);
  218.         }
  219.     }
  220.     /* Now do something about the return value */
  221.     if (isStructUnionType(GetTreeTP(expr)) && (GetTPSize(GetTreeTP(expr)) > 4)) {
  222.         result = Via(bigresult)->SlotLoc;
  223.     } else if (isFloatingType(GetTreeTP(expr))) {
  224.         /*
  225.          * Allocate a spill slot, and move the contents of d0-d1-a0 to it.
  226.          * This follows the return conventions of the MPW C compiler,
  227.          * documented in the MPW C manual appendix C, page 187 version 3.1
  228.          */
  229.         LocAMVia_t                      half2;
  230.         bigresult = GetSpillSlot(SizeOfLongDouble);
  231.         Genmove(M68sz_word, BuildDRegLocation(0), Via(bigresult)->SlotLoc, Codes);
  232.         half2 = BuildARegDisplace(GetLocAReg(Via(bigresult)->SlotLoc),
  233.                        GetLocConstant(Via(bigresult)->SlotLoc) + 2);
  234.         Genmove(M68sz_long, BuildDRegLocation(1), half2,
  235.             Codes);
  236.         half2 = BuildARegDisplace(GetLocAReg(Via(bigresult)->SlotLoc),
  237.                        GetLocConstant(Via(bigresult)->SlotLoc) + 6);
  238.         Genmove(M68sz_long, BuildARegDirect(0), half2,
  239.             Codes);
  240.         result = Via(bigresult)->SlotLoc;
  241.         SetLocSZ(result, M68_TypeSize(GetTreeTP(expr)));
  242.     } else if (discardit || isVoidType(GetTreeTP(expr))) {
  243.         result = NULL;
  244.     } else {
  245.         /*
  246.          * Function results are always returned in D0. Pascal calling
  247.          * conventions are an exception.
  248.          */
  249.         if (ParamReturn) {
  250.             result = TempDataReg(Codes);
  251.             SetLocSZ(result, M68_TypeSize(GetTreeTP(expr)));
  252.             Genmove(GetLocSZ(result), ParamReturn, result, Codes);
  253.         } else {
  254.             if ((GetTPFlags(functype) & ISPASCALMASK)) {
  255.                 LocAMVia_t                      spinc;
  256.                 spinc = BuildARegPostInc(7);
  257.                 result = TempDataReg(Codes);
  258.                 SetLocSZ(result, M68_TypeSize(GetTreeTP(expr)));
  259.                 Genmove(GetLocSZ(result), spinc, result, Codes);
  260.                 if (GetLocSZ(result) == M68sz_byte) {
  261.                     GenInst(M68op_EXT, M68sz_word, result, NULL, Codes);
  262.                     GenInst(M68op_EXT, M68sz_long, result, NULL, Codes);
  263.                     SetLocSZ(result, M68sz_long);
  264.                 }
  265.                 if (GetLocSZ(result) == M68sz_word) {
  266.                     GenInst(M68op_EXT, M68sz_long, result, NULL, Codes);
  267.                     SetLocSZ(result, M68sz_long);
  268.                 }
  269.             } else {
  270.                 result = TempDataReg(Codes);
  271.                 if (GetLocDReg(result) != 0) {
  272.                     Genmove(M68_TypeSize(GetTreeTP(expr)), BuildDRegLocation(0), result, Codes);
  273.                 }
  274.                 SetLocSZ(result, M68_TypeSize(GetTreeTP(expr)));
  275.                 if (GetLocSZ(result) == M68sz_byte) {
  276.                     GenInst(M68op_EXT, M68sz_word, result, NULL, Codes);
  277.                     GenInst(M68op_EXT, M68sz_long, result, NULL, Codes);
  278.                     SetLocSZ(result, M68sz_long);
  279.                 }
  280.                 if (GetLocSZ(result) == M68sz_word) {
  281.                     GenInst(M68op_EXT, M68sz_long, result, NULL, Codes);
  282.                     SetLocSZ(result, M68sz_long);
  283.                 }
  284.             }
  285.         }
  286.     }
  287.     return result;
  288. }
  289.  
  290. LocAMVia_t
  291. GenLogicalOr(ParseTreeVia_t left, ParseTreeVia_t right,
  292.          InstListVia_t Codes)
  293. {
  294.     LocAMVia_t                      result;
  295.     LabSYMVia_t                     Maketrue;
  296.     LabSYMVia_t                     DoneLabel;
  297.     Maketrue = MakeEccLabel(NextEccLabel++);
  298.     DoneLabel = MakeEccLabel(NextEccLabel++);
  299.  
  300.     GenCompareNonZero(left, Maketrue, Codes);
  301.     GenCompareNonZero(right, Maketrue, Codes);
  302.     result = TempDataReg(Codes);
  303.     SetLocSZ(result, M68sz_long);
  304.     GenInst(M68op_MOVEQ, M68sz_none, BuildImmediate(0, M68sz_long), result, Codes);
  305.     GenInst(M68op_BRA, M68sz_none, BuildLabelLoc(DoneLabel), NULL, Codes);
  306.     GenLabel(Maketrue, Codes);
  307.     GenInst(M68op_MOVEQ, M68sz_none,
  308.         BuildImmediate(1, M68sz_long),
  309.         result, Codes);
  310.     GenLabel(DoneLabel, Codes);
  311.     if (gProject->itsOptions->int2byte)
  312.     SetLocSZ(result, 2);
  313.     else
  314.     SetLocSZ(result, 4);
  315.     return result;
  316. }
  317.  
  318. LocAMVia_t
  319. GenLogicalAnd(ParseTreeVia_t left, ParseTreeVia_t right,
  320.           InstListVia_t Codes)
  321. {
  322.     LocAMVia_t                      result;
  323.     LabSYMVia_t                     Makefalse;
  324.     LabSYMVia_t                     DoneLabel;
  325.     Makefalse = MakeEccLabel(NextEccLabel++);
  326.     DoneLabel = MakeEccLabel(NextEccLabel++);
  327.  
  328.     GenCompareZero(left, Makefalse, Codes);
  329.     GenCompareZero(right, Makefalse, Codes);
  330.     result = TempDataReg(Codes);
  331.     SetLocSZ(result, M68sz_long);
  332.     GenInst(M68op_MOVEQ, M68sz_none,
  333.         BuildImmediate(1, M68sz_long),
  334.         result, Codes);
  335.     GenInst(M68op_BRA, M68sz_none, BuildLabelLoc(DoneLabel), NULL, Codes);
  336.     GenLabel(Makefalse, Codes);
  337.     GenInst(M68op_MOVEQ, M68sz_none, BuildImmediate(0, M68sz_long), result, Codes);
  338.     GenLabel(DoneLabel, Codes);
  339.     if (gProject->itsOptions->int2byte)
  340.     SetLocSZ(result, 2);
  341.     else
  342.     SetLocSZ(result, 4);
  343.     return result;
  344. }
  345.  
  346. LocAMVia_t
  347. GenTernary(ParseTreeVia_t cond,
  348.        ParseTreeVia_t trueval,
  349.        ParseTreeVia_t falseval,
  350.        InstListVia_t Codes)
  351. {
  352.     LocAMVia_t                      result;
  353.     LocAMVia_t                      exprop;
  354.     LabSYMVia_t                     Makefalse;
  355.     LabSYMVia_t                     DoneLabel;
  356.     SpillSlotVia_t                  slot;
  357.     /*
  358.      * The temp value here is held in a spill slot instead of a register to
  359.      * avoid problems with reg allocation.
  360.      */
  361.     slot = GetSpillSlot(M68_TypeSize(GetTreeTP(trueval)));
  362.     result = Via(slot)->SlotLoc;
  363.     SetLocSZ(result, M68sz_long);
  364.     Makefalse = MakeEccLabel(NextEccLabel++);
  365.     DoneLabel = MakeEccLabel(NextEccLabel++);
  366.     GenCompareZero(cond, Makefalse, Codes);
  367.     exprop = GenExpression(trueval, Codes);
  368.     Genmove(M68_TypeSize(GetTreeTP(trueval)), exprop, result, Codes);
  369.     FreeTemp(exprop);
  370.     GenInst(M68op_BRA, M68sz_none, BuildLabelLoc(DoneLabel), NULL, Codes);
  371.     GenLabel(Makefalse, Codes);
  372.     exprop = GenExpression(falseval, Codes);
  373.     Genmove(M68_TypeSize(GetTreeTP(falseval)), exprop, result, Codes);
  374.     FreeTemp(exprop);
  375.     GenLabel(DoneLabel, Codes);
  376.     SetLocSZ(result, M68_TypeSize(GetTreeTP(trueval)));
  377.     return result;
  378. }
  379.  
  380. LocAMVia_t
  381. GenLogicalNegate(ParseTreeVia_t expr, InstListVia_t Codes)
  382. {
  383.     LocAMVia_t                      result;
  384.     LabSYMVia_t                     Makefalse;
  385.     LabSYMVia_t                     DoneLabel;
  386.     Makefalse = MakeEccLabel(NextEccLabel++);
  387.     DoneLabel = MakeEccLabel(NextEccLabel++);
  388.     GenCompareNonZero(expr, Makefalse, Codes);
  389.     result = TempDataReg(Codes);
  390.     SetLocSZ(result, M68sz_long);
  391.     GenInst(M68op_MOVEQ, M68sz_none,
  392.         BuildImmediate(1, M68sz_long), result, Codes);
  393.     GenInst(M68op_BRA, M68sz_none,
  394.         BuildLabelLoc(DoneLabel), NULL, Codes);
  395.     GenLabel(Makefalse, Codes);
  396.     GenInst(M68op_MOVEQ, M68sz_none, BuildImmediate(0, M68sz_long), result, Codes);
  397.     GenLabel(DoneLabel, Codes);
  398.     SetLocSZ(result, M68_TypeSize(GetTreeTP(expr)));
  399.     return result;
  400. }
  401.  
  402. LocAMVia_t
  403. GenRelational(Opcode_t OP, ParseTreeVia_t left, ParseTreeVia_t right,
  404.           InstListVia_t Codes)
  405. {
  406.     LabSYMVia_t                     TrueLabelSym;
  407.     LabSYMVia_t                     EndLabelSym;
  408.     LocAMVia_t                      result;
  409.     /*
  410.      * The OP argument is the Bcc instruction which is appropriate for
  411.      * whatever relational we are doing.
  412.      */
  413.     /* The only possibilities for OP are BEQ,BNE,BLE,BGE,BLT,BGT */
  414.  
  415.  
  416.     TrueLabelSym = MakeEccLabel(NextEccLabel++);
  417.     EndLabelSym = MakeEccLabel(NextEccLabel++);
  418.  
  419.     GenCompareBranch(left, right, OP, TrueLabelSym, Codes);
  420.  
  421.     /* QQQQ Can we used Scc instead of this mess ? */
  422.     /* This is the false case - we clear the result register. */
  423.     result = TempDataReg(Codes);
  424.  
  425.     GenInst(M68op_MOVEQ, M68sz_none, BuildImmediate(0, M68sz_long), result, Codes);
  426.     /* Jump over the true case. */
  427.     GenInst(M68op_BRA, M68sz_none,
  428.         BuildLabelLoc(EndLabelSym), NULL, Codes);
  429.     GenLabel(TrueLabelSym, Codes);
  430.     /* This is the true case. */
  431.     GenInst(M68op_MOVEQ, M68sz_none,
  432.         BuildImmediate(1, M68sz_long), result, Codes);
  433.     GenLabel(EndLabelSym, Codes);
  434.     if (gProject->itsOptions->int2byte)
  435.     SetLocSZ(result, 2);
  436.     else
  437.     SetLocSZ(result, 4);
  438.     return result;
  439. }
  440.  
  441. LocAMVia_t
  442. GenbitTwoOp(Opcode_t OP,
  443.         ParseTreeVia_t left, ParseTreeVia_t right, InstListVia_t Codes)
  444. {
  445.     /* Integers only */
  446.     LocAMVia_t                      leftop;
  447.     LocAMVia_t                      rightop;
  448.     leftop = GenExpression(left, Codes);
  449.     rightop = GenExpression(right, Codes);
  450.     leftop = DictateTempDReg(leftop, Codes);
  451.     rightop = DictateAnyDReg(rightop, Codes);
  452.     /*
  453.      * Careful with the Size specification here !  This could be all wrong
  454.      * with respect to shifts and legal addressingmodes - same for >>= and
  455.      * <<= elsewhere in the code...
  456.      */
  457.     GenDeConflictize(&leftop, &rightop, Codes);
  458.     GenInst(OP, GetLocSZ(leftop), rightop, leftop, Codes);
  459.     FreeTemp(rightop);
  460.     return leftop;
  461. }
  462.  
  463. /*
  464.  * General notes about SANE math.  For any SANE call, we must push both
  465.  * operands, with the destination on top (ie push src first, dest second).
  466.  * These operands must be in the form of a pointer to a range of memory
  467.  * holding the floating point number.  In the case of the destination, this
  468.  * must always be an extended number. Therefore, destination operands for
  469.  * SANE calls must always be a float temp spill slot.  The format of the
  470.  * source operand may be extended, double, single, 16bit int, or 32 bit int.
  471.  */
  472. LocAMVia_t
  473. GenTwoOp(Opcode_t OP,
  474.      ParseTreeVia_t left, ParseTreeVia_t right, InstListVia_t Codes)
  475. {
  476.     /* The possibilities for OP are ADD, SUB, AND, OR */
  477.     LocAMVia_t                      result;
  478.     LocAMVia_t                      leftop;
  479.     LocAMVia_t                      rightop;
  480.     LocAMVia_t                      multiplier;
  481.     rightop = GenExpression(right, Codes);
  482.     leftop = GenExpression(left, Codes);
  483.  
  484.     if (isFloatingType(GetTreeTP(left))) {
  485.     /*
  486.      * In the case of floating math, we need to switch on OP to find out
  487.      * what ops we should really generate.
  488.      */
  489.     leftop = DictateTempFloat(leftop, Codes);    /* Make sure leftop is
  490.                              * in a temp. */
  491.     if (gProject->itsOptions->useMC68881) {
  492.         switch (OP) {
  493.         case M68op_ADD:
  494.         GenInst(M68op_FADD, GetLocSZ(rightop), rightop, leftop,
  495.             Codes);
  496.         break;
  497.         case M68op_SUB:
  498.         GenInst(M68op_FSUB, GetLocSZ(rightop), rightop, leftop,
  499.             Codes);
  500.         break;
  501.         }
  502.     } else {
  503.         rightop = DictateTempFloat(rightop, Codes);
  504.         switch (OP) {
  505.         case M68op_ADD:
  506.         GenSANECall(FFEXT + FOADD, rightop, leftop, Codes);
  507.         break;
  508.         case M68op_SUB:
  509.         GenSANECall(FFEXT + FOSUB, rightop, leftop, Codes);
  510.         break;
  511.         }
  512.     }
  513.     FreeTemp(rightop);
  514.     result = leftop;
  515.     } else {
  516.     if (isUnsignedType(GetTreeTP(left))) {
  517.         leftop = DictateTempDReg(leftop, Codes);
  518.         GenDeConflictize(&leftop, &rightop, Codes);
  519.         GenInst(OP, GetLocSZ(leftop), rightop, leftop, Codes);
  520.         FreeTemp(rightop);
  521.         result = leftop;
  522.     } else if (isPointerType(GetTreeTP(left))) {
  523.         if (isIntegralType(GetTreeTP(right))) {
  524.         leftop = DictateTempAReg(leftop, Codes);
  525.         rightop = DictateTempDReg(rightop, Codes);
  526.         if (GetTPSize(GetTPBase(GetTreeTP(left))) != 1) {
  527.             multiplier = BuildImmediate(GetTPSize(GetTPBase(GetTreeTP(left))),
  528.                         M68sz_long);
  529.             multiplier = DictateTempDReg(multiplier, Codes);
  530.             rightop = GenMulSigned(M68op_MULS, rightop, multiplier, Codes);
  531.             FreeTemp(multiplier);
  532.         }
  533.         GenDeConflictize(&leftop, &rightop, Codes);
  534.         GenInst(OP, M68sz_long, rightop, leftop, Codes);
  535.         FreeTemp(rightop);
  536.         result = leftop;
  537.         } else {
  538.         leftop = DictateTempAReg(leftop, Codes);
  539.         GenDeConflictize(&leftop, &rightop, Codes);
  540.         GenInst(OP, M68sz_long, rightop, leftop, Codes);
  541.         FreeTemp(rightop);
  542.         result = leftop;
  543.         }
  544.     } else if (isPointerType(GetTreeTP(right))) {
  545.         if (isIntegralType(GetTreeTP(left))) {
  546.         rightop = DictateTempAReg(rightop, Codes);
  547.         leftop = DictateTempDReg(leftop, Codes);
  548.         if (GetTPSize(GetTPBase(GetTreeTP(right))) != 1) {
  549.             multiplier = BuildImmediate(GetTPSize(GetTPBase(GetTreeTP(right))),
  550.                         M68sz_long);
  551.             multiplier = DictateTempDReg(multiplier, Codes);
  552.             leftop = GenMulSigned(M68op_MULS, leftop, multiplier, Codes);
  553.             FreeTemp(multiplier);
  554.         }
  555.         GenDeConflictize(&leftop, &rightop, Codes);
  556.         GenInst(OP, M68sz_long, leftop, rightop, Codes);
  557.         FreeTemp(rightop);
  558.         result = leftop;
  559.         } else {
  560.         rightop = DictateTempAReg(rightop, Codes);
  561.         GenDeConflictize(&leftop, &rightop, Codes);
  562.         GenInst(OP, M68sz_long, leftop, rightop, Codes);
  563.         FreeTemp(leftop);
  564.         result = rightop;
  565.         }
  566.     } else {
  567.         leftop = DictateTempDReg(leftop, Codes);
  568.         GenDeConflictize(&leftop, &rightop, Codes);
  569.         GenInst(OP, GetLocSZ(leftop), rightop, leftop, Codes);
  570.         FreeTemp(rightop);
  571.         result = leftop;
  572.     }
  573.     }
  574.     return result;
  575. }
  576.  
  577. /*
  578.  * The subject of 32 bit multiplication and division.  ECC generates, by
  579.  * default, code which will work on a 68010 processor. The 68010 does not
  580.  * support 32 bit mult/div.  Therefore, something special must be done to
  581.  * handle these cases.  The routine GenLibraryCall, appearing below, is the
  582.  * solution when running under Sun UNIX.  It accepts the two operands as
  583.  * arguments, and a label corresponding to a subroutine defined elsewhere. It
  584.  * moves the left operand into D0 and the right operand into D1, and calls
  585.  * the routine, anticipating a result in D0, which it returns in a spill
  586.  * slot.  The other possibilities for handling long math are : use 16 bit
  587.  * math (generally undesirable), use the 68020 muls.l instruction (this
  588.  * should be a compiler option), use some other library orutine other than
  589.  * Sun's. This third possibility will have to be the default when this
  590.  * compiler becomes a real Mac compiler.  I will probably have to code these
  591.  * routines myself.  I have two examples from which I can refer: the c68
  592.  * libraries from the MINIX compiler, and the libraries for PDC.  In any
  593.  * case, there are 8 occasions in the code generator wherein long mult/div
  594.  * must be done.  Actually there are four occasions, each of them needing to
  595.  * be handled both for signed and unsigned math : modassign (%=), modulo (%),
  596.  * muldiv (* or /), and muldivassign (*= or /=).  All four methods for
  597.  * generating long mul/div should be available at each of these 8 sites. In
  598.  * addition, a decision needs to be made about the default conditions, and
  599.  * which options take precedence over which others.  For example, when the
  600.  * compiler is in Macintosh mode (options for this mode need to be created
  601.  * yet), the default will be to generate calls to the libraries appropriate
  602.  * for the Mac (which I may have to write).  However, if the use68020 switch
  603.  * is on, we should generate muls.l instructions, even though we are in Mac
  604.  * mode.
  605.  */
  606.  
  607.  
  608.  
  609. LocAMVia_t
  610. GenModulo(ParseTreeVia_t left,
  611.       ParseTreeVia_t right, InstListVia_t Codes)
  612. {
  613.     /* Integer only. */
  614.     LocAMVia_t                      leftop;
  615.     LocAMVia_t                      rightop;
  616.     leftop = GenExpression(left, Codes);
  617.     rightop = GenExpression(right, Codes);
  618.     if (isUnsignedType(GetTreeTP(left))) {
  619.     if (GetTPSize(GetTreeTP(left)) > 2) {
  620.         if (!gProject->itsOptions->useMC68020) {
  621.         leftop = GenLibraryCall(leftop, rightop,
  622.                     LibLabelULMODT, Codes);
  623.         FreeTemp(rightop);
  624.         } else {
  625.         /*
  626.          * We currently do long mod with library even in 68020 mode.
  627.          */
  628.         leftop = GenLibraryCall(leftop, rightop,
  629.                     LibLabelULMODT, Codes);
  630.         FreeTemp(rightop);
  631.         }
  632.     } else {
  633.         leftop = DictateTempDReg(leftop, Codes);
  634.         rightop = DictateTempDReg(rightop, Codes);
  635.         GenInst(M68op_DIVU, M68sz_none, rightop, leftop, Codes);
  636.         GenInst(M68op_SWAP, M68sz_none, leftop, NULL, Codes);
  637.         GenInst(M68op_EXT, M68sz_long, leftop, NULL, Codes);
  638.         FreeTemp(rightop);
  639.     }
  640.     } else {
  641.     if (GetTPSize(GetTreeTP(left)) > 2) {
  642.         if (!gProject->itsOptions->useMC68020) {
  643.         leftop = GenLibraryCall(leftop, rightop,
  644.                     LibLabelLMODT, Codes);
  645.         } else {
  646.         /*
  647.          * We currently do long mod with library even in 68020 mode.
  648.          */
  649.         leftop = GenLibraryCall(leftop, rightop,
  650.                     LibLabelLMODT, Codes);
  651.         }
  652.     } else {
  653.         leftop = DictateTempDReg(leftop, Codes);
  654.         rightop = DictateTempDReg(rightop, Codes);
  655.         GenInst(M68op_DIVS, M68sz_none, rightop, leftop, Codes);
  656.         GenInst(M68op_SWAP, M68sz_none, leftop, NULL, Codes);
  657.         GenInst(M68op_EXT, M68sz_long, leftop, NULL, Codes);
  658.     }
  659.     }
  660.     FreeTemp(rightop);
  661.     return leftop;
  662. }
  663.  
  664. LocAMVia_t
  665. GenMulDiv(Opcode_t OP, ParseTreeVia_t left,
  666.       ParseTreeVia_t right, InstListVia_t Codes)
  667. {
  668.     LocAMVia_t                      leftop;
  669.     LocAMVia_t                      rightop;
  670.     /* The possibilities for OP here are MULS and DIVS */
  671.     leftop = GenExpression(left, Codes);
  672.     rightop = GenExpression(right, Codes);
  673.     if (isFloatingType(GetTreeTP(left))) {
  674.     if (gProject->itsOptions->useMC68881) {
  675.         leftop = DictateTempFloat(leftop, Codes);
  676.         if (isShortFloatingType(GetTreeTP(left))) {
  677.         switch (OP) {
  678.         case M68op_MULS:
  679.             GenInst(M68op_FSGLMUL, M68sz_single, rightop, leftop, Codes);
  680.             break;
  681.         case M68op_DIVS:
  682.             GenInst(M68op_FSGLDIV, M68sz_single, rightop, leftop, Codes);
  683.             break;
  684.         default:
  685.             Gen68Error("Illegal opcode in gen68_muldiv for floats");
  686.             break;
  687.         }
  688.         } else {
  689.         switch (OP) {
  690.         case M68op_MULS:
  691.             GenInst(M68op_FMUL, GetLocSZ(rightop), rightop, leftop, Codes);
  692.             break;
  693.         case M68op_DIVS:
  694.             GenInst(M68op_FDIV, GetLocSZ(rightop), rightop, leftop, Codes);
  695.             break;
  696.         }
  697.         }
  698.     } else {
  699.         leftop = DictateTempFloat(leftop, Codes);
  700.         rightop = DictateTempFloat(rightop, Codes);
  701.         switch (OP) {
  702.         case M68op_MULS:
  703.         GenSANECall(FFEXT + FOMUL, rightop, leftop, Codes);
  704.         break;
  705.         case M68op_DIVS:
  706.         GenSANECall(FFEXT + FODIV, rightop, leftop, Codes);
  707.         break;
  708.         }
  709.     }
  710.     } else {
  711.     if (isUnsignedType(GetTreeTP(left))) {
  712.         leftop = GenMulUnsigned(OP, leftop, rightop, Codes);
  713.     } else {
  714.         leftop = GenMulSigned(OP, leftop, rightop, Codes);
  715.     }
  716.     }
  717.     FreeTemp(rightop);
  718.     return leftop;
  719. }
  720.  
  721. LocAMVia_t
  722. GenSubscript(ParseTreeVia_t expr,
  723.          InstListVia_t Codes)
  724. {
  725.     LocAMVia_t                      result;
  726.     LocAMVia_t                      baseop;
  727.     LocAMVia_t                      subop;
  728.     LocAMVia_t                      multiplier;
  729.     FoldValue_t                     testK;
  730.     baseop = GenExpression(Via(expr)->a, Codes);
  731.     ConstExprValue(Via(expr)->b, &testK);
  732.     if (testK.isK) {
  733.     int                             offset;
  734.     offset = GetTPSize(GetTPBase(GetTreeTP(Via(expr)->a))) * testK.intval;
  735.     baseop = DictateTempAReg(baseop, Codes);
  736.     if (offset) {
  737.         subop = BuildImmediate(offset, M68sz_long);
  738.         /* MOTOM Should be ADDA */
  739.         GenInst(M68op_ADD, M68sz_long, subop, baseop, Codes);
  740.         FreeTemp(subop);
  741.     }
  742.     } else {
  743.     subop = GenExpression(Via(expr)->b, Codes);
  744.     subop = DictateTempDReg(subop, Codes);
  745.     if (GetTPSize(GetTPBase(GetTreeTP(Via(expr)->a))) != 1) {
  746.         multiplier = BuildImmediate(GetTPSize(GetTPBase(GetTreeTP(Via(expr)->a))),
  747.                     GetLocSZ(subop));
  748.         subop = GenMulSigned(M68op_MULS, subop, multiplier, Codes);
  749.         FreeTemp(multiplier);
  750.     }
  751.     if (GetLocSZ(subop) != M68sz_long) {
  752.         GenInst(M68op_EXT, M68sz_long, subop, NULL, Codes);
  753.     }
  754.     baseop = DictateTempAReg(baseop, Codes);
  755.     /* MOTOM Should be ADDA */
  756.     GenInst(M68op_ADD, M68sz_long, subop, baseop, Codes);
  757.     FreeTemp(subop);
  758.     }
  759.     result = BuildARegIndirect(GetLocAReg(baseop));
  760.     if (isTempReg(baseop)) {
  761.     TempAddrs[GetLocAReg(baseop)].holder = result;
  762.     /* Dangerous move. */
  763.     }
  764.     SetLocSZ(result, M68_TypeSize(GetTreeTP(expr)));
  765.     return result;
  766. }
  767.  
  768. LocAMVia_t
  769. GenIndirectMember(ParseTreeVia_t expr, InstListVia_t Codes)
  770. {
  771.     LocAMVia_t                      retres;
  772.     LocAMVia_t                      result;
  773.     if (isBitFieldType(GetTreeTP(expr))) {
  774.     result = GenExpression(Via(expr)->a, Codes);
  775.     result = DictateAnyAReg(result, Codes);
  776.     retres = BuildARegDisplaceField(GetLocAReg(result),
  777.                     Via(Via(expr)->data.thesymbol)->numbers.structoffset, Via(Via(expr)->data.thesymbol)->Definition.StartEndBits);
  778.     if (isTempReg(result)) {
  779.         TempAddrs[GetLocAReg(result)].holder = retres;
  780.         /*
  781.          * Dangerous operation - this should probably be documented and
  782.          * moved into its own routine.
  783.          */
  784.     }
  785.     SetLocSZ(retres, M68sz_long);
  786.     return retres;
  787.     } else {
  788.     result = GenExpression(Via(expr)->a, Codes);
  789.     result = DictateAnyAReg(result, Codes);
  790.     retres = BuildARegDisplace(GetLocAReg(result),
  791.               Via(Via(expr)->data.thesymbol)->numbers.structoffset);
  792.     SetLocSZ(retres, M68_TypeSize(GetTreeTP(expr)));
  793.     if (isTempReg(result)) {
  794.         TempAddrs[GetLocAReg(result)].holder = retres;
  795.         /*
  796.          * Dangerous operation - this should probably be documented and
  797.          * moved into its own routine.
  798.          */
  799.     }
  800.     return retres;
  801.     }
  802. }
  803.  
  804. LocAMVia_t
  805. GenMember(ParseTreeVia_t expr, InstListVia_t Codes)
  806. {
  807.     LocAMVia_t                      retres;
  808.     LocAMVia_t                      result;
  809.     if (isBitFieldType(GetTreeTP(expr))) {
  810.     result = GenAddrOf(Via(expr)->a, Codes);
  811.     retres = BuildARegDisplaceField(GetLocAReg(result),
  812.                     Via(Via(expr)->data.thesymbol)->numbers.structoffset, Via(Via(expr)->data.thesymbol)->Definition.StartEndBits);
  813.     TempAddrs[GetLocAReg(result)].holder = retres;
  814.     /*
  815.      * Dangerous operation - this should probably be documented and moved
  816.      * into its own routine.
  817.      */
  818.     SetLocSZ(retres, M68sz_long);
  819.     return retres;
  820.     } else {
  821. #define MAYBENOT
  822. #ifdef MAYBENOT
  823.     if (Via(Via(expr)->data.thesymbol)->numbers.structoffset) {
  824.         result = GenAddrOf(Via(expr)->a, Codes);
  825.         retres = BuildARegDisplace(GetLocAReg(result),
  826.               Via(Via(expr)->data.thesymbol)->numbers.structoffset);
  827.     } else {
  828.         retres = GenExpression(Via(expr)->a, Codes);
  829.         result = NULL;
  830.     }
  831. #else
  832.     result = GenAddrOf(Via(expr)->a, Codes);
  833.     retres = BuildARegDisplace(GetLocAReg(result),
  834.               Via(Via(expr)->data.thesymbol)->numbers.structoffset);
  835. #endif
  836.     SetLocSZ(retres, M68_TypeSize(GetTreeTP(expr)));
  837.     if (result) {
  838.         TempAddrs[GetLocAReg(result)].holder = retres;
  839.         /*
  840.          * Dangerous operation - this should probably be documented and
  841.          * moved into its own routine.
  842.          */
  843.     }
  844.     return retres;
  845.     }
  846. }
  847.  
  848. LocAMVia_t
  849. GenAddrOf(ParseTreeVia_t expr, InstListVia_t Codes)
  850. {
  851.     LocAMVia_t                      result;
  852.     LocAMVia_t                      tempresult;
  853.     result = GenExpression(expr, Codes);
  854.     FreeTemp(result);
  855.     if (GetLocAM(result) == M68am_Immediate)    /* Ugly kludge. */
  856.     return result;
  857.     tempresult = TempAddrReg(Codes);
  858.     SetLocSZ(tempresult, M68sz_long);    /* This assumes that the size of all
  859.                      * pointers is 4. */
  860.     GenLoadEA(result, tempresult, Codes);
  861.     return tempresult;
  862. }
  863.  
  864. LocAMVia_t
  865. GenDeref(ParseTreeVia_t expr, InstListVia_t Codes)
  866. {
  867.     LocAMVia_t                      result;
  868.     LocAMVia_t                      retres;
  869.     result = GenExpression(Via(expr)->a, Codes);
  870.     result = DictateTempAReg(result, Codes);
  871.     retres = BuildARegIndirect(GetLocAReg(result));
  872.     TempAddrs[GetLocAReg(result)].holder = retres;
  873.     result = retres;
  874.     SetLocSZ(result, M68_TypeSize(GetTreeTP(expr)));
  875.     return result;
  876. }
  877.  
  878. LocAMVia_t
  879. GenBitNegate(ParseTreeVia_t expr, InstListVia_t Codes)
  880. {
  881.     LocAMVia_t                      result;
  882.     result = GenExpression(expr, Codes);
  883.     result = DictateTempDReg(result, Codes);
  884.     GenInst(M68op_NOT, GetTPSize(GetTreeTP(expr)), result, NULL, Codes);
  885.     return result;
  886. }
  887.  
  888. LocAMVia_t
  889. GenNegate(ParseTreeVia_t expr, InstListVia_t Codes)
  890. {
  891.     LocAMVia_t                      result;
  892.     result = GenExpression(expr, Codes);
  893.     if (isFloatingType(GetTreeTP(expr))) {
  894.     result = DictateTempFloat(result, Codes);
  895.     GenInst(M68op_FNEG, GetLocSZ(result), result, NULL, Codes);
  896.     } else {
  897.     result = DictateTempDReg(result, Codes);
  898.     GenInst(M68op_NEG, GetTPSize(GetTreeTP(expr)), result, NULL, Codes);
  899.     }
  900.     return result;
  901. }
  902.  
  903. LocAMVia_t
  904. GenIdentifier(ParseTreeVia_t expr, InstListVia_t Codes)
  905. /*
  906.  * General identifiers are handled here.
  907.  */
  908. {
  909.     LocAMVia_t                      result;
  910.     result = Via(Via(expr)->data.thesymbol)->M68kDef.Loc;
  911.     if (!result) {
  912.         Gen68Error("Symbol with no location");
  913.     }
  914.     if (GetLocAM(result) == M68am_LargeGlobal) {
  915.         LocAMVia_t                      temp;
  916.         LocAMVia_t                      temp2;
  917.         temp = TempAddrReg(Codes);
  918.         Genmove(M68sz_long, BuildARegDirect(5), temp,
  919.             Codes);
  920.         GenInst(M68op_ADD, M68sz_long, result, temp, Codes);
  921.         temp2 = BuildARegIndirect(GetLocAReg(temp));
  922.         TempAddrs[GetLocAReg(temp)].holder = temp2;
  923.         result = temp2;
  924.     }
  925.     return result;
  926. }
  927.  
  928. LocAMVia_t
  929. GenStringLit(ParseTreeVia_t expr, InstListVia_t Codes)
  930. {
  931.     LocAMVia_t                      result;
  932.     LocAMVia_t                      temp;
  933.     result = Via(Via(expr)->data.SLit)->M68kDef.Loc;
  934.     temp = TempAddrReg(Codes);
  935.     GenLoadEA(result, temp, Codes);
  936.     result = temp;
  937.     return result;
  938. }
  939.  
  940. LocAMVia_t
  941. GenExpression(ParseTreeVia_t expr, InstListVia_t Codes)
  942. /*
  943.  * This is the general routine to call to generate code for any expression or
  944.  * statement tree.
  945.  */
  946. {
  947.     LocAMVia_t                      result;
  948.     result = NULL;
  949.     if (expr) {
  950.     switch (Via(expr)->kind) {
  951.     case PTF_array_subscript:
  952.         result = GenSubscript(expr, Codes);
  953.         break;
  954.     case PTF_function_call:
  955.         result = GenFunctionCall(expr, Codes);
  956.         break;
  957.     case PTF_postincrement:
  958.         result = GenPostInc(Via(expr)->a, Codes);
  959.         break;
  960.     case PTF_postdecrement:
  961.         result = GenPostDec(Via(expr)->a, Codes);
  962.         break;
  963.     case PTF_argument_list:
  964.         /* This should never happen */
  965.         break;
  966.     case PTF_preincrement:
  967.         result = GenPreInc(Via(expr)->a, Codes);
  968.         break;
  969.     case PTF_predecrement:
  970.         result = GenPreDec(Via(expr)->a, Codes);
  971.         break;
  972.     case PTF_gen_addrof:    /* Should this be this way ?? */
  973.     case PTF_address_of:
  974.         result = GenAddrOf(Via(expr)->a, Codes);
  975.         break;
  976.     case PTF_deref:
  977.         result = GenDeref(expr, Codes);
  978.         break;
  979.     case PTF_unary_plus:
  980.         result = GenExpression(Via(expr)->a, Codes);
  981.         break;
  982.     case PTF_unary_minus:
  983.         result = GenNegate(Via(expr)->a, Codes);
  984.         break;
  985.     case PTF_bitwise_neg:
  986.         result = GenBitNegate(Via(expr)->a, Codes);
  987.         break;
  988.     case PTF_logical_neg:
  989.         result = GenLogicalNegate(Via(expr)->a, Codes);
  990.         break;
  991.     case PTF_sizeof:
  992.         result = BuildImmediate(GetTPSize(Via(expr)->data.TP), GetTPSize(GetTreeTP(expr)));
  993.         break;
  994.     case PTF_enumconstant:
  995.         result = BuildImmediate(Via(Via(expr)->data.thesymbol)->numbers.EnumVal,
  996.                     GetTPSize(GetTreeTP(expr)));
  997.         break;
  998.     case PTF_multiply:
  999.         result = GenMulDiv(M68op_MULS, Via(expr)->a, Via(expr)->b, Codes);
  1000.         break;
  1001.     case PTF_divide:
  1002.         result = GenMulDiv(M68op_DIVS, Via(expr)->a, Via(expr)->b, Codes);
  1003.         break;
  1004.     case PTF_modulo:
  1005.         result = GenModulo(Via(expr)->a, Via(expr)->b, Codes);
  1006.         break;
  1007.     case PTF_typechange:
  1008.         result = GenTypeChange(expr, Codes);
  1009.         break;
  1010.     case PTF_add:
  1011.         result = GenTwoOp(M68op_ADD, Via(expr)->a, Via(expr)->b, Codes);
  1012.         break;
  1013.     case PTF_subtract:
  1014.         result = GenTwoOp(M68op_SUB, Via(expr)->a, Via(expr)->b, Codes);
  1015.         break;
  1016.     case PTF_shift_left:
  1017.         result = GenbitTwoOp(M68op_ASL, Via(expr)->a, Via(expr)->b, Codes);
  1018.         break;
  1019.     case PTF_shift_right:
  1020.         result = GenbitTwoOp(M68op_ASR, Via(expr)->a, Via(expr)->b, Codes);
  1021.         break;
  1022.     case PTF_lessthan:
  1023.         result = GenRelational(M68op_BLT, Via(expr)->a, Via(expr)->b, Codes);
  1024.         break;
  1025.     case PTF_greaterthan:
  1026.         result = GenRelational(M68op_BGT, Via(expr)->a, Via(expr)->b, Codes);
  1027.         break;
  1028.     case PTF_lessthaneq:
  1029.         result = GenRelational(M68op_BLE, Via(expr)->a, Via(expr)->b, Codes);
  1030.         break;
  1031.     case PTF_greaterthaneq:
  1032.         result = GenRelational(M68op_BGE, Via(expr)->a, Via(expr)->b, Codes);
  1033.         break;
  1034.     case PTF_equal:
  1035.         result = GenRelational(M68op_BEQ, Via(expr)->a, Via(expr)->b, Codes);
  1036.         break;
  1037.     case PTF_notequal:
  1038.         result = GenRelational(M68op_BNE, Via(expr)->a, Via(expr)->b, Codes);
  1039.         break;
  1040.     case PTF_bitwise_and:
  1041.         result = GenbitTwoOp(M68op_AND, Via(expr)->a, Via(expr)->b, Codes);
  1042.         break;
  1043.     case PTF_bitwise_xor:
  1044.         result = GenbitTwoOp(M68op_EOR, Via(expr)->a, Via(expr)->b, Codes);
  1045.         break;
  1046.     case PTF_bitwise_or:
  1047.         result = GenbitTwoOp(M68op_OR, Via(expr)->a, Via(expr)->b, Codes);
  1048.         break;
  1049.     case PTF_logical_and:
  1050.         result = GenLogicalAnd(Via(expr)->a, Via(expr)->b, Codes);
  1051.         break;
  1052.     case PTF_logical_or:
  1053.         result = GenLogicalOr(Via(expr)->a, Via(expr)->b, Codes);
  1054.         break;
  1055.     case PTF_ternary:
  1056.         result = GenTernary(Via(expr)->a, Via(expr)->b, Via(expr)->c, Codes);
  1057.         break;
  1058.     case PTF_assign:
  1059.         result = GenAssign(Via(expr)->a, Via(expr)->b, Codes);
  1060.         break;
  1061.     case PTF_mulassign:
  1062.         result = GenMulDivAssign(M68op_MULS, Via(expr)->a, Via(expr)->b,
  1063.                      Codes);
  1064.         break;
  1065.     case PTF_divassign:
  1066.         result = GenMulDivAssign(M68op_DIVS, Via(expr)->a, Via(expr)->b,
  1067.                      Codes);
  1068.         break;
  1069.     case PTF_modassign:
  1070.         result = GenModAssign(Via(expr)->a, Via(expr)->b, Codes);
  1071.         break;
  1072.     case PTF_addassign:
  1073.         result = GenOPAssign(M68op_ADD, Via(expr)->a, Via(expr)->b, Codes);
  1074.         break;
  1075.     case PTF_subassign:
  1076.         result = GenOPAssign(M68op_SUB, Via(expr)->a, Via(expr)->b, Codes);
  1077.         break;
  1078.     case PTF_leftassign:
  1079.         result = GenOPAssignDREG(M68op_ASL, Via(expr)->a, Via(expr)->b, Codes);
  1080.         break;
  1081.     case PTF_rightassign:
  1082.         result = GenOPAssignDREG(M68op_ASR, Via(expr)->a, Via(expr)->b, Codes);
  1083.         break;
  1084.     case PTF_andassign:
  1085.         result = GenOPAssign(M68op_AND, Via(expr)->a, Via(expr)->b, Codes);
  1086.         break;
  1087.     case PTF_xorassign:
  1088.         result = GenOPAssignDREG(M68op_EOR, Via(expr)->a, Via(expr)->b, Codes);
  1089.         break;
  1090.     case PTF_orassign:
  1091.         result = GenOPAssign(M68op_OR, Via(expr)->a, Via(expr)->b, Codes);
  1092.         break;
  1093.     case PTF_commas:
  1094.         GenExpression(Via(expr)->a, Codes);
  1095.         result = GenExpression(Via(expr)->b, Codes);
  1096.         break;
  1097.     case PTF_multi_initializer:
  1098.         result = GenExpression(Via(expr)->a, Codes);
  1099.         break;
  1100.     case PTF_initializer_list:
  1101.         result = NULL;
  1102.         Gen68Error("Multiple initializers are not allowed for auto variables.");
  1103.         break;
  1104.     case PTF_exprstmt:
  1105.         FreeAllRegs();
  1106.         /*
  1107.          * TODO It would be nice to be able to stick annotations on ALL
  1108.          * kinds of statements, but most will be too many lines long, and
  1109.          * we cannot control when comments begin or end.
  1110.          */
  1111.         DiscardedFunctionCall = 0;
  1112.         if (Via(expr)->a) {
  1113.         if (Via(Via(expr)->a)->kind == PTF_function_call) {
  1114.             DiscardedFunctionCall = 1;
  1115.         }
  1116.         }
  1117.         result = GenExpression(Via(expr)->a, Codes);
  1118.         FreeTemp(result);
  1119.         break;
  1120.     case PTF_emptystmt:
  1121.         break;
  1122.     case PTF_switchcase_stmt:
  1123.         GenSwitchCase(expr, Codes);
  1124.         break;
  1125.     case PTF_switchdefault_stmt:
  1126.         GenSwitchDefault(expr, Codes);
  1127.         break;
  1128.     case PTF_compound_stmt:
  1129.         GenCompound(expr, Codes);
  1130.         break;
  1131.     case PTF_stmt_list:
  1132.         GenExpression(Via(expr)->b, Codes);
  1133.         GenExpression(Via(expr)->a, Codes);
  1134.         break;
  1135.     case PTF_ifthenelse_stmt:
  1136.         GenIfThenElse(Via(expr)->a, Via(expr)->b, Via(expr)->c, Codes);
  1137.         break;
  1138.     case PTF_switch_stmt:
  1139.         GenSWITCH(Via(expr)->a, Via(expr)->b, Codes);
  1140.         break;
  1141.     case PTF_while_stmt:
  1142.         GenWhile(Via(expr)->a, Via(expr)->b, Codes);
  1143.         break;
  1144.     case PTF_dowhile_stmt:
  1145.         GenDoWhile(Via(expr)->a, Via(expr)->b, Codes);
  1146.         break;
  1147.     case PTF_for_stmt:
  1148.         Genforstmt(Via(expr)->a, Via(expr)->b, Via(expr)->c, GetTreeFour(expr), Codes);
  1149.         break;
  1150.     case PTF_continue_stmt:
  1151.         GenInst(M68op_BRA, M68sz_none,
  1152.             BuildLabelLoc(ContinueLabel), NULL, Codes);
  1153.         break;
  1154.     case PTF_break_stmt:
  1155.         GenInst(M68op_BRA, M68sz_none,
  1156.             BuildLabelLoc(BreakLabel), NULL, Codes);
  1157.         break;
  1158.     case PTF_return_stmt:
  1159.         GenReturn(Via(expr)->a, Codes);
  1160.         break;
  1161.     case PTF_identifier:
  1162.         result = GenIdentifier(expr, Codes);
  1163.         break;
  1164.     case PTF_intconstant:
  1165.         result = BuildImmediate(Via(expr)->data.number, GetTPSize(GetTreeTP(expr)));
  1166.         break;
  1167.     case PTF_floatconstant:
  1168.         result = Via(Via(expr)->data.FLit)->Loc;
  1169.         /*
  1170.          * QQQQ We should not have to do lea stuff here, because we
  1171.          * essentially ALWAYS PEA this Loc , right ?
  1172.          */
  1173.         break;
  1174.     case PTF_string_literal:
  1175.         result = GenStringLit(expr, Codes);
  1176.         if (!result) {
  1177.         Gen68Error("String lit with no location");
  1178.         }
  1179.         break;
  1180.     case PTF_struct_member:
  1181.         result = GenMember(expr, Codes);
  1182.         break;
  1183.     case PTF_struct_indirect_member:
  1184.         result = GenIndirectMember(expr, Codes);
  1185.         break;
  1186.     case PTF_labelled_stmt:
  1187.         GenLabelledStmt(expr, Codes);
  1188.         break;
  1189.     case PTF_goto_stmt:
  1190.         GenGotoStmt(expr, Codes);
  1191.         break;
  1192.     case PTF_NOP:
  1193.         result = NULL;
  1194.         break;
  1195.     case PTF_asm_stmt:
  1196.         AddInstList(Via(expr)->data.AsmCodes, Codes);
  1197.         break;
  1198.     default:
  1199.         break;
  1200.     }
  1201.     }
  1202.     return result;
  1203. }
  1204.