home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Harvest C 1.3 / Source Code / regalloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-15  |  26.8 KB  |  1,100 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 register allocation.
  35.  * 
  36.  * 
  37.  */
  38.  
  39.  
  40. #include "conditcomp.h"
  41. #include <stdio.h>
  42. #include <string.h>
  43.  
  44. #include "structs.h"
  45. #include "CHarvestDoc.h"
  46. #include "CHarvestOptions.h"
  47.  
  48. extern CHarvestDoc *gProject;
  49.  
  50.  
  51. #pragma segment RegAlloc
  52.  
  53.  
  54. SpillSlotVia_t
  55. RawSpillSlot(void)
  56. {
  57.     register SpillSlotVia_t         raw;
  58.     raw = Ealloc(sizeof(SpillSlot_t));
  59.     Via(raw)->next = NULL;
  60.     Via(raw)->local = 0;
  61.     Via(raw)->status = 0;
  62.     Via(raw)->SlotLoc = NULL;
  63.     Via(raw)->SlotSize = 0;
  64.     return raw;
  65. }
  66.  
  67. void
  68. FreePerms(void)
  69. {
  70.     /* Set all perm registers to available. */
  71.     int                             ndx;
  72.  
  73.     ndx = MAXTEMPDATAREG + 1;
  74.     while (ndx <= 7) {
  75.     TempDatas[ndx].status = M68rs_Available;
  76.     TempDatas[ndx].holder = NULL;
  77.     TempDatas[ndx].waiting = 0;
  78.     TempDatas[ndx].count = 0;
  79.     ndx++;
  80.     }
  81.     ndx = MAXTEMPADDRREG + 1;
  82.     while (ndx <= 7) {
  83.     TempAddrs[ndx].status = M68rs_Available;
  84.     TempAddrs[ndx].holder = NULL;
  85.     TempAddrs[ndx].waiting = 0;
  86.     TempAddrs[ndx].count = 0;
  87.     ndx++;
  88.     }
  89.     ndx = MAXTEMPFLOATREG + 1;
  90.     while (ndx <= 6) {
  91.     TempAddrs[ndx].status = M68rs_Available;
  92.     TempAddrs[ndx].holder = NULL;
  93.     TempAddrs[ndx].waiting = 0;
  94.     TempAddrs[ndx].count = 0;
  95.     ndx++;
  96.     }
  97. }
  98.  
  99. void
  100. FreeAllRegs(void)
  101. {
  102.     /* Set all temp registers to available. */
  103.     int                             ndx;
  104.  
  105.     ndx = 0;
  106.     while (ndx <= MAXTEMPDATAREG) {
  107.     /* TODO Check here to see if it is hanging */
  108.     TempDatas[ndx].status = M68rs_Available;
  109.     TempDatas[ndx].holder = NULL;
  110.     TempDatas[ndx].waiting = 0;
  111.     ndx++;
  112.     }
  113.     ndx = 0;
  114.     while (ndx <= MAXTEMPADDRREG) {
  115.     /* TODO Check here to see if it is hanging */
  116.     TempAddrs[ndx].status = M68rs_Available;
  117.     TempAddrs[ndx].holder = NULL;
  118.     TempAddrs[ndx].waiting = 0;
  119.     ndx++;
  120.     }
  121.     ndx = 0;
  122.     while (ndx <= MAXTEMPFLOATREG) {
  123.     TempFloats[ndx].status = M68rs_Available;
  124.     TempFloats[ndx].holder = NULL;
  125.     TempFloats[ndx].waiting = 0;
  126.     ndx++;
  127.     }
  128.     NextTempFloatReg = 0;
  129.     NextTempDataReg = 0;
  130.     NextTempAddrReg = 0;
  131. }
  132.  
  133. SpillSlotVia_t
  134. GetSpillSlot(int size)
  135. /*
  136.  * A spill slot is a temporary unit of storage, allocated on the stack frame
  137.  * as if it were a local variable.  When temp registers spill, they are moved
  138.  * to a spill slot.
  139.  */
  140. {
  141.     SpillSlotVia_t                  result;
  142.     SpillSlotVia_t                  cur;
  143.     int                             realsize;
  144.     int                             offset;
  145.     int                             truesize;
  146.     /*
  147.      * Search the spill list for a slot of the given size which is free. If
  148.      * not found, create a new one by expanding the stack frame (in the
  149.      * global variable LinkInst) by size, and returning the slot.
  150.      */
  151.     truesize = size;
  152.     switch (size) {
  153.     case M68sz_single:
  154.     size = SizeOfFloat;
  155.     break;
  156.     case M68sz_double:
  157.     size = SizeOfDouble;
  158.     break;
  159.     case M68sz_extended:
  160.     size = SizeOfLongDouble;
  161.     break;
  162.     default:
  163.     break;
  164.     }
  165.     realsize = size;
  166.     if (size % 2) {
  167.     size++;
  168.     }
  169.     cur = SpillList;
  170.     while (cur) {
  171.     if (Via(cur)->SlotSize == size) {
  172.         if (Via(cur)->status == M68ss_free) {
  173.         Via(cur)->status = M68ss_used;
  174.         return cur;
  175.         }
  176.     }
  177.     cur = Via(cur)->next;
  178.     }
  179.     result = RawSpillSlot();
  180.  
  181.     Via(result)->SlotSize = size;
  182.     Via(result)->next = SpillList;
  183.     SpillList = result;
  184.     Via(result)->status = M68ss_used;
  185. #ifdef Undefined
  186.     offset = GetLocConstant(Via(LinkInst)->right) - realsize;
  187. #else
  188.     offset = GetLocConstant(Via(LinkInst)->right) - size;    /* 27 Mar 1992 */
  189. #endif
  190.     SetLocConstant(Via(LinkInst)->right, GetLocConstant(Via(LinkInst)->right) - size);
  191.     Via(result)->SlotLoc = BuildAutoLoc(offset, truesize);
  192.     SetLocSlot(Via(result)->SlotLoc, result);
  193.  
  194.     return result;
  195. }
  196.  
  197. void
  198. KillSpillList(void)
  199. {
  200.     SpillSlotVia_t                  cur;
  201.     SpillSlotVia_t                  nxt;
  202.     cur = SpillList;
  203.     while (cur) {
  204.     nxt = Via(cur)->next;
  205.     Efree(cur);
  206.     cur = nxt;
  207.     }
  208. }
  209.  
  210. SpillSlotVia_t
  211. SpillTemp(LocAMVia_t pushee, InstListVia_t Codes)
  212. /* Spills the value in a temporary register... */
  213. {
  214.     SpillSlotVia_t                  result;
  215.     /*
  216.      * A SANE FP temp will never be spilled, because it is itself a spill
  217.      * slot.
  218.      */
  219.     if (!isTempReg(pushee)) {
  220.     Gen68Error("Spill temp called on non temp");
  221.     }
  222.     if (GetLocAM(pushee) == M68am_FReg) {
  223.     if (!gProject->itsOptions->useMC68881) {
  224.         Gen68Error("FReg access with 68881 switch off !");
  225.     }
  226.     result = GetSpillSlot(8);
  227.     SetLocSZ(Via(result)->SlotLoc, M68sz_double);
  228.     SetLocSlot(pushee, result);
  229.     Genmove(M68sz_double, pushee, Via(result)->SlotLoc, Codes);
  230.     SetLocStatus(pushee, M68os_spilled);
  231.     return result;
  232.     } else {
  233.     if (isARegMode(pushee)) {
  234.         LocAMVia_t                      reg;
  235.         result = GetSpillSlot(4);
  236.         SetLocSlot(pushee, result);
  237.         reg = BuildARegDirect(GetLocAReg(pushee));
  238.         Genmove(M68sz_long, reg, Via(result)->SlotLoc, Codes);
  239.         SetLocStatus(pushee, M68os_spilled);
  240.         return result;
  241.     } else {
  242.         result = GetSpillSlot(4);
  243.         SetLocSlot(pushee, result);
  244.         Genmove(M68sz_long, pushee, Via(result)->SlotLoc, Codes);
  245.         SetLocStatus(pushee, M68os_spilled);
  246.         return result;
  247.     }
  248.     }
  249. }
  250.  
  251. void
  252. UnSpillTemp(LocAMVia_t freed, InstListVia_t Codes)
  253. /* unspills a temp register. */
  254. {
  255.     if (isARegMode(freed)) {
  256.     LocAMVia_t                      regd;
  257.     regd = BuildARegDirect(GetLocAReg(freed));
  258.     Via(GetLocSlot(freed))->status = M68ss_free;
  259.     SetLocStatus(freed, M68os_valid);
  260.     Genmove(M68sz_long, Via(GetLocSlot(freed))->SlotLoc, regd, Codes);
  261.     SetLocSlot(freed, NULL);
  262.     } else {
  263.     Via(GetLocSlot(freed))->status = M68ss_free;
  264.     SetLocStatus(freed, M68os_valid);
  265.     Genmove(M68sz_long, Via(GetLocSlot(freed))->SlotLoc, freed, Codes);
  266.     SetLocSlot(freed, NULL);
  267.     }
  268. }
  269.  
  270. int
  271. isPermReg(LocAMVia_t loc)
  272. {
  273.     int                             result;
  274.     result = 0;
  275.     if (loc) {
  276.     switch (GetLocAM(loc)) {
  277.     case M68am_DReg:
  278.         if (GetLocDReg(loc) > MAXTEMPDATAREG) {
  279.         result = 1;
  280.         }
  281.         break;
  282.     case M68am_ARegDirect:
  283.     case M68am_ARegIndirect:
  284.     case M68am_ARegPostInc:
  285.     case M68am_ARegPreDec:
  286.     case M68am_ARegDisplace:
  287.     case M68am_ARegDisplaceFIELD:
  288.     case M68am_ARegDispIndx:
  289.         if (GetLocAReg(loc) > MAXTEMPADDRREG) {
  290.         if ((GetLocAReg(loc) != 7) && (GetLocAReg(loc) != FRAME) && (GetLocAReg(loc)
  291.                                != 5))
  292.             result = 1;
  293.         }
  294.         break;
  295.     default:
  296.         break;
  297.     }
  298.     }
  299.     return result;
  300. }
  301.  
  302. int
  303. isTempReg(LocAMVia_t loc)
  304. /*
  305.  * Returns true if the location passed is a temporary addr or data or 68881
  306.  * float register.
  307.  */
  308. {
  309.     int                             result;
  310.     result = 0;
  311.     if (loc) {
  312.     switch (GetLocAM(loc)) {
  313.     case M68am_FSANEtemp:
  314.         result = 1;
  315.         break;
  316.     case M68am_FReg:
  317.         if (GetLocFReg(loc) <= MAXTEMPFLOATREG) {
  318.         result = 1;
  319.         }
  320.         break;
  321.     case M68am_DReg:
  322.         if (GetLocDReg(loc) <= MAXTEMPDATAREG) {
  323.         result = 1;
  324.         }
  325.         break;
  326.     case M68am_ARegDirect:
  327.     case M68am_ARegIndirect:
  328.     case M68am_ARegPostInc:
  329.     case M68am_ARegPreDec:
  330.     case M68am_ARegDisplace:
  331.     case M68am_ARegDisplaceFIELD:
  332.     case M68am_ARegDispIndx:
  333.         if (GetLocAReg(loc) <= MAXTEMPADDRREG) {
  334.         result = 1;
  335.         }
  336.         break;
  337.     default:
  338.         break;
  339.     }
  340.     }
  341.     return result;
  342. }
  343.  
  344. void
  345. FreePerm(LocAMVia_t loc)
  346. {
  347.     if (loc) {
  348.     if (isPermReg(loc)) {
  349.         switch (GetLocAM(loc)) {
  350.         case M68am_DReg:
  351.         TempDatas[GetLocDReg(loc)].status = M68rs_Available;
  352.         TempDatas[GetLocDReg(loc)].holder = NULL;
  353.         break;
  354.         case M68am_FReg:
  355.         TempFloats[GetLocFReg(loc)].status = M68rs_Available;
  356.         TempFloats[GetLocFReg(loc)].holder = NULL;
  357.         break;
  358.         case M68am_FSANEtemp:
  359.         if (GetLocSlot(loc)) {
  360.             Via(GetLocSlot(loc))->status = M68ss_free;
  361.         }
  362.         break;
  363.         default:        /* AReg is default. */
  364.         TempAddrs[GetLocAReg(loc)].status = M68rs_Available;
  365.         TempAddrs[GetLocAReg(loc)].holder = NULL;
  366.         break;
  367.         }
  368.     }
  369.     if (GetLocSlot(loc)) {
  370.         Via(GetLocSlot(loc))->status = M68ss_free;
  371.     }
  372.     }
  373. }
  374.  
  375. void
  376. FreeTemp(LocAMVia_t loc)
  377. /*
  378.  * If the loc passed is a temporary data or address register, that register
  379.  * is marked available.  Also, if the loc is a 68881 freg, or a spill slot,
  380.  * it is marked available.
  381.  */
  382. {
  383.     if (loc) {
  384.     if (isTempReg(loc)) {
  385.         switch (GetLocAM(loc)) {
  386.         case M68am_DReg:
  387.         TempDatas[GetLocDReg(loc)].status = M68rs_Available;
  388.         TempDatas[GetLocDReg(loc)].holder = NULL;
  389.         break;
  390.         case M68am_FReg:
  391.         TempFloats[GetLocFReg(loc)].status = M68rs_Available;
  392.         TempFloats[GetLocFReg(loc)].holder = NULL;
  393.         break;
  394.         case M68am_FSANEtemp:
  395.         if (GetLocSlot(loc)) {
  396.             if (!Via(GetLocSlot(loc))->local)
  397.             Via(GetLocSlot(loc))->status = M68ss_free;
  398.         }
  399.         break;
  400.         default:        /* AReg is default. */
  401.         TempAddrs[GetLocAReg(loc)].status = M68rs_Available;
  402.         TempAddrs[GetLocAReg(loc)].holder = NULL;
  403.         break;
  404.         }
  405.     }
  406.     if (GetLocSlot(loc)) {
  407.         if (!Via(GetLocSlot(loc))->local)
  408.         Via(GetLocSlot(loc))->status = M68ss_free;
  409.     }
  410.     }
  411. }
  412.  
  413. void
  414. FreeIt(LocAMVia_t loc)
  415. {
  416.     FreeTemp(loc);
  417.     FreePerm(loc);
  418. }
  419.  
  420. LocAMVia_t
  421. ValidateReg(LocAMVia_t loc, InstListVia_t Codes)
  422. /*
  423.  * If the loc passed is a temporary data/addr/float register which is
  424.  * currently spilled, then it is brought off the stack frame and restored to
  425.  * its place.
  426.  */
  427. {
  428.     LocAMVia_t                      result;
  429.     result = loc;
  430.     if (loc) {
  431.     switch (GetLocAM(loc)) {
  432.     case M68am_FReg:
  433.         if (GetLocFReg(loc) <= MAXTEMPFLOATREG) {
  434.         if (GetLocStatus(loc) != M68os_valid) {
  435.             if (TempFloats[GetLocFReg(loc)].status == M68rs_Available) {
  436.             UnSpillTemp(loc, Codes);
  437.             TempFloats[GetLocFReg(loc)].status = M68rs_Used;
  438.             TempFloats[GetLocFReg(loc)].holder = loc;
  439.             TempFloats[GetLocFReg(loc)].waiting--;
  440.             } else {
  441.             Gen68Error("VERYBAD float Reg being validated was not available !");
  442.             }
  443.         }
  444.         }
  445.         break;
  446.     case M68am_DReg:
  447.         if (GetLocDReg(loc) <= MAXTEMPDATAREG) {
  448.         if (GetLocStatus(loc) != M68os_valid) {
  449.             if (TempDatas[GetLocDReg(loc)].status == M68rs_Available) {
  450.             UnSpillTemp(loc, Codes);
  451.             TempDatas[GetLocDReg(loc)].status = M68rs_Used;
  452.             TempDatas[GetLocDReg(loc)].holder = loc;
  453.             TempDatas[GetLocDReg(loc)].waiting--;
  454.             } else {
  455.             Gen68Error("VERYBAD DReg being validated was not available !");
  456.             }
  457.         }
  458.         }
  459.         break;
  460.     case M68am_ARegDirect:
  461.     case M68am_ARegIndirect:
  462.     case M68am_ARegPostInc:
  463.     case M68am_ARegPreDec:
  464.     case M68am_ARegDisplace:
  465.     case M68am_ARegDispIndx:
  466.         if (GetLocAReg(loc) <= MAXTEMPADDRREG) {
  467.         if (GetLocStatus(loc) != M68os_valid) {
  468.             if (TempAddrs[GetLocAReg(loc)].status == M68rs_Available) {
  469.             UnSpillTemp(loc, Codes);
  470.             TempAddrs[GetLocAReg(loc)].status = M68rs_Used;
  471.             TempAddrs[GetLocAReg(loc)].holder = loc;
  472.             TempAddrs[GetLocAReg(loc)].waiting--;
  473.             } else {
  474.             Gen68Error("VERYBAD AReg being validated was not available !");
  475.             }
  476.         }
  477.         }
  478.         break;
  479.     default:
  480.         break;
  481.     }
  482.     }
  483.     return result;
  484. }
  485.  
  486. int
  487. AvailFloatReg(void)
  488. /*
  489.  * Returns the number of an available float register, if there is one
  490.  * available.  This only applies for the 68881 mode, because there are an
  491.  * arbitrary number of SANE temps which can be created on the stack frame. We
  492.  * have two priorities here.  first, we want to return a reg which is
  493.  * available if possible.  Second, whether we return an available reg or not,
  494.  * we want to return the one with the fewest locations spilled (waiting).
  495.  */
  496. {
  497.     int                             ndx;
  498.     int                             loop;
  499.     int                             fewest;
  500.     fewest = -1;
  501.     ndx = NextTempFloatReg;
  502.     loop = 0;
  503.     while (!loop) {
  504.     if (TempFloats[ndx].status == M68rs_Available) {
  505.         if (fewest < 0) {
  506.         fewest = ndx;
  507.         } else {
  508.         if (TempFloats[ndx].waiting < TempFloats[fewest].waiting) {
  509.             fewest = ndx;
  510.         }
  511.         }
  512.     }
  513.     ndx = (ndx + 1) % NUMOFTEMPFLOATREGS;
  514.     if (ndx == NextTempFloatReg) {
  515.         loop = 1;
  516.     }
  517.     }
  518.     if (fewest >= 0) {
  519.     return fewest;
  520.     }
  521.     /*
  522.      * OK. None are available, find the one with the fewest locs waiting.
  523.      */
  524.  
  525.     fewest = NextTempFloatReg;
  526.     ndx = NextTempFloatReg;
  527.     loop = 0;
  528.     while (!loop) {
  529.     if (TempFloats[ndx].waiting < TempFloats[fewest].waiting) {
  530.         fewest = ndx;
  531.     }
  532.     ndx = (ndx + 1) % NUMOFTEMPFLOATREGS;
  533.     if (ndx == NextTempFloatReg) {
  534.         loop = 1;
  535.     }
  536.     }
  537.     return fewest;
  538. }
  539.  
  540. int
  541. AvailAddrPerm(void)
  542. /*
  543.  * Returns the number of an available perm addr register, if there is one
  544.  * available.
  545.  */
  546. {
  547.     int                             ndx;
  548.     ndx = MAXTEMPADDRREG + 1;
  549.     while (ndx <= 6) {
  550.     if (ndx != FRAME)
  551.         if (ndx != 5)
  552.         if (TempAddrs[ndx].status == M68rs_Available)
  553.             return ndx;
  554.     ndx++;
  555.     }
  556.     return 0;
  557. }
  558.  
  559. void
  560. PopPerms(InstListVia_t Codes)
  561. {
  562.     /*
  563.      * This function scans TempDatas (perms only) and determines if any perms
  564.      * were used.  If so, it generates instructions to get them from the
  565.      * stack, and inserts those instructions into Codes
  566.      */
  567.     int                             ndx;
  568.     LocAMVia_t                      stkpop;
  569.     stkpop = RawLocation();
  570.     SetLocAM(stkpop, M68am_ARegPostInc);
  571.     SetLocAReg(stkpop, 7);
  572.  
  573.     ndx = MAXTEMPDATAREG + 1;
  574.     while (ndx <= 7) {
  575.     if (TempDatas[ndx].count) {
  576.         GenInst(M68op_MOVE, M68sz_long, stkpop, BuildDRegLocation(ndx),
  577.             Codes);
  578.     }
  579.     ndx++;
  580.     }
  581.     ndx = MAXTEMPFLOATREG + 1;
  582.     while (ndx <= 7) {
  583.     if (TempFloats[ndx].count) {
  584.         GenInst(M68op_FMOVE, M68sz_extended, stkpop, BuildFRegLocation(ndx),
  585.             Codes);
  586.     }
  587.     ndx++;
  588.     }
  589.     ndx = MAXTEMPADDRREG + 1;
  590.     while (ndx <= 6) {
  591.     if (TempAddrs[ndx].count) {
  592.         GenInst(M68op_MOVE, M68sz_long, stkpop, BuildARegDirect(ndx),
  593.             Codes);
  594.     }
  595.     ndx++;
  596.     }
  597. }
  598.  
  599. void
  600. PushPerms(void)
  601. {
  602.     /*
  603.      * This function scans TempDatas (perms only) and determines if any perms
  604.      * were used.  If so, it generates instructions to save them onto the
  605.      * stack, and inserts those instructions immediately after LinkInst.
  606.      */
  607.     int                             ndx;
  608.     LocAMVia_t                      stkpush;
  609.     stkpush = RawLocation();
  610.     SetLocAM(stkpush, M68am_ARegPreDec);
  611.     SetLocAReg(stkpush, 7);
  612.  
  613.     ndx = MAXTEMPDATAREG + 1;
  614.     while (ndx <= 7) {
  615.     if (TempDatas[ndx].count) {
  616.         InsertInstruction(M68op_MOVE, M68sz_long, BuildDRegLocation(ndx),
  617.                   stkpush, LinkInst);
  618.     }
  619.     ndx++;
  620.     }
  621.     ndx = MAXTEMPFLOATREG + 1;
  622.     while (ndx <= 7) {
  623.     if (TempFloats[ndx].count) {
  624.         InsertInstruction(M68op_FMOVE, M68sz_extended, BuildFRegLocation(ndx),
  625.                   stkpush, LinkInst);
  626.     }
  627.     ndx++;
  628.     }
  629.     ndx = MAXTEMPADDRREG + 1;
  630.     while (ndx <= 6) {
  631.     if (TempAddrs[ndx].count) {
  632.         InsertInstruction(M68op_MOVE, M68sz_long, BuildARegDirect(ndx),
  633.                   stkpush, LinkInst);
  634.     }
  635.     ndx++;
  636.     }
  637. }
  638.  
  639. int
  640. AvailFloatPerm(void)
  641. /*
  642.  * Returns the number of an available perm float register, if there is one
  643.  * available.
  644.  */
  645. {
  646.     int                             ndx;
  647.     ndx = MAXTEMPFLOATREG + 1;
  648.     while (ndx <= 7) {
  649.     if (TempFloats[ndx].status == M68rs_Available) {
  650.         return ndx;
  651.     }
  652.     ndx++;
  653.     }
  654.     return 0;
  655. }
  656.  
  657. int
  658. AvailDataPerm(void)
  659. /*
  660.  * Returns the number of an available perm data register, if there is one
  661.  * available.
  662.  */
  663. {
  664.     int                             ndx;
  665.     ndx = MAXTEMPDATAREG + 1;
  666.     while (ndx <= 7) {
  667.     if (TempDatas[ndx].status == M68rs_Available) {
  668.         return ndx;
  669.     }
  670.     ndx++;
  671.     }
  672.     return 0;
  673. }
  674.  
  675. int
  676. AvailDataReg(void)
  677. /*
  678.  * Returns the number of an available data register, if there is one
  679.  * available. We have two priorities here.  first, we want to return a reg
  680.  * which is available if possible.  Second, whether we return an available
  681.  * reg or not, we want to return the one with the fewest locations spilled
  682.  * (waiting). Unfortunately, there is a third consideration.  Sometimes there
  683.  * is a tie.  It occurs when there is more than one available register with
  684.  * the same value for waiting.  How do we break the tie ?  The global var
  685.  * NextTempDataReg is used to determine which is the next reg to be
  686.  * allocated.
  687.  */
  688. {
  689.     int                             ndx;
  690.     int                             loop;
  691.     int                             fewest;
  692.     fewest = -1;
  693.     ndx = NextTempDataReg;
  694.     loop = 0;
  695.     while (!loop) {
  696.     if (TempDatas[ndx].status == M68rs_Available) {
  697.         if (fewest < 0) {
  698.         fewest = ndx;
  699.         } else {
  700.         if (TempDatas[ndx].waiting < TempDatas[fewest].waiting) {
  701.             fewest = ndx;
  702.         }
  703.         }
  704.     }
  705.     ndx = (ndx + 1) % NUMOFTEMPDATAREGS;
  706.     if (ndx == NextTempDataReg) {
  707.         loop = 1;
  708.     }
  709.     }
  710.     if (fewest >= 0) {
  711.     return fewest;
  712.     }
  713.     /*
  714.      * OK. None are available, find the one with the fewest locs waiting.
  715.      */
  716.  
  717.     fewest = NextTempDataReg;
  718.     ndx = NextTempDataReg;
  719.     loop = 0;
  720.     while (!loop) {
  721.     if (TempDatas[ndx].waiting < TempDatas[fewest].waiting) {
  722.         fewest = ndx;
  723.     }
  724.     ndx = (ndx + 1) % NUMOFTEMPDATAREGS;
  725.     if (ndx == NextTempDataReg) {
  726.         loop = 1;
  727.     }
  728.     }
  729.     return fewest;
  730. }
  731.  
  732. int
  733. AvailAddrReg(void)
  734. /*
  735.  * Returns the number of an available addr register, if there is one
  736.  * available.
  737.  */
  738. {
  739.     int                             ndx;
  740.     int                             loop;
  741.     int                             fewest;
  742.     fewest = -1;
  743.     ndx = NextTempAddrReg;
  744.     loop = 0;
  745.     while (!loop) {
  746.     if (TempAddrs[ndx].status == M68rs_Available) {
  747.         if (fewest < 0) {
  748.         fewest = ndx;
  749.         } else {
  750.         if (TempAddrs[ndx].waiting < TempAddrs[fewest].waiting) {
  751.             fewest = ndx;
  752.         }
  753.         }
  754.     }
  755.     ndx = (ndx + 1) % NUMOFTEMPADDRREGS;
  756.     if (ndx == NextTempAddrReg) {
  757.         loop = 1;
  758.     }
  759.     }
  760.     if (fewest >= 0) {
  761.     return fewest;
  762.     }
  763.     /*
  764.      * OK. None are available, find the one with the fewest locs waiting.
  765.      */
  766.  
  767.     fewest = NextTempAddrReg;
  768.     ndx = NextTempAddrReg;
  769.     loop = 0;
  770.     while (!loop) {
  771.     if (TempAddrs[ndx].waiting < TempAddrs[fewest].waiting) {
  772.         fewest = ndx;
  773.     }
  774.     ndx = (ndx + 1) % NUMOFTEMPADDRREGS;
  775.     if (ndx == NextTempAddrReg) {
  776.         loop = 1;
  777.     }
  778.     }
  779.     return fewest;
  780. }
  781.  
  782. LocAMVia_t
  783. TempAddrReg(InstListVia_t Codes)
  784. /*
  785.  * Allocates and returns the location record for a temporary addr register.
  786.  * If all the temp addr registers are full, then one is spilled onto the
  787.  * stack to make room.
  788.  */
  789. {
  790.     LocAMVia_t                      result;
  791.     SpillSlotVia_t                  slot;
  792.     NextTempAddrReg = AvailAddrReg();
  793.     result = BuildARegDirect(NextTempAddrReg);
  794.     if (TempAddrs[NextTempAddrReg].status != M68rs_Available) {
  795.     slot = SpillTemp(TempAddrs[NextTempAddrReg].holder, Codes);
  796.     TempAddrs[NextTempAddrReg].waiting++;
  797.     }
  798.     TempAddrs[NextTempAddrReg].holder = result;
  799.     TempAddrs[NextTempAddrReg].status = M68rs_Used;
  800.     TempAddrs[NextTempAddrReg].count++;
  801.     NextTempAddrReg = (NextTempAddrReg + 1) % NUMOFTEMPADDRREGS;
  802.     return result;
  803. }
  804.  
  805. LocAMVia_t
  806. TempFloatReg(InstListVia_t Codes)
  807. /*
  808.  * Allocates and returns the location record for a temporary float register.
  809.  * If all the temp float registers are full, then one is spilled onto the
  810.  * stack to make room.
  811.  */
  812. {
  813.     /* Check for SANE mode here and handle it differently. */
  814.     LocAMVia_t                      result;
  815.     SpillSlotVia_t                  slot;
  816.     if (gProject->itsOptions->useMC68881) {
  817.     NextTempFloatReg = AvailFloatReg();
  818.     result = BuildFRegLocation(NextTempFloatReg);
  819.     if (TempFloats[NextTempFloatReg].status != M68rs_Available) {
  820.         slot = SpillTemp(TempFloats[NextTempFloatReg].holder, Codes);
  821.         TempFloats[NextTempFloatReg].waiting++;
  822.     }
  823.     TempFloats[NextTempFloatReg].holder = result;
  824.     TempFloats[NextTempFloatReg].status = M68rs_Used;
  825.     NextTempFloatReg = (NextTempFloatReg + 1) % NUMOFTEMPFLOATREGS;
  826.     } else {
  827.     slot = GetSpillSlot(10);
  828.     result = Via(slot)->SlotLoc;
  829.     SetLocSZ(result, 10);
  830.     SetLocAM(result, M68am_FSANEtemp);
  831.     }
  832.     SetLocIsFloat(result, 1);
  833.     return result;
  834. }
  835.  
  836. LocAMVia_t
  837. PermAddrReg(void)
  838. /*
  839.  * Allocates and returns the location record for a perm addr register.  If
  840.  * all the perm addr registers are full, then the caller is out of luck.
  841.  */
  842. {
  843.     LocAMVia_t                      result;
  844.     int                             whichreg;
  845.     whichreg = AvailAddrPerm();
  846.     if (!whichreg) {
  847.     return NULL;
  848.     }
  849.     result = BuildARegDirect(whichreg);
  850.     TempAddrs[whichreg].holder = result;
  851.     TempAddrs[whichreg].status = M68rs_Used;
  852.     TempAddrs[whichreg].count++;
  853.     return result;
  854. }
  855.  
  856. LocAMVia_t
  857. PermFloatReg(void)
  858. /*
  859.  * Allocates and returns the location record for a perm float register.  If
  860.  * all the perm float registers are full, then the caller is out of luck.
  861.  */
  862. {
  863.     LocAMVia_t                      result;
  864.     int                             whichreg;
  865.     whichreg = AvailFloatPerm();
  866.     if (!whichreg) {
  867.     return NULL;
  868.     }
  869.     result = BuildFRegLocation(whichreg);
  870.     TempFloats[whichreg].holder = result;
  871.     TempFloats[whichreg].status = M68rs_Used;
  872.     TempFloats[whichreg].count++;
  873.     return result;
  874. }
  875.  
  876. LocAMVia_t
  877. PermDataReg(void)
  878. /*
  879.  * Allocates and returns the location record for a perm data register.  If
  880.  * all the perm data registers are full, then the caller is out of luck.
  881.  */
  882. {
  883.     LocAMVia_t                      result;
  884.     int                             whichreg;
  885.     whichreg = AvailDataPerm();
  886.     if (!whichreg) {
  887.     return NULL;
  888.     }
  889.     result = BuildDRegLocation(whichreg);
  890.     TempDatas[whichreg].holder = result;
  891.     TempDatas[whichreg].status = M68rs_Used;
  892.     TempDatas[whichreg].count++;
  893.     return result;
  894. }
  895.  
  896. LocAMVia_t
  897. TempDataReg(InstListVia_t Codes)
  898. /*
  899.  * Allocates and returns the location record for a temporary data register.
  900.  * If all the temp data registers are full, then one is spilled onto the
  901.  * stack to make room.
  902.  */
  903. {
  904.     LocAMVia_t                      result;
  905.     SpillSlotVia_t                  slot;
  906.     NextTempDataReg = AvailDataReg();
  907.     result = BuildDRegLocation(NextTempDataReg);
  908.     if (TempDatas[NextTempDataReg].status != M68rs_Available) {
  909.     slot = SpillTemp(TempDatas[NextTempDataReg].holder, Codes);
  910.     TempDatas[NextTempDataReg].waiting++;
  911.     }
  912.     TempDatas[NextTempDataReg].holder = result;
  913.     TempDatas[NextTempDataReg].status = M68rs_Used;
  914.     TempDatas[NextTempDataReg].count++;
  915.     NextTempDataReg = (NextTempDataReg + 1) % NUMOFTEMPDATAREGS;
  916.     return result;
  917. }
  918.  
  919. LocAMVia_t
  920. DictateTempFloat(LocAMVia_t operand, InstListVia_t Codes)
  921. /*
  922.  * Ensures the the loc passed is a temp float register, generating a move
  923.  * instruction to make it so, if necessary.
  924.  */
  925. {
  926.     LocAMVia_t                      result;
  927.     if (gProject->itsOptions->useMC68881) {
  928.     if (GetLocAM(operand) == M68am_FReg) {
  929.         if (isTempReg(operand)) {
  930.         return operand;
  931.         }
  932.     }
  933.     } else {
  934.     if (GetLocAM(operand) == M68am_FSANEtemp) {
  935.         return operand;
  936.     }
  937.     }
  938.     if (isTempReg(operand)) {
  939.     FreeTemp(operand);
  940.     }
  941.     result = TempFloatReg(Codes);
  942.     Genmove(GetLocSZ(operand), operand, result, Codes);
  943.     return result;
  944. }
  945.  
  946. LocAMVia_t
  947. DictateAnyFReg(LocAMVia_t operand, InstListVia_t Codes)
  948. /*
  949.  * Ensures the the loc passed is a float register, allocating a temp to make
  950.  * it so, if necessary.
  951.  */
  952. {
  953.     if (operand) {
  954.     if (GetLocAM(operand) != M68am_FReg) {
  955.         operand = DictateTempFloat(operand, Codes);
  956.     }
  957.     }
  958.     return operand;
  959. }
  960.  
  961. LocAMVia_t
  962. DictateAnyDReg(LocAMVia_t operand, InstListVia_t Codes)
  963. /*
  964.  * Ensures the the loc passed is an data register, allocating a temp to make
  965.  * it so, if necessary.
  966.  */
  967. {
  968.     if (operand) {
  969.     if (GetLocAM(operand) != M68am_DReg) {
  970.         operand = DictateTempDReg(operand, Codes);
  971.     }
  972.     }
  973.     return operand;
  974. }
  975.  
  976. LocAMVia_t
  977. DictateAnyAReg(LocAMVia_t operand, InstListVia_t Codes)
  978. /*
  979.  * Ensures the the loc passed is an addr register, allocating a temp to make
  980.  * it so, if necessary.
  981.  */
  982. {
  983.     if (operand) {
  984.     if (GetLocAM(operand) != M68am_ARegDirect) {
  985.         operand = DictateTempAReg(operand, Codes);
  986.     }
  987.     }
  988.     return operand;
  989. }
  990.  
  991. LocAMVia_t
  992. DictateTempAReg(LocAMVia_t operand, InstListVia_t Codes)
  993. /*
  994.  * Ensures the the loc passed is a temp addr register, generating a move
  995.  * instruction to make it so, if necessary.
  996.  */
  997. {
  998.     LocAMVia_t                      result;
  999.     ValidateReg(operand, Codes);
  1000.     if (GetLocAM(operand) == M68am_ARegDirect) {
  1001.     if (isTempReg(operand)) {
  1002.         return operand;
  1003.     }
  1004.     }
  1005.     if (isTempReg(operand)) {
  1006.     FreeTemp(operand);
  1007.     }
  1008.     result = TempAddrReg(Codes);
  1009.     SetLocSZ(result, GetLocSZ(operand));
  1010.     Genmove(GetLocSZ(operand), operand, result, Codes);
  1011.     return result;
  1012. }
  1013.  
  1014. LocAMVia_t
  1015. DictateTempDReg(LocAMVia_t operand, InstListVia_t Codes)
  1016. /*
  1017.  * Ensures the the loc passed is a temp data register, generating a move
  1018.  * instruction to make it so, if necessary.
  1019.  */
  1020. {
  1021.     LocAMVia_t                      result;
  1022.     if (GetLocAM(operand) == M68am_DReg) {
  1023.     if (isTempReg(operand)) {
  1024.         return operand;
  1025.     }
  1026.     }
  1027.     if (isTempReg(operand)) {
  1028.     FreeTemp(operand);
  1029.     }
  1030.     result = TempDataReg(Codes);
  1031.     SetLocSZ(result, GetLocSZ(operand));
  1032.     if (GetLocSZ(operand) == M68sz_none) {
  1033.     Gen68Error("Missing size in dictatetempdreg");
  1034.     }
  1035.     Genmove(GetLocSZ(operand), operand, result, Codes);
  1036.     /*
  1037.      * TODO Here, do we need to sign extend or something if this is not a
  1038.      * long ?
  1039.      */
  1040.     return result;
  1041. }
  1042.  
  1043. void
  1044. SaveDataRegisters(InstListVia_t Codes)
  1045. /*
  1046.  * Spills all used data registers, leaving them all free for use. This
  1047.  * routine is used before all library calls.
  1048.  */
  1049. {
  1050.     int                             ndx;
  1051.  
  1052.     ndx = 0;
  1053.     while (ndx <= MAXTEMPDATAREG) {
  1054.     if (TempDatas[ndx].status != M68rs_Available) {
  1055.         SpillTemp(TempDatas[ndx].holder, Codes);
  1056.         TempDatas[ndx].status = M68rs_Available;
  1057.         TempDatas[ndx].holder = NULL;
  1058.     }
  1059.     ndx++;
  1060.     }
  1061. }
  1062.  
  1063. void
  1064. SaveTheRegisters(InstListVia_t Codes)
  1065. /*
  1066.  * Spills all used registers, leaving them all free for use.  This routine is
  1067.  * used before all function calls.
  1068.  */
  1069. {
  1070.     int                             ndx;
  1071.  
  1072.     ndx = 0;
  1073.     while (ndx <= MAXTEMPADDRREG) {
  1074.     if (TempAddrs[ndx].status != M68rs_Available) {
  1075.         SpillTemp(TempAddrs[ndx].holder, Codes);
  1076.         TempAddrs[ndx].status = M68rs_Available;
  1077.         TempAddrs[ndx].holder = NULL;
  1078.     }
  1079.     ndx++;
  1080.     }
  1081.     ndx = 0;
  1082.     while (ndx <= MAXTEMPFLOATREG) {
  1083.     if (TempFloats[ndx].status != M68rs_Available) {
  1084.         SpillTemp(TempFloats[ndx].holder, Codes);
  1085.         TempFloats[ndx].status = M68rs_Available;
  1086.         TempFloats[ndx].holder = NULL;
  1087.     }
  1088.     ndx++;
  1089.     }
  1090.     ndx = 0;
  1091.     while (ndx <= MAXTEMPDATAREG) {
  1092.     if (TempDatas[ndx].status != M68rs_Available) {
  1093.         SpillTemp(TempDatas[ndx].holder, Codes);
  1094.         TempDatas[ndx].status = M68rs_Available;
  1095.         TempDatas[ndx].holder = NULL;
  1096.     }
  1097.     ndx++;
  1098.     }
  1099. }
  1100.