Annotation of gcc/config/out-alliant.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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