home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / gcc-2.3.3-src.lha / GNU / src / amiga / gcc-2.3.3 / config / tahoe.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  14KB  |  565 lines

  1. /* Subroutines for insn-output.c for Tahoe.
  2.    Copyright (C) 1989, 1991 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU CC.
  5.  
  6. GNU CC is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU CC is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU CC; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. #include "config.h"
  22. #include "rtl.h"
  23. #include "regs.h"
  24. #include "hard-reg-set.h"
  25. #include "real.h"
  26. #include "insn-config.h"
  27. #include "conditions.h"
  28. #include "insn-flags.h"
  29. #include "output.h"
  30. #include "insn-attr.h"
  31.  
  32. /*
  33.  * File: output-tahoe.c
  34.  *
  35.  * Original port made at the University of Buffalo by Devon Bowen,
  36.  * Dale Wiles and Kevin Zachmann.
  37.  *
  38.  * Changes for HCX by Piet van Oostrum,
  39.  * University of Utrecht, The Netherlands (piet@cs.ruu.nl)
  40.  *
  41.  * Speed tweaks by Michael Tiemann (tiemann@lurch.stanford.edu).
  42.  *
  43.  * Mail bugs reports or fixes to:    gcc@cs.buffalo.edu
  44.  */
  45.  
  46.  
  47. /* On tahoe, you have to go to memory to convert a register
  48.    from sub-word to word.  */
  49.  
  50. rtx tahoe_reg_conversion_loc;
  51.  
  52. int
  53. extendable_operand (op, mode)
  54.      rtx op;
  55.      enum machine_mode mode;
  56. {
  57.   if ((GET_CODE (op) == REG
  58.        || (GET_CODE (op) == SUBREG
  59.        && GET_CODE (SUBREG_REG (op)) == REG))
  60.       && tahoe_reg_conversion_loc == 0)
  61.     tahoe_reg_conversion_loc = assign_stack_local (SImode, GET_MODE_SIZE (SImode));
  62.   return general_operand (op, mode);
  63. }
  64.  
  65. /* most of the print_operand_address function was taken from the vax    */
  66. /* since the modes are basically the same. I had to add a special case,    */
  67. /* though, for symbol references with offsets.                */
  68.  
  69. #include <stdio.h>
  70.  
  71. print_operand_address (file, addr)
  72.      FILE *file;
  73.      register rtx addr;
  74. {
  75.   register rtx reg1, reg2, breg, ireg;
  76.   rtx offset;
  77.   static char *reg_name[] = REGISTER_NAMES;
  78.  
  79.  retry:
  80.   switch (GET_CODE (addr))
  81.     {
  82.     case MEM:
  83.       fprintf (file, "*");
  84.       addr = XEXP (addr, 0);
  85.       goto retry;
  86.  
  87.     case REG:
  88.       fprintf (file, "(%s)", reg_name [REGNO (addr)]);
  89.       break;
  90.  
  91.     case PRE_DEC:
  92.       fprintf (file, "-(%s)", reg_name [REGNO (XEXP (addr, 0))]);
  93.       break;
  94.  
  95.     case POST_INC:
  96.       fprintf (file, "(%s)+", reg_name [REGNO (XEXP (addr, 0))]);
  97.       break;
  98.  
  99.     case PLUS:
  100.       reg1 = 0;    reg2 = 0;
  101.       ireg = 0;    breg = 0;
  102.       offset = 0;
  103.  
  104.       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
  105.       && GET_CODE (XEXP (addr, 1)) == CONST_INT)
  106.     output_addr_const (file, addr);
  107.  
  108.       if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
  109.       && GET_CODE (XEXP (addr, 0)) == CONST_INT)
  110.     output_addr_const (file, addr);
  111.  
  112.       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
  113.       || GET_CODE (XEXP (addr, 0)) == MEM)
  114.     {
  115.       offset = XEXP (addr, 0);
  116.       addr = XEXP (addr, 1);
  117.     }
  118.       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
  119.            || GET_CODE (XEXP (addr, 1)) == MEM)
  120.     {
  121.       offset = XEXP (addr, 1);
  122.       addr = XEXP (addr, 0);
  123.     }
  124.       if (GET_CODE (addr) != PLUS)
  125.     ;
  126.       else if (GET_CODE (XEXP (addr, 0)) == MULT)
  127.     {
  128.       reg1 = XEXP (addr, 0);
  129.       addr = XEXP (addr, 1);
  130.     }
  131.       else if (GET_CODE (XEXP (addr, 1)) == MULT)
  132.     {
  133.       reg1 = XEXP (addr, 1);
  134.       addr = XEXP (addr, 0);
  135.     }
  136.       else if (GET_CODE (XEXP (addr, 0)) == REG)
  137.     {
  138.       reg1 = XEXP (addr, 0);
  139.       addr = XEXP (addr, 1);
  140.     }
  141.       else if (GET_CODE (XEXP (addr, 1)) == REG)
  142.     {
  143.       reg1 = XEXP (addr, 1);
  144.       addr = XEXP (addr, 0);
  145.     }
  146.       if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT)
  147.     {
  148.       if (reg1 == 0)
  149.         reg1 = addr;
  150.       else
  151.         reg2 = addr;
  152.       addr = 0;
  153.     }
  154.       if (offset != 0)
  155.     {
  156.       if (addr != 0) abort ();
  157.       addr = offset;
  158.     }
  159.       if (reg1 != 0 && GET_CODE (reg1) == MULT)
  160.     {
  161.       breg = reg2;
  162.       ireg = reg1;
  163.     }
  164.       else if (reg2 != 0 && GET_CODE (reg2) == MULT)
  165.     {
  166.       breg = reg1;
  167.       ireg = reg2;
  168.     }
  169.       else if (reg2 != 0 || GET_CODE (addr) == MEM)
  170.     {
  171.       breg = reg2;
  172.       ireg = reg1;
  173.     }
  174.       else
  175.     {
  176.       breg = reg1;
  177.       ireg = reg2;
  178.     }
  179.       if (addr != 0)
  180.     output_address (offset);
  181.       if (breg != 0)
  182.     {
  183.       if (GET_CODE (breg) != REG)
  184.         abort ();
  185.       fprintf (file, "(%s)", reg_name[REGNO (breg)]);
  186.     }
  187.       if (ireg != 0)
  188.     {
  189.       if (GET_CODE (ireg) == MULT)
  190.         ireg = XEXP (ireg, 0);
  191.       if (GET_CODE (ireg) != REG)
  192.         abort ();
  193.       fprintf (file, "[%s]", reg_name[REGNO (ireg)]);
  194.     }
  195.       break;
  196.  
  197.     default:
  198.       output_addr_const (file, addr);
  199.     }
  200. }
  201.  
  202. /* Do a quick check and find out what the best way to do the */
  203. /* mini-move is. Could be a push or a move.....             */
  204.  
  205. static char *
  206. singlemove_string (operands)
  207.      rtx *operands;
  208. {
  209.   if (operands[1] == const0_rtx)
  210.       return "clrl %0";
  211.   if (push_operand (operands[0], SImode))
  212.     return "pushl %1";
  213.   return "movl %1,%0";
  214. }
  215.  
  216. /* given the rtx for an address, return true if the given */
  217. /* register number is used in the address somewhere.      */
  218.  
  219. regisused(addr,regnum)
  220. rtx addr;
  221. int regnum;
  222. {
  223.     if (GET_CODE(addr) == REG)
  224.         if (REGNO(addr) == regnum)
  225.             return (1);
  226.         else
  227.             return (0);
  228.  
  229.     if (GET_CODE(addr) == MEM)
  230.         return regisused(XEXP(addr,0),regnum);
  231.  
  232.     if ((GET_CODE(addr) == MULT) || (GET_CODE(addr) == PLUS))
  233.         return ((regisused(XEXP(addr,0),regnum)) ||
  234.                     (regisused(XEXP(addr,1),regnum)));
  235.  
  236.     return 0;
  237. }
  238.  
  239.  
  240. /* Given some rtx, traverse it and return the register used in a */
  241. /* index. If no index is found, return 0.             */
  242.  
  243. rtx
  244. index_reg(addr)
  245. rtx addr;
  246. {
  247.     rtx temp;
  248.  
  249.     if (GET_CODE(addr) == MEM)
  250.         return index_reg(XEXP(addr,0));
  251.  
  252.     if (GET_CODE(addr) == MULT)
  253.         if (GET_CODE(XEXP(addr,0)) == REG)
  254.             return XEXP(addr,0);
  255.         else
  256.             return XEXP(addr,1);
  257.  
  258.     if (GET_CODE(addr) == PLUS)
  259.         if (temp = index_reg(XEXP(addr,0)))
  260.             return temp;
  261.         else
  262.             return index_reg(XEXP(addr,1));
  263.  
  264.     return 0;
  265. }
  266.  
  267.  
  268. /* simulate the move double by generating two movl's. You have */
  269. /* to be careful about mixing modes here.               */
  270.  
  271. char *
  272. output_move_double (operands)
  273.      rtx *operands;
  274. {
  275.   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, INDOP, CNSTOP, RNDOP }
  276.     optype0, optype1;
  277.   rtx latehalf[2];
  278.   rtx shftreg0 = 0, shftreg1 = 0;
  279.   rtx temp0 = 0, temp1 = 0;
  280.   rtx addreg0 = 0, addreg1 = 0;
  281.   int dohighfirst = 0;
  282.  
  283.   /* First classify both operands. */
  284.  
  285.   if (REG_P (operands[0]))
  286.     optype0 = REGOP;
  287.   else if ((GET_CODE(operands[0])==MEM) && (shftreg0=index_reg(operands[0])))
  288.     optype0 = INDOP;
  289.   else if (offsettable_memref_p (operands[0]))
  290.     optype0 = OFFSOP;
  291.   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) {
  292.     optype0 = PUSHOP;
  293.     dohighfirst++;
  294.   } else if (GET_CODE (operands[0]) == MEM)
  295.     optype0 = MEMOP;
  296.   else
  297.     optype0 = RNDOP;
  298.  
  299.   if (REG_P (operands[1]))
  300.     optype1 = REGOP;
  301.   else if ((GET_CODE(operands[1])==MEM) && (shftreg1=index_reg(operands[1])))
  302.     optype1 = INDOP;
  303.   else if (offsettable_memref_p (operands[1]))
  304.     optype1 = OFFSOP;
  305.   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
  306.     optype1 = POPOP; 
  307.   else if (GET_CODE (operands[1]) == MEM)
  308.     optype1 = MEMOP;
  309.   else if (CONSTANT_P (operands[1]))
  310.     optype1 = CNSTOP;
  311.   else
  312.     optype1 = RNDOP;
  313.  
  314.   /* set up for the high byte move for operand zero */
  315.  
  316.   switch (optype0) {
  317.  
  318.     /* if it's a register, just use the next highest in the */
  319.     /* high address move.                    */
  320.  
  321.     case REGOP  : latehalf[0] = gen_rtx (REG,SImode,REGNO(operands[0])+1);
  322.               break;
  323.  
  324.     /* for an offsettable address, use the gcc function to  */
  325.     /* modify the operand to get an offset of 4 higher for  */
  326.     /* the second move.                    */
  327.  
  328.     case OFFSOP : latehalf[0] = adj_offsettable_operand (operands[0], 4);
  329.               break;
  330.  
  331.     /* if the operand is MEMOP type, it must be a pointer    */
  332.     /* to a pointer. So just remember to increase the mem    */
  333.     /* location and use the same operand.            */
  334.  
  335.     case MEMOP  : latehalf[0] = operands[0];
  336.               addreg0 = XEXP(operands[0],0);
  337.               break;
  338.  
  339.     /* if we're dealing with a push instruction, just leave */
  340.     /* the operand alone since it auto-increments.        */
  341.  
  342.     c