Annotation of gcc/config/convex.c, revision 1.1.1.1

1.1       root        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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.