Annotation of gcc/config/fx80/fx80.c, revision 1.1.1.2

1.1       root        1: /* Subroutines for insn-output.c for Alliant FX computers.
                      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
1.1.1.2 ! root       18: the Free Software Foundation, 59 Temple Place - Suite 330,
        !            19: Boston, MA 02111-1307, USA.  */
1.1       root       20: 
                     21: 
                     22: /* Some output-actions in alliant.md need these.  */
                     23: #include <stdio.h>
                     24: #include "config.h"
                     25: #include "rtl.h"
                     26: #include "regs.h"
                     27: #include "hard-reg-set.h"
                     28: #include "real.h"
                     29: #include "insn-config.h"
                     30: #include "conditions.h"
                     31: #include "insn-flags.h"
                     32: #include "output.h"
                     33: #include "insn-attr.h"
                     34: 
                     35: /* Index into this array by (register number >> 3) to find the
                     36:    smallest class which contains that register.  */
                     37: enum reg_class regno_reg_class[]
                     38:   = { DATA_REGS, ADDR_REGS, FP_REGS };
                     39: 
                     40: static rtx find_addr_reg ();
                     41: 
                     42: char *
                     43: output_btst (operands, countop, dataop, insn, signpos)
                     44:      rtx *operands;
                     45:      rtx countop, dataop;
                     46:      rtx insn;
                     47:      int signpos;
                     48: {
                     49:   operands[0] = countop;
                     50:   operands[1] = dataop;
                     51: 
                     52:   if (GET_CODE (countop) == CONST_INT)
                     53:     {
                     54:       register int count = INTVAL (countop);
                     55:       /* If COUNT is bigger than size of storage unit in use,
                     56:         advance to the containing unit of same size.  */
                     57:       if (count > signpos)
                     58:        {
                     59:          int offset = (count & ~signpos) / 8;
                     60:          count = count & signpos;
                     61:          operands[1] = dataop = adj_offsettable_operand (dataop, offset);
                     62:        }
                     63:       if (count == signpos)
                     64:        cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
                     65:       else
                     66:        cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
                     67: 
                     68:       /* These three statements used to use next_insns_test_no...
                     69:         but it appears that this should do the same job.  */
                     70:       if (count == 31
                     71:          && next_insn_tests_no_inequality (insn))
                     72:        return "tst%.l %1";
                     73:       if (count == 15
                     74:          && next_insn_tests_no_inequality (insn))
                     75:        return "tst%.w %1";
                     76:       if (count == 7
                     77:          && next_insn_tests_no_inequality (insn))
                     78:        return "tst%.b %1";
                     79: 
                     80:       cc_status.flags = CC_NOT_NEGATIVE;
                     81:     }
                     82:   return "btst %0,%1";
                     83: }
                     84: 
                     85: /* Return the best assembler insn template
                     86:    for moving operands[1] into operands[0] as a fullword.  */
                     87: 
                     88: static char *
                     89: singlemove_string (operands)
                     90:      rtx *operands;
                     91: {
                     92:   if (operands[1] != const0_rtx)
                     93:     return "mov%.l %1,%0";
                     94:   if (! ADDRESS_REG_P (operands[0]))
                     95:     return "clr%.l %0";
                     96:   return "sub%.l %0,%0";
                     97: }
                     98: 
                     99: /* Output assembler code to perform a doubleword move insn
                    100:    with operands OPERANDS.  */
                    101: 
                    102: char *
                    103: output_move_double (operands)
                    104:      rtx *operands;
                    105: {
                    106:   enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, CNSTOP, RNDOP } optype0, optype1;
                    107:   rtx latehalf[2];
                    108:   rtx addreg0 = 0, addreg1 = 0;
                    109: 
                    110:   /* First classify both operands.  */
                    111: 
                    112:   if (REG_P (operands[0]))
                    113:     optype0 = REGOP;
                    114:   else if (offsettable_memref_p (operands[0]))
                    115:     optype0 = OFFSOP;
                    116:   else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
                    117:     optype0 = POPOP;
                    118:   else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
                    119:     optype0 = PUSHOP;
                    120:   else if (GET_CODE (operands[0]) == MEM)
                    121:     optype0 = MEMOP;
                    122:   else
                    123:     optype0 = RNDOP;
                    124: 
                    125:   if (REG_P (operands[1]))
                    126:     optype1 = REGOP;
                    127:   else if (CONSTANT_P (operands[1]))
                    128:     optype1 = CNSTOP;
                    129:   else if (offsettable_memref_p (operands[1]))
                    130:     optype1 = OFFSOP;
                    131:   else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC)
                    132:     optype1 = POPOP;
                    133:   else if (GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
                    134:     optype1 = PUSHOP;
                    135:   else if (GET_CODE (operands[1]) == MEM)
                    136:     optype1 = MEMOP;
                    137:   else
                    138:     optype1 = RNDOP;
                    139: 
                    140:   /* Check for the cases that the operand constraints are not
                    141:      supposed to allow to happen.  Abort if we get one,
                    142:      because generating code for these cases is painful.  */
                    143: 
                    144:   if (optype0 == RNDOP || optype1 == RNDOP)
                    145:     abort ();
                    146: 
                    147:   /* If one operand is decrementing and one is incrementing
                    148:      decrement the former register explicitly
                    149:      and change that operand into ordinary indexing.  */
                    150: 
                    151:   if (optype0 == PUSHOP && optype1 == POPOP)
                    152:     {
                    153:       operands[0] = XEXP (XEXP (operands[0], 0), 0);
                    154:       output_asm_insn ("subq%.l %#8,%0", operands);
                    155:       operands[0] = gen_rtx (MEM, DImode, operands[0]);
                    156:       optype0 = OFFSOP;
                    157:     }
                    158:   if (optype0 == POPOP && optype1 == PUSHOP)
                    159:     {
                    160:       operands[1] = XEXP (XEXP (operands[1], 0), 0);
                    161:       output_asm_insn ("subq%.l %#8,%1", operands);
                    162:       operands[1] = gen_rtx (MEM, DImode, operands[1]);
                    163:       optype1 = OFFSOP;
                    164:     }
                    165: 
                    166:   /* If an operand is an unoffsettable memory ref, find a register
                    167:      we can increment temporarily to make it refer to the second word.  */
                    168: 
                    169:   if (optype0 == MEMOP)
                    170:     addreg0 = find_addr_reg (XEXP (operands[0], 0));
                    171: 
                    172:   if (optype1 == MEMOP)
                    173:     addreg1 = find_addr_reg (XEXP (operands[1], 0));
                    174: 
                    175:   /* Ok, we can do one word at a time.
                    176:      Normally we do the low-numbered word first,
                    177:      but if either operand is autodecrementing then we
                    178:      do the high-numbered word first.
                    179: 
                    180:      In either case, set up in LATEHALF the operands to use
                    181:      for the high-numbered word and in some cases alter the
                    182:      operands in OPERANDS to be suitable for the low-numbered word.  */
                    183: 
                    184:   if (optype0 == REGOP)
                    185:     latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
                    186:   else if (optype0 == OFFSOP)
                    187:     latehalf[0] = adj_offsettable_operand (operands[0], 4);
                    188:   else
                    189:     latehalf[0] = operands[0];
                    190: 
                    191:   if (optype1 == REGOP)
                    192:     latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
                    193:   else if (optype1 == OFFSOP)
                    194:     latehalf[1] = adj_offsettable_operand (operands[1], 4);
                    195:   else if (optype1 == CNSTOP)
                    196:     {
                    197:       if (GET_CODE (operands[1]) == CONST_DOUBLE)
                    198:        split_double (operands[1], &operands[1], &latehalf[1]);
                    199:       else if (CONSTANT_P (operands[1]))
                    200:        {
                    201:          latehalf[1] = operands[1];
                    202:          operands[1] = const0_rtx;
                    203:        }
                    204:     }
                    205:   else
                    206:     latehalf[1] = operands[1];
                    207: 
                    208:   /* If insn is effectively movd N(sp),-(sp) then we will do the
                    209:      high word first.  We should use the adjusted operand 1 (which is N+4(sp))
                    210:      for the low word as well, to compensate for the first decrement of sp.  */
                    211:   if (optype0 == PUSHOP
                    212:       && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
                    213:       && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1]))
                    214:     operands[1] = latehalf[1];
                    215: 
                    216:   /* If one or both operands autodecrementing,
                    217:      do the two words, high-numbered first.  */
                    218: 
                    219:   /* Likewise,  the first move would clobber the source of the second one,
                    220:      do them in the other order.  This happens only for registers;
                    221:      such overlap can't happen in memory unless the user explicitly
                    222:      sets it up, and that is an undefined circumstance.  */
                    223: 
                    224:   if (optype0 == PUSHOP || optype1 == PUSHOP
                    225:       || (optype0 == REGOP && optype1 == REGOP
                    226:          && REGNO (operands[0]) == REGNO (latehalf[1])))
                    227:     {
                    228:       /* Make any unoffsettable addresses point at high-numbered word.  */
                    229:       if (addreg0)
                    230:        output_asm_insn ("addql %#4,%0", &addreg0);
                    231:       if (addreg1)
                    232:        output_asm_insn ("addql %#4,%0", &addreg1);
                    233: 
                    234:       /* Do that word.  */
                    235:       output_asm_insn (singlemove_string (latehalf), latehalf);
                    236: 
                    237:       /* Undo the adds we just did.  */
                    238:       if (addreg0)
                    239:        output_asm_insn ("subql %#4,%0", &addreg0);
                    240:       if (addreg1)
                    241:        output_asm_insn ("subql %#4,%0", &addreg1);
                    242: 
                    243:       /* Do low-numbered word.  */
                    244:       return singlemove_string (operands);
                    245:     }
                    246: 
                    247:   /* Normal case: do the two words, low-numbered first.  */
                    248: 
                    249:   output_asm_insn (singlemove_string (operands), operands);
                    250: 
                    251:   /* Make any unoffsettable addresses point at high-numbered word.  */
                    252:   if (addreg0)
                    253:     output_asm_insn ("addql %#4,%0", &addreg0);
                    254:   if (addreg1)
                    255:     output_asm_insn ("addql %#4,%0", &addreg1);
                    256: 
                    257:   /* Do that word.  */
                    258:   output_asm_insn (singlemove_string (latehalf), latehalf);
                    259: 
                    260:   /* Undo the adds we just did.  */
                    261:   if (addreg0)
                    262:     output_asm_insn ("subql %#4,%0", &addreg0);
                    263:   if (addreg1)
                    264:     output_asm_insn ("subql %#4,%0", &addreg1);
                    265: 
                    266:   return "";
                    267: }
                    268: 
                    269: /* Return a REG that occurs in ADDR with coefficient 1.
                    270:    ADDR can be effectively incremented by incrementing REG.  */
                    271: 
                    272: static rtx
                    273: find_addr_reg (addr)
                    274:      rtx addr;
                    275: {
                    276:   while (GET_CODE (addr) == PLUS)
                    277:     {
                    278:       if (GET_CODE (XEXP (addr, 0)) == REG)
                    279:        addr = XEXP (addr, 0);
                    280:       else if (GET_CODE (XEXP (addr, 1)) == REG)
                    281:        addr = XEXP (addr, 1);
                    282:       else if (CONSTANT_P (XEXP (addr, 0)))
                    283:        addr = XEXP (addr, 1);
                    284:       else if (CONSTANT_P (XEXP (addr, 1)))
                    285:        addr = XEXP (addr, 0);
                    286:       else
                    287:        abort ();
                    288:     }
                    289:   if (GET_CODE (addr) == REG)
                    290:     return addr;
                    291:   abort ();
                    292: }
                    293: 
                    294: int
                    295: standard_SunFPA_constant_p (x)
                    296:      rtx x;
                    297: {
                    298:   return( 0 );
                    299: }
                    300: 

unix.superglobalmegacorp.com

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