Annotation of gcc/config/convex.c, revision 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.