diff options
Diffstat (limited to 'gcc/config/tahoe/tahoe.c')
-rw-r--r-- | gcc/config/tahoe/tahoe.c | 565 |
1 files changed, 0 insertions, 565 deletions
diff --git a/gcc/config/tahoe/tahoe.c b/gcc/config/tahoe/tahoe.c deleted file mode 100644 index 6fec44418f4..00000000000 --- a/gcc/config/tahoe/tahoe.c +++ /dev/null @@ -1,565 +0,0 @@ -/* Subroutines for insn-output.c for Tahoe. - Copyright (C) 1989, 1991 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, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - - -#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" - -/* - * File: output-tahoe.c - * - * Original port made at the University of Buffalo by Devon Bowen, - * Dale Wiles and Kevin Zachmann. - * - * Changes for HCX by Piet van Oostrum, - * University of Utrecht, The Netherlands (piet@cs.ruu.nl) - * - * Speed tweaks by Michael Tiemann (tiemann@lurch.stanford.edu). - * - * Mail bugs reports or fixes to: gcc@cs.buffalo.edu - */ - - -/* On tahoe, you have to go to memory to convert a register - from sub-word to word. */ - -rtx tahoe_reg_conversion_loc; - -int -extendable_operand (op, mode) - rtx op; - enum machine_mode mode; -{ - if ((GET_CODE (op) == REG - || (GET_CODE (op) == SUBREG - && GET_CODE (SUBREG_REG (op)) == REG)) - && tahoe_reg_conversion_loc == 0) - tahoe_reg_conversion_loc = assign_stack_local (SImode, GET_MODE_SIZE (SImode)); - return general_operand (op, mode); -} - -/* most of the print_operand_address function was taken from the vax */ -/* since the modes are basically the same. I had to add a special case, */ -/* though, for symbol references with offsets. */ - -#include <stdio.h> - -print_operand_address (file, addr) - FILE *file; - register rtx addr; -{ - register rtx reg1, reg2, breg, ireg; - rtx offset; - static char *reg_name[] = REGISTER_NAMES; - - retry: - switch (GET_CODE (addr)) - { - case MEM: - fprintf (file, "*"); - addr = XEXP (addr, 0); - goto retry; - - case REG: - fprintf (file, "(%s)", reg_name [REGNO (addr)]); - break; - - case PRE_DEC: - fprintf (file, "-(%s)", reg_name [REGNO (XEXP (addr, 0))]); - break; - - case POST_INC: - fprintf (file, "(%s)+", reg_name [REGNO (XEXP (addr, 0))]); - break; - - case PLUS: - reg1 = 0; reg2 = 0; - ireg = 0; breg = 0; - offset = 0; - - if (CONSTANT_ADDRESS_P (XEXP (addr, 0)) - && GET_CODE (XEXP (addr, 1)) == CONST_INT) - output_addr_const (file, addr); - - if (CONSTANT_ADDRESS_P (XEXP (addr, 1)) - && GET_CODE (XEXP (addr, 0)) == CONST_INT) - output_addr_const (file, addr); - - 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); - } - if (GET_CODE (addr) != PLUS) - ; - else if (GET_CODE (XEXP (addr, 0)) == MULT) - { - reg1 = XEXP (addr, 0); - addr = XEXP (addr, 1); - } - else if (GET_CODE (XEXP (addr, 1)) == MULT) - { - 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 if (GET_CODE (XEXP (addr, 1)) == REG) - { - reg1 = XEXP (addr, 1); - addr = XEXP (addr, 0); - } - if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT) - { - if (reg1 == 0) - reg1 = addr; - else - reg2 = addr; - addr = 0; - } - if (offset != 0) - { - if (addr != 0) abort (); - addr = offset; - } - if (reg1 != 0 && GET_CODE (reg1) == MULT) - { - breg = reg2; - ireg = reg1; - } - else if (reg2 != 0 && GET_CODE (reg2) == MULT) - { - breg = reg1; - ireg = reg2; - } - else if (reg2 != 0 || GET_CODE (addr) == MEM) - { - breg = reg2; - ireg = reg1; - } - else - { - breg = reg1; - ireg = reg2; - } - if (addr != 0) - output_address (offset); - if (breg != 0) - { - if (GET_CODE (breg) != REG) - abort (); - fprintf (file, "(%s)", reg_name[REGNO (breg)]); - } - if (ireg != 0) - { - if (GET_CODE (ireg) == MULT) - ireg = XEXP (ireg, 0); - if (GET_CODE (ireg) != REG) - abort (); - fprintf (file, "[%s]", reg_name[REGNO (ireg)]); - } - break; - - default: - output_addr_const (file, addr); - } -} - -/* Do a quick check and find out what the best way to do the */ -/* mini-move is. Could be a push or a move..... */ - -static char * -singlemove_string (operands) - rtx *operands; -{ - if (operands[1] == const0_rtx) - return "clrl %0"; - if (push_operand (operands[0], SImode)) - return "pushl %1"; - return "movl %1,%0"; -} - -/* given the rtx for an address, return true if the given */ -/* register number is used in the address somewhere. */ - -regisused(addr,regnum) -rtx addr; -int regnum; -{ - if (GET_CODE(addr) == REG) - if (REGNO(addr) == regnum) - return (1); - else - return (0); - - if (GET_CODE(addr) == MEM) - return regisused(XEXP(addr,0),regnum); - - if ((GET_CODE(addr) == MULT) || (GET_CODE(addr) == PLUS)) - return ((regisused(XEXP(addr,0),regnum)) || - (regisused(XEXP(addr,1),regnum))); - - return 0; -} - - -/* Given some rtx, traverse it and return the register used in a */ -/* index. If no index is found, return 0. */ - -rtx -index_reg(addr) -rtx addr; -{ - rtx temp; - - if (GET_CODE(addr) == MEM) - return index_reg(XEXP(addr,0)); - - if (GET_CODE(addr) == MULT) - if (GET_CODE(XEXP(addr,0)) == REG) - return XEXP(addr,0); - else - return XEXP(addr,1); - - if (GET_CODE(addr) == PLUS) - if (temp = index_reg(XEXP(addr,0))) - return temp; - else - return index_reg(XEXP(addr,1)); - - return 0; -} - - -/* simulate the move double by generating two movl's. You have */ -/* to be careful about mixing modes here. */ - -char * -output_move_double (operands) - rtx *operands; -{ - enum { REGOP, OFFSOP, MEMOP, PUSHOP, POPOP, INDOP, CNSTOP, RNDOP } - optype0, optype1; - rtx latehalf[2]; - rtx shftreg0 = 0, shftreg1 = 0; - rtx temp0 = 0, temp1 = 0; - rtx addreg0 = 0, addreg1 = 0; - int dohighfirst = 0; - - /* First classify both operands. */ - - if (REG_P (operands[0])) - optype0 = REGOP; - else if ((GET_CODE(operands[0])==MEM) && (shftreg0=index_reg(operands[0]))) - optype0 = INDOP; - else if (offsettable_memref_p (operands[0])) - optype0 = OFFSOP; - else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) { - optype0 = PUSHOP; - dohighfirst++; - } else if (GET_CODE (operands[0]) == MEM) - optype0 = MEMOP; - else - optype0 = RNDOP; - - if (REG_P (operands[1])) - optype1 = REGOP; - else if ((GET_CODE(operands[1])==MEM) && (shftreg1=index_reg(operands[1]))) - optype1 = INDOP; - else if (offsettable_memref_p (operands[1])) - optype1 = OFFSOP; - else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC) - optype1 = POPOP; - else if (GET_CODE (operands[1]) == MEM) - optype1 = MEMOP; - else if (CONSTANT_P (operands[1])) - optype1 = CNSTOP; - else - optype1 = RNDOP; - - /* set up for the high byte move for operand zero */ - - switch (optype0) { - - /* if it's a register, just use the next highest in the */ - /* high address move. */ - - case REGOP : latehalf[0] = gen_rtx (REG,SImode,REGNO(operands[0])+1); - break; - - /* for an offsettable address, use the gcc function to */ - /* modify the operand to get an offset of 4 higher for */ - /* the second move. */ - - case OFFSOP : latehalf[0] = adj_offsettable_operand (operands[0], 4); - break; - - /* if the operand is MEMOP type, it must be a pointer */ - /* to a pointer. So just remember to increase the mem */ - /* location and use the same operand. */ - - case MEMOP : latehalf[0] = operands[0]; - addreg0 = XEXP(operands[0],0); - break; - - /* if we're dealing with a push instruction, just leave */ - /* the operand alone since it auto-increments. */ - - case PUSHOP : latehalf[0] = operands[0]; - break; - - /* YUCK! Indexed addressing!! If the address is considered */ - /* offsettable, go use the offset in the high part. Otherwise */ - /* find what exactly is being added to the multiplication. If */ - /* it's a mem reference, increment that with the high part */ - /* being unchanged to cause the shift. If it's a reg, do the */ - /* same. If you can't identify it, abort. Remember that the */ - /* shift register was already set during identification. */ - - case INDOP : if (offsettable_memref_p(operands[0])) { - latehalf[0] = adj_offsettable_operand(operands[0],4); - break; - } - - latehalf[0] = operands[0]; - - temp0 = XEXP(XEXP(operands[0],0),0); - if (GET_CODE(temp0) == MULT) { - temp1 = temp0; - temp0 = XEXP(XEXP(operands[0],0),1); - } else { - temp1 = XEXP(XEXP(operands[0],0),1); - if (GET_CODE(temp1) != MULT) - abort(); - } - - if (GET_CODE(temp0) == MEM) - addreg0 = temp0; - else if (GET_CODE(temp0) == REG) - addreg0 = temp0; - else - abort(); - - break; - - /* if we don't know the operand type, print a friendly */ - /* little error message... 8-) */ - - case RNDOP : - default : abort(); - } - - /* do the same setup for operand one */ - - switch (optype1) { - - case REGOP : latehalf[1] = gen_rtx(REG,SImode,REGNO(operands[1])+1); - break; - - case OFFSOP : latehalf[1] = adj_offsettable_operand (operands[1], 4); - break; - - case MEMOP : latehalf[1] = operands[1]; - addreg1 = XEXP(operands[1],0); - break; - - case POPOP : latehalf[1] = operands[1]; - break; - - case INDOP : if (offsettable_memref_p(operands[1])) { - latehalf[1] = adj_offsettable_operand(operands[1],4); - break; - } - - latehalf[1] = operands[1]; - - temp0 = XEXP(XEXP(operands[1],0),0); - if (GET_CODE(temp0) == MULT) { - temp1 = temp0; - temp0 = XEXP(XEXP(operands[1],0),1); - } else { - temp1 = XEXP(XEXP(operands[1],0),1); - if (GET_CODE(temp1) != MULT) - abort(); - } - - if (GET_CODE(temp0) == MEM) - addreg1 = temp0; - else if (GET_CODE(temp0) == REG) - addreg1 = temp0; - else - abort(); - - break; - - case CNSTOP : - if (GET_CODE (operands[1]) == CONST_DOUBLE) - split_double (operands[1], &operands[1], &latehalf[1]); - else if (CONSTANT_P (operands[1])) - latehalf[1] = const0_rtx; - else abort (); - break; - - case RNDOP : - default : abort(); - } - - - /* double the register used for shifting in both of the operands */ - /* but make sure the same register isn't doubled twice! */ - - if (shftreg0 && shftreg1 && (rtx_equal_p(shftreg0,shftreg1))) - output_asm_insn("addl2 %0,%0", &shftreg0); - else { - if (shftreg0) - output_asm_insn("addl2 %0,%0", &shftreg0); - if (shftreg1) - output_asm_insn("addl2 %0,%0", &shftreg1); - } - - /* if the destination is a register and that register is needed in */ - /* the source addressing mode, swap the order of the moves since we */ - /* don't want this destroyed til last. If both regs are used, not */ - /* much we can do, so abort. If these becomes a problem, maybe we */ - /* can do it on the stack? */ - - if (GET_CODE(operands[0])==REG && regisused(operands[1],REGNO(operands[0]))) - if (regisused(latehalf[1],REGNO(latehalf[0]))) - 8; - else - dohighfirst++; - - /* if we're pushing, do the high address part first. */ - - if (dohighfirst) { - - if (addreg0 && addreg1 && (rtx_equal_p(addreg0,addreg1))) - output_asm_insn("addl2 $4,%0", &addreg0); - else { - if (addreg0) - output_asm_insn("addl2 $4,%0", &addreg0); - if (addreg1) - output_asm_insn("addl2 $4,%0", &addreg1); - } - - output_asm_insn(singlemove_string(latehalf), latehalf); - - if (addreg0 && addreg1 && (rtx_equal_p(addreg0,addreg1))) - output_asm_insn("subl2 $4,%0", &addreg0); - else { - if (addreg0) - output_asm_insn("subl2 $4,%0", &addreg0); - if (addreg1) - output_asm_insn("subl2 $4,%0", &addreg1); - } - - return singlemove_string(operands); - } - - output_asm_insn(singlemove_string(operands), operands); - - if (addreg0 && addreg1 && (rtx_equal_p(addreg0,addreg1))) - output_asm_insn("addl2 $4,%0", &addreg0); - else { - if (addreg0) - output_asm_insn("addl2 $4,%0", &addreg0); - if (addreg1) - output_asm_insn("addl2 $4,%0", &addreg1); - } - - output_asm_insn(singlemove_string(latehalf), latehalf); - - if (addreg0 && addreg1 && (rtx_equal_p(addreg0,addreg1))) - output_asm_insn("subl2 $4,%0", &addreg0); - else { - if (addreg0) - output_asm_insn("subl2 $4,%0", &addreg0); - if (addreg1) - output_asm_insn("subl2 $4,%0", &addreg1); - } - - if (shftreg0 && shftreg1 && (rtx_equal_p(shftreg0,shftreg1))) - output_asm_insn("shar $1,%0,%0", &shftreg0); - else { - if (shftreg0) - output_asm_insn("shar $1,%0,%0", &shftreg0); - if (shftreg1) - output_asm_insn("shar $1,%0,%0", &shftreg1); - } - - return ""; -} - - -/* This checks if a zero_extended cmp[bw] can be replaced by a sign_extended - cmp[bw]. This can be done if the operand is a constant that fits in a - byte/word or a memory operand. Besides that the next instruction must be an - unsigned compare. Some of these tests are done by the machine description */ - -int -tahoe_cmp_check (insn, op, max) -rtx insn, op; int max; -{ - if (GET_CODE (op) == CONST_INT - && ( INTVAL (op) < 0 || INTVAL (op) > max )) - return 0; - { - register rtx next = NEXT_INSN (insn); - - if ((GET_CODE (next) == JUMP_INSN - || GET_CODE (next) == INSN - || GET_CODE (next) == CALL_INSN)) - { - next = PATTERN (next); - if (GET_CODE (next) == SET - && SET_DEST (next) == pc_rtx - && GET_CODE (SET_SRC (next)) == IF_THEN_ELSE) - switch (GET_CODE (XEXP (SET_SRC (next), 0))) - { - case EQ: - case NE: - case LTU: - case GTU: - case LEU: - case GEU: - return 1; - } - } - } - return 0; -} |