/* Subroutines for insn-output.c for Vax. Copyright (C) 1987 Free Software Foundation, Inc. This file is part of GNU CC. GNU CC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include "config.h" #include "rtl.h" #include "regs.h" #include "hard-reg-set.h" #include "real.h" #include "insn-config.h" #include "conditions.h" #include "insn-flags.h" #include "output.h" #include "insn-attr.h" /* Return 1 if the operand is a REG, a SUBREG, or a MEM that is does not have an index. This is used when we are using an operand in a different mode than the hardware expects. See jlbc/jlbs. This is nonimmedate_operand with a restriction on the type of MEM. */ int reg_or_nxmem_operand (op, mode) rtx op; enum machine_mode mode; { if (! nonimmediate_operand (op, mode)) return 0; if (GET_CODE (op) != MEM) return 1; GO_IF_NONINDEXED_ADDRESS (XEXP (op, 0), nonidx); return 0; nonidx: return 1; } void split_quadword_operands (operands, low, n) rtx *operands, *low; int n; { int i; /* Split operands. */ low[0] = low[1] = low[2] = 0; for (i = 0; i < 3; i++) { if (low[i]) /* it's already been figured out */; else if (GET_CODE (operands[i]) == MEM && (GET_CODE (XEXP (operands[i], 0)) == POST_INC)) { rtx addr = XEXP (operands[i], 0); operands[i] = low[i] = gen_rtx (MEM, SImode, addr); if (which_alternative == 0 && i == 0) { addr = XEXP (operands[i], 0); operands[i+1] = low[i+1] = gen_rtx (MEM, SImode, addr); } } else { low[i] = operand_subword (operands[i], 0, 0, DImode); operands[i] = operand_subword (operands[i], 1, 0, DImode); } } } print_operand_address (file, addr) FILE *file; register rtx addr; { register rtx reg1, reg2, breg, ireg; rtx offset; retry: switch (GET_CODE (addr)) { case MEM: fprintf (file, "*"); addr = XEXP (addr, 0); goto retry; case REG: fprintf (file, "(%s)", reg_names[REGNO (addr)]); break; case PRE_DEC: fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]); break; case POST_INC: fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]); break; case PLUS: /* There can be either two or three things added here. One must be a REG. One can be either a REG or a MULT of a REG and an appropriate constant, and the third can only be a constant or a MEM. We get these two or three things and put the constant or MEM in OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have a register and can't tell yet if it is a base or index register, put it into REG1. */ reg1 = 0; ireg = 0; breg = 0; offset = 0; if (CONSTANT_ADDRESS_P (XEXP (addr, 0)) || GET_CODE (XEXP (addr, 0)) == MEM) { offset = XEXP (addr, 0); addr = XEXP (addr, 1); } else if (CONSTANT_ADDRESS_P (XEXP (addr, 1)) || GET_CODE (XEXP (addr, 1)) == MEM) { offset = XEXP (addr, 1); addr = XEXP (addr, 0); } else if (GET_CODE (XEXP (addr, 1)) == MULT) { ireg = XEXP (addr, 1); addr = XEXP (addr, 0); } else if (GET_CODE (XEXP (addr, 0)) == MULT) { ireg = XEXP (addr, 0); addr = XEXP (addr, 1); } else if (GET_CODE (XEXP (addr, 1)) == REG) { reg1 = XEXP (addr, 1); addr = XEXP (addr, 0); } else if (GET_CODE (XEXP (addr, 0)) == REG) { reg1 = XEXP (addr, 0); addr = XEXP (addr, 1); } else abort (); if (GET_CODE (addr) == REG) { if (reg1) ireg = addr; else reg1 = addr; } else if (GET_CODE (addr) == MULT) ireg = addr; else if (GET_CODE (addr) == PLUS) { if (CONSTANT_ADDRESS_P (XEXP (addr, 0)) || GET_CODE (XEXP (addr, 0)) == MEM) { if (offset) { if (GET_CODE (offset) == CONST_INT) offset = plus_constant (XEXP (addr, 0), INTVAL (offset)); else if (GET_CODE (XEXP (addr, 0)) == CONST_INT) offset = plus_constant (offset, INTVAL (XEXP (addr, 0))); else abort (); } offset = XEXP (addr, 0); } else if (GET_CODE (XEXP (addr, 0)) == REG) { if (reg1) ireg = reg1, breg = XEXP (addr, 0), reg1 = 0; else reg1 = XEXP (addr, 0); } else if (GET_CODE (XEXP (addr, 0)) == MULT) { if (ireg) abort (); ireg = XEXP (addr, 0); } else abort (); if (CONSTANT_ADDRESS_P (XEXP (addr, 1)) || GET_CODE (XEXP (addr, 1)) == MEM) { if (offset) { if (GET_CODE (offset) == CONST_INT) offset = plus_constant (XEXP (addr, 1), INTVAL (offset)); else if (GET_CODE (XEXP (addr, 1)) == CONST_INT) offset = plus_constant (offset, INTVAL (XEXP (addr, 1))); else abort (); } offset = XEXP (addr, 1); } else if (GET_CODE (XEXP (addr, 1)) == REG) { if (reg1) ireg = reg1, breg = XEXP (addr, 1), reg1 = 0; else reg1 = XEXP (addr, 1); } else if (GET_CODE (XEXP (addr, 1)) == MULT) { if (ireg) abort (); ireg = XEXP (addr, 1); } else abort (); } else abort (); /* If REG1 is non-zero, figure out if it is a base or index register. */ if (reg1) { if (breg != 0 || (offset && GET_CODE (offset) == MEM)) { if (ireg) abort (); ireg = reg1; } else breg = reg1; } if (offset != 0) output_address (offset); if (breg != 0) fprintf (file, "(%s)", reg_names[REGNO (breg)]); if (ireg != 0) { if (GET_CODE (ireg) == MULT) ireg = XEXP (ireg, 0); if (GET_CODE (ireg) != REG) abort (); fprintf (file, "[%s]", reg_names[REGNO (ireg)]); } break; default: output_addr_const (file, addr); } } char * rev_cond_name (op) rtx op; { switch (GET_CODE (op)) { case EQ: return "neq"; case NE: return "eql"; case LT: return "geq"; case LE: return "gtr"; case GT: return "leq"; case GE: return "lss"; case LTU: return "gequ"; case LEU: return "gtru"; case GTU: return "lequ"; case GEU: return "lssu"; default: abort (); } }