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 / convex.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  6KB  |  221 lines

  1. /* Subroutines for insn-output.c for Convex.
  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 1, 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. #include "config.h"
  21. #include "rtl.h"
  22. #include "regs.h"
  23. #include "hard-reg-set.h"
  24. #include "real.h"
  25. #include "insn-config.h"
  26. #include "conditions.h"
  27. #include "insn-flags.h"
  28. #include "output.h"
  29. #include "insn-attr.h"
  30.  
  31. /* Boolean to keep track of whether the current section is .text or not.
  32.    Used by .align handler in convex.h. */
  33.  
  34. int current_section_is_text;
  35.  
  36. /* set_cmp saves the operands of a "cmp" insn, along with the type character
  37.  * to be used in the compare instruction.
  38.  *
  39.  * gen_cmp finds out what comparison is to be performed and outputs the
  40.  * necessary instructions, e.g.
  41.  *    "eq.w a1,a2\;jbra.t L5"
  42.  * for (cmpsi a1 a2) (beq L5)  */
  43.  
  44. static rtx xop0, xop1;
  45. static char typech, regch;
  46.  
  47. char *
  48. set_cmp (op0, op1, typechr)
  49.      rtx op0, op1;
  50.      char typechr;
  51. {
  52.   xop0 = op0;
  53.   xop1 = op1;
  54.   typech = typechr;
  55.   if (GET_CODE (op0) == REG)
  56.     regch = A_REGNO_P (REGNO (op0)) ? 'a' : 's';
  57.   else if (GET_CODE (op1) == REG)
  58.     regch = A_REGNO_P (REGNO (op1)) ? 'a' : 's';
  59.   else abort ();
  60.   return "";
  61. }
  62.  
  63. char *
  64. gen_cmp (label, cmpop, tf)
  65.      rtx label;
  66.      char *cmpop;
  67.      char tf;
  68. {
  69.   char buf[80];
  70.   char revop[4];
  71.   rtx ops[3];
  72.  
  73.   ops[2] = label;
  74.  
  75.   /* Constant must be first; swap operands if necessary.
  76.      If lt, le, ltu, leu are swapped, change to le, lt, leu, ltu
  77.      and reverse the sense of the jump. */
  78.  
  79.   if (CONSTANT_P (xop1))
  80.     {
  81.       ops[0] = xop1;
  82.       ops[1] = xop0;
  83.       if (cmpop[0] == 'l')
  84.     {
  85.       bcopy (cmpop, revop, sizeof revop);
  86.       revop[1] ^= 'e' ^ 't';
  87.       tf ^= 't' ^ 'f';
  88.       cmpop = revop;
  89.     }
  90.     }
  91.   else
  92.     {
  93.       ops[0] = xop0;
  94.       ops[1] = xop1;
  95.     }
  96.  
  97.   sprintf (buf, "%s.%c %%0,%%1\n\tjbr%c.%c %%l2", cmpop, typech, regch, tf);
  98.   output_asm_insn (buf, ops);
  99.   return "";
  100. }
  101.  
  102. /* Routines to separate CONST_DOUBLEs into component parts. */
  103.  
  104. int
  105. const_double_high_int (x)
  106.      rtx x;
  107. {
  108.   if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
  109.     return CONST_DOUBLE_LOW (x);
  110.   else
  111.     return CONST_DOUBLE_HIGH (x);
  112. }
  113.  
  114. int
  115. const_double_low_int (x)
  116.      rtx x;
  117. {
  118.   if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
  119.     return CONST_DOUBLE_HIGH (x);
  120.   else
  121.     return CONST_DOUBLE_LOW (x);
  122. }
  123.  
  124. /* Return the number of args in the call insn X. */
  125.  
  126. static int
  127. call_num_args (x)
  128.      rtx x;
  129. {
  130.   if (GET_CODE (x) == CALL)
  131.     return INTVAL (x->fld[1].rtx);
  132.   if (GET_CODE (x) == SET)
  133.     return call_num_args (SET_SRC (x));
  134.   abort ();
  135. }
  136.  
  137. /* Scan forward from a call to decide whether we need to reload AP
  138.    from 12(FP) after it.  We need to if there can be a reference to
  139.    arg_pointer_rtx before the next call, which will clobber AP.
  140.    Look forward in the instruction list until encountering a call
  141.    (don't need the load), or a reference to AP (do need it), or
  142.    a jump (don't know, do the load).  */
  143.  
  144. static int
  145. ap_reload_needed (insn)
  146.      rtx insn;
  147. {
  148.   for (;;)
  149.     {
  150.       insn = NEXT_INSN (insn);
  151.       switch (GET_CODE (insn))
  152.     {
  153.     case JUMP_INSN:
  154.       /* Basic block ends.  If return, no AP needed, else assume it is. */
  155.       return GET_CODE (PATTERN (insn)) != RETURN;
  156.     case CALL_INSN:
  157.       /* A subsequent call.  AP isn't needed unless the call itself
  158.          requires it.  But zero-arg calls don't clobber AP, so
  159.          don't terminate the search in that case. */
  160.       if (reg_mentioned_p (arg_pointer_rtx, PATTERN (insn)))
  161.         return 1;
  162.       if (! TARGET_ARGCOUNT && call_num_args (PATTERN (insn)) == 0)
  163.         break;
  164.       return 0;
  165.     case BARRIER:
  166.       /* Barrier, don't need AP. */
  167.       return 0;
  168.     case INSN:
  169.       /* Other insn may need AP; if not, keep looking. */
  170.       if (reg_mentioned_p (arg_pointer_rtx, PATTERN (insn)))
  171.         return 1;
  172.     }
  173.     }
  174. }
  175.  
  176. /* Output the insns needed to do a call. */
  177.  
  178. char *
  179. output_call (insn, address, argcount)
  180.     rtx insn, address, argcount;
  181. {
  182.   int set_ap = TARGET_ARGCOUNT || argcount != const0_rtx;
  183.  
  184.   /* If AP is used by the call address, evaluate the address into a temp. */
  185.   if (reg_mentioned_p (arg_pointer_rtx, address))
  186.     if (set_ap)
  187.       {
  188.     address = XEXP (address, 0);
  189.     output_asm_insn ("ld.w %0,a1", &address);
  190.     address = gen_rtx (MEM, QImode, gen_rtx (REG, Pmode, 9));
  191.       }
  192.  
  193.   /* If there are args, point AP to them. */
  194.   if (set_ap)
  195.     output_asm_insn ("mov sp,ap");
  196.  
  197.   /* If we are passing an arg count, convert it to words and push it. */
  198.   if (TARGET_ARGCOUNT)
  199.     {
  200.       argcount = gen_rtx (CONST_INT, VOIDmode, (INTVAL (argcount) + 3) / 4);
  201.       output_asm_insn ("pshea %a0", &argcount);
  202.     }
  203.  
  204.   /* The call. */
  205.   output_asm_insn ("calls %0", &address);
  206.  
  207.   /* If we clobbered AP, reload it if it is live. */
  208.   if (set_ap)
  209.     if (ap_reload_needed (insn))
  210.       output_asm_insn ("ld.w 12(fp),ap");
  211.  
  212.   /* If we pushed an arg count, pop it and the args. */
  213.   if (TARGET_ARGCOUNT)
  214.     {
  215.       argcount = gen_rtx (CONST_INT, VOIDmode, INTVAL (argcount) * 4 + 4);
  216.       output_asm_insn ("add.w %0,sp", &argcount);
  217.     }
  218.   
  219.   return "";
  220. }
  221.