diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1995-12-20 01:06:22 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1995-12-20 01:06:22 +0000 |
commit | c482518380683ee38d14024c1e362a0d681cf967 (patch) | |
tree | e69b4f6d3fee3aced20a41f3fdf543fc1c77fb5d /gnu/usr.bin/gcc/config/tahoe | |
parent | 76a62188d0db49c65b696d474c855a799fd96dce (diff) |
FSF GCC version 2.7.2
Diffstat (limited to 'gnu/usr.bin/gcc/config/tahoe')
-rw-r--r-- | gnu/usr.bin/gcc/config/tahoe/harris.h | 87 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/config/tahoe/tahoe.c | 565 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/config/tahoe/tahoe.h | 1016 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/config/tahoe/tahoe.md | 2113 | ||||
-rw-r--r-- | gnu/usr.bin/gcc/config/tahoe/xm-tahoe.h | 59 |
5 files changed, 3840 insertions, 0 deletions
diff --git a/gnu/usr.bin/gcc/config/tahoe/harris.h b/gnu/usr.bin/gcc/config/tahoe/harris.h new file mode 100644 index 00000000000..9226445ed98 --- /dev/null +++ b/gnu/usr.bin/gcc/config/tahoe/harris.h @@ -0,0 +1,87 @@ +/* Definitions of target machine for GNU compiler. Harris tahoe version. + Copyright (C) 1989, 1993 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 "tahoe/tahoe.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dtahoe -Dunix -Dhcx -Asystem(unix) -Acpu(tahoe) -Amachine(tahoe)" + +#undef DBX_DEBUGGING_INFO +#define SDB_DEBUGGING_INFO + +#undef LIB_SPEC + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT 1 + +/* urem and udiv don't exist on this system. */ +#undef UDIVSI3_LIBCALL +#undef UMODSI3_LIBCALL + +/* Operand of .align is not logarithmic. */ +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + LOG ? fprintf (FILE, "\t.align %d\n", 1 << (LOG)) : 0 + +/* For the same reason, we need .align 2 after casesi. */ +#undef PRINT_OPERAND +#define PRINT_OPERAND(FILE, X, CODE) \ +{ if (CODE == '@') \ + putc ('2', FILE); \ + else if (GET_CODE (X) == REG) \ + fprintf (FILE, "%s", reg_names[REGNO (X)]); \ + else if (GET_CODE (X) == MEM) \ + output_address (XEXP (X, 0)); \ + else { putc ('$', FILE); output_addr_const (FILE, X); }} + +#undef ASM_OUTPUT_LOCAL +#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ +( fputs (".bss ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%u,4\n", (ROUNDED))) + +/* Output at beginning of assembler file. */ +/* The .file command should always begin the output. */ + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + output_file_directive ((FILE), main_input_filename); + +#define ASM_OUTPUT_ASCII(FILE, PTR, SIZE) \ +do { \ + unsigned char *_p = (PTR); \ + int _thissize = (SIZE); \ + fprintf ((FILE), "\t.ascii \""); \ + for (i = 0; i < _thissize; i++) \ + { \ + register int c = _p[i]; \ + if (c >= ' ' && c < 0177 && c != '\"' && c != '\\') \ + putc (c, (FILE)); \ + else \ + { \ + fprintf ((FILE), "\\%o", c); \ + if (i < _thissize - 1 \ + && _p[i + 1] >= '0' && _p[i + 1] <= '9') \ + fprintf ((FILE), "\"\n\t.ascii \""); \ + } \ + } \ + fprintf ((FILE), "\"\n"); \ +} while (0) diff --git a/gnu/usr.bin/gcc/config/tahoe/tahoe.c b/gnu/usr.bin/gcc/config/tahoe/tahoe.c new file mode 100644 index 00000000000..6fec44418f4 --- /dev/null +++ b/gnu/usr.bin/gcc/config/tahoe/tahoe.c @@ -0,0 +1,565 @@ +/* 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; +} diff --git a/gnu/usr.bin/gcc/config/tahoe/tahoe.h b/gnu/usr.bin/gcc/config/tahoe/tahoe.h new file mode 100644 index 00000000000..7eced776b3b --- /dev/null +++ b/gnu/usr.bin/gcc/config/tahoe/tahoe.h @@ -0,0 +1,1016 @@ +/* Definitions of target machine for GNU compiler. Tahoe version. + Copyright (C) 1989, 1993, 1994, 1995 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. */ + +/* + * Original port made at the University of Buffalo by Devon Bowen, + * Dale Wiles and Kevin Zachmann. + * + * HCX/UX version by Piet van Oostrum (piet@cs.ruu.nl) + * + * Performance hacking by Michael Tiemann (tiemann@cygnus.com) + */ + +/* define this for the HCX/UX version */ + +/* #define HCX_UX */ + +/* + * Run-time Target Specification + */ + +#ifdef HCX_UX +/* no predefines, see Makefile and hcx-universe.c */ +/* have cc1 print that this is the hcx version */ +#define TARGET_VERSION printf (" (hcx)"); +#else +/* we want "tahoe" and "unix" defined for all future compilations */ +#define CPP_PREDEFINES "-Dtahoe -Dunix -Asystem(unix) -Acpu(tahoe) -Amachine(tahoe)" +/* have cc1 print that this is the tahoe version */ +#define TARGET_VERSION printf (" (tahoe)"); +#endif + +/* this is required in all tm files to hold flags */ + +extern int target_flags; + +/* Zero if it is safe to output .dfloat and .float pseudos. */ +#define TARGET_HEX_FLOAT (target_flags & 1) + +#define TARGET_DEFAULT 1 + +#define TARGET_SWITCHES \ + { {"hex-float", 1}, \ + {"no-hex-float", -1}, \ + { "", TARGET_DEFAULT} } + + +/* + * Storage Layout + */ + +/* This symbol was previously not mentioned, so apparently the tahoe + is little-endian for bits, or else doesn't care. */ +#define BITS_BIG_ENDIAN 0 + +/* tahoe uses a big endian byte order */ + +#define BYTES_BIG_ENDIAN 1 + +/* tahoe uses a big endian word order */ + +#define WORDS_BIG_ENDIAN 1 + +/* standard byte size is usable on tahoe */ + +#define BITS_PER_UNIT 8 + +/* longs on the tahoe are 4 byte groups */ + +#define BITS_PER_WORD 32 + +/* from the last two params we get 4 bytes per word */ + +#define UNITS_PER_WORD 4 + +/* addresses are 32 bits (one word) */ + +#define POINTER_SIZE 32 + +/* all parameters line up on 32 boundaries */ + +#define PARM_BOUNDARY 32 + +/* stack should line up on 32 boundaries */ + +#define STACK_BOUNDARY 32 + +/* line functions up on 32 bits */ + +#define FUNCTION_BOUNDARY 32 + +/* the biggest alignment the tahoe needs in 32 bits */ + +#define BIGGEST_ALIGNMENT 32 + +/* we have to align after an 'int : 0' in a structure */ + +#define EMPTY_FIELD_BOUNDARY 32 + +#ifdef HCX_UX +/* structures must be made of full words */ + +#define STRUCTURE_SIZE_BOUNDARY 32 +#else +/* structures must be made of full bytes */ + +#define STRUCTURE_SIZE_BOUNDARY 8 +#endif + +/* tahoe is picky about data alignment */ + +#define STRICT_ALIGNMENT 1 + +/* keep things standard with pcc */ + +#define PCC_BITFIELD_TYPE_MATTERS 1 + +/* this section is borrowed from the vax version since the */ +/* formats are the same in both of the architectures */ + +#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \ + if (OVERFLOW) \ + (D) = 1.7014117331926443e+38; \ + else if ((MODE) == SFmode) \ + { \ + if ((D) > 1.7014117331926443e+38) \ + (OVERFLOW) = 1, (D) = 1.7014117331926443e+38; \ + else if ((D) < -1.7014117331926443e+38) \ + (OVERFLOW) = 1, (D) = -1.7014117331926443e+38; \ + else if (((D) > 0) && ((D) < 2.9387358770557188e-39)) \ + (OVERFLOW) = 1, (D) = 0.0; \ + else if (((D) < 0) && ((D) > -2.9387358770557188e-39)) \ + (OVERFLOW) = 1, (D) = 0.0; \ + } + + +/* + * Register Usage + */ + +/* define 15 general regs plus one for the floating point reg (FPP) */ + +#define FIRST_PSEUDO_REGISTER 17 + +/* let the compiler know what the fp, sp and pc are */ + +#define FIXED_REGISTERS {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0} + +/* lots of regs aren't guaranteed to return from a call. The FPP reg */ +/* must be included in these since it can't be saved by the reg mask */ + +#define CALL_USED_REGISTERS {1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1} + +/* A single fp reg can handle any type of float. + CPU regs hold just 32 bits. */ + +#define HARD_REGNO_NREGS(REGNO, MODE) \ + (REGNO != 16 ? ((GET_MODE_SIZE(MODE)+UNITS_PER_WORD-1) / UNITS_PER_WORD) \ + : GET_MODE_NUNITS ((MODE))) + +/* any mode greater than 4 bytes (doubles) can only go in an even regs */ +/* and the FPP can only hold SFmode and DFmode */ + +#define HARD_REGNO_MODE_OK(REGNO, MODE) \ + (REGNO != 16 \ + ? (GET_MODE_UNIT_SIZE (MODE) <= 4 ? 1 : (REGNO % 2 - 1)) \ + : ((MODE) == SFmode || (MODE) == DFmode \ + || (MODE) == SCmode || (MODE) == DCmode)) + +/* if mode1 or mode2, but not both, are doubles then modes cannot be tied */ + +#define MODES_TIEABLE_P(MODE1, MODE2) \ + (((MODE1) == DFmode || (MODE1) == DCmode) \ + == ((MODE2) == DFmode || (MODE2) == DCmode)) + +/* return nonzero if register variable of mode MODE is not + a priori a bad idea. Used only if defined. */ +#define MODE_OK_FOR_USERVAR(MODE) \ + ((MODE) == SImode) + +/* the program counter is reg 15 */ + +#define PC_REGNUM 15 + +/* the stack pointer is reg 14 */ + +#define STACK_POINTER_REGNUM 14 + +/* the frame pointer is reg 13 */ + +#define FRAME_POINTER_REGNUM 13 + +/* tahoe does require an fp */ + +#define FRAME_POINTER_REQUIRED 1 + +/* since tahoe doesn't have a argument pointer, make it the fp */ + +#define ARG_POINTER_REGNUM 13 + +/* this isn't currently used since C doesn't support this feature */ + +#define STATIC_CHAIN_REGNUM 0 + +/* we'll use reg 1 for structure passing cause the destination */ +/* of the eventual movblk requires it to be there anyway. */ + +#define STRUCT_VALUE_REGNUM 1 + + +/* + * Register Classes + */ + +/* tahoe has two types of regs. GENERAL_REGS are all the regs up */ +/* to number 15. FPP_REG is the special floating point processor */ +/* register class (only one reg). */ + +enum reg_class {NO_REGS,GENERAL_REGS,FPP_REG,ALL_REGS,LIM_REG_CLASSES}; + +/* defines the number of reg classes. */ + +#define N_REG_CLASSES (int) LIM_REG_CLASSES + +/* this defines what the classes are officially named for debugging */ + +#define REG_CLASS_NAMES \ + {"NO_REGS","GENERAL_REGS","FPP_REG","ALL_REGS"} + +/* set general regs to be the first 16 regs and the fpp reg to be 17th */ + +#define REG_CLASS_CONTENTS {0,0xffff,0x10000,0x1ffff} + +/* register class for the fpp reg is FPP_REG, all others are GENERAL_REGS */ + +#define REGNO_REG_CLASS(REGNO) (REGNO == 16 ? FPP_REG : GENERAL_REGS) + +/* only general registers can be used as a base reg */ + +#define BASE_REG_CLASS GENERAL_REGS + +/* only general registers can be used to index */ + +#define INDEX_REG_CLASS GENERAL_REGS + +/* 'a' as a constraint in the md file means the FFP_REG class */ + +#define REG_CLASS_FROM_LETTER(C) (C == 'a' ? FPP_REG : NO_REGS) + +/* any general reg but the fpp can be a base reg */ + +#define REGNO_OK_FOR_BASE_P(regno) \ +((regno) < FIRST_PSEUDO_REGISTER - 1 || reg_renumber[regno] >= 0) + +/* any general reg except the pc and fpp can be an index reg */ + +#define REGNO_OK_FOR_INDEX_P(regno) \ +((regno) < FIRST_PSEUDO_REGISTER - 2 || reg_renumber[regno] >= 0) + +/* if your loading a floating point constant, it can't be done */ +/* through a register. Force it to be a memory constant. */ + +#define PREFERRED_RELOAD_CLASS(X,CLASS) \ + ((GET_CODE (X) == CONST_DOUBLE) ? NO_REGS : CLASS) + +/* for the fpp reg, all modes fit; for any others, you need two for doubles */ + +#define CLASS_MAX_NREGS(CLASS, MODE) \ + (CLASS != FPP_REG ? ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) : 1) + +/* we don't define any special constant sizes so all should fail */ + +#define CONST_OK_FOR_LETTER_P(VALUE, C) 0 + +/* we don't define any special double sizes so all should fail */ + +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0 + + +/* + * Describing Stack Layout + */ + +/* tahoe stack grows from high to low memory */ + +#define STACK_GROWS_DOWNWARD + +/* Define this if longjmp restores from saved registers + rather than from what setjmp saved. */ +#define LONGJMP_RESTORE_FROM_STACK + +/* tahoe call frames grow from high to low memory on the stack */ + +#define FRAME_GROWS_DOWNWARD + +/* the tahoe fp points to the *top* of the frame instead of the */ +/* bottom, so we have to make this offset a constant large enough */ +/* to jump over the biggest frame possible. */ + +#define STARTING_FRAME_OFFSET -52 + +/* tahoe always pushes 4 bytes unless it's a double in which case */ +/* it pushes a full 8 bytes. */ + +#define PUSH_ROUNDING(BYTES) (BYTES <= 4 ? 4 : 8) + +/* the first parameter in a function is at the fp + 4 */ + +#define FIRST_PARM_OFFSET(FNDECL) 4 + +/* the tahoe return function takes care of everything on the stack */ + +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) (SIZE) + +/* function values for all types are returned in register 0 */ + +#define FUNCTION_VALUE(VALTYPE, FUNC) \ + gen_rtx (REG, TYPE_MODE (VALTYPE), 0) + +/* library routines also return things in reg 0 */ + +#define LIBCALL_VALUE(MODE) gen_rtx (REG, MODE, 0) + +/* Tahoe doesn't return structures in a reentrant way */ + +#define PCC_STATIC_STRUCT_RETURN + +/* we only return values from a function in reg 0 */ + +#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0) + +/* we never pass args through a register */ + +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) 0 + +/* int is fine to hold the argument summary in FUNCTION_ARG */ + +#define CUMULATIVE_ARGS int + +/* we just set CUM to 0 before the FUNCTION_ARG call. No matter what */ +/* we make it, FUNCTION_ARG will return 0 anyway */ + +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \ + ((CUM) = 0) + +/* all modes push their size rounded to the nearest word boundary */ +/* except block which is the size of the block rounded up */ + +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \ + ((CUM) += ((MODE) != BLKmode \ + ? (GET_MODE_SIZE (MODE) + 3) & ~3 \ + : (int_size_in_bytes (TYPE) + 3) & ~3)) + +/* this is always false since we never pass params in regs */ + +#define FUNCTION_ARG_REGNO_P(N) 0 + +/* this code calculates the register entry mask and sets up */ +/* the stack pointer for the function. The stack is set down */ +/* far enough from the fp to jump over any push regs and local */ +/* vars. This is a problem since the tahoe has the fp pointing */ +/* to the top of the frame and the compiler must know the off- */ +/* set off the fp to the local vars. */ + +#define FUNCTION_PROLOGUE(FILE, SIZE) \ +{ register int regno; \ + register int mask = 0; \ + extern char call_used_regs[]; \ + for (regno = 0; regno < FIRST_PSEUDO_REGISTER-1; regno++) \ + if (regs_ever_live[regno] && !call_used_regs[regno]) \ + mask |= 1 << regno; \ + fprintf (FILE, "\t.word 0x%x\n", mask); \ + if (SIZE != 0) fprintf (FILE, "\tsubl3 $%d,fp,sp\n", (SIZE) - STARTING_FRAME_OFFSET); } + +/* Zero out global variable in case it was used in this function. */ +#define FUNCTION_EPILOGUE(FILE, SIZE) \ +{ extern rtx tahoe_reg_conversion_loc; \ + tahoe_reg_conversion_loc = 0; \ +} + +#ifdef HCX_UX + +/* to call the profiler, the address of the counter var is placed */ +/* on the stack and then passed into mcount this way */ + +#define FUNCTION_PROFILER(FILE, LABELNO) \ + fprintf (FILE, "\tpushal LP%d\n\tcallf $8,mcount\n", (LABELNO)); + +#else + +/* to call the profiler, push the variable value onto the stack */ +/* and call mcount like a regular function. */ + +#define FUNCTION_PROFILER(FILE, LABELNO) \ + fprintf (FILE, "\tpushl $LP%d\n\tcallf $8,mcount\n", (LABELNO)); + +#endif + +/* all stack handling at the end of a function is handled by the */ +/* return command. */ + +#define EXIT_IGNORE_STACK 1 + +/* + * Library Subroutine Names + */ + +/* udiv is a valid C library routine in libc.a, so we call that */ + +#define UDIVSI3_LIBCALL "*udiv" + +/* urem is a valid C library routine in libc.a, so we call that */ +/* but not so on hcx/ux */ + +#ifdef HCX_UX +#undef UMODSI3_LIBCALL +#else +#define UMODSI3_LIBCALL "*urem" +#endif + + +/* + * Addressing Modes + */ + +/* constant addresses can be treated exactly the same as normal constants */ + +#define CONSTANT_ADDRESS_P(X) \ + (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \ + || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \ + || GET_CODE (X) == HIGH) + +/* we can have as many as two regs in any given address */ + +#define MAX_REGS_PER_ADDRESS 2 + +/* The following is all the code for GO_IF_LEGITIMATE_ADDRESS */ +/* most of this taken directly from the vax tm file since the */ +/* tahoe and vax addressing modes are nearly identical. */ + +/* Is x an indirectable address? */ + +#define INDIRECTABLE_ADDRESS_P(X) \ + (CONSTANT_ADDRESS_P (X) \ + || (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ + || (GET_CODE (X) == PLUS \ + && GET_CODE (XEXP (X, 0)) == REG \ + && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ + && CONSTANT_ADDRESS_P (XEXP (X, 1)))) + +/* If x is a non-indexed-address, go to ADDR. */ + +#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \ +{ register rtx xfoob = (X); \ + if (GET_CODE (xfoob) == REG) goto ADDR; \ + if (INDIRECTABLE_ADDRESS_P (xfoob)) goto ADDR; \ + xfoob = XEXP (X, 0); \ + if (GET_CODE (X) == MEM && INDIRECTABLE_ADDRESS_P (xfoob)) \ + goto ADDR; \ + if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \ + && GET_CODE (xfoob) == REG && REGNO (xfoob) == 14) \ + goto ADDR; } + +/* Is PROD an index term in mode MODE. */ + +#define INDEX_TERM_P(PROD, MODE) \ +(GET_MODE_SIZE (MODE) == 1 \ + ? (GET_CODE (PROD) == REG && REG_OK_FOR_BASE_P (PROD)) \ + : (GET_CODE (PROD) == MULT \ + && \ + (xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \ + ((GET_CODE (xfoo0) == CONST_INT \ + && INTVAL (xfoo0) == GET_MODE_SIZE (MODE) \ + && GET_CODE (xfoo1) == REG \ + && REG_OK_FOR_INDEX_P (xfoo1)) \ + || \ + (GET_CODE (xfoo1) == CONST_INT \ + && INTVAL (xfoo1) == GET_MODE_SIZE (MODE) \ + && GET_CODE (xfoo0) == REG \ + && REG_OK_FOR_INDEX_P (xfoo0)))))) + +/* Is the addition to the index a reg? */ + +#define GO_IF_REG_PLUS_INDEX(X, MODE, ADDR) \ +{ register rtx xfooa; \ + if (GET_CODE (X) == PLUS) \ + { if (GET_CODE (XEXP (X, 0)) == REG \ + && REG_OK_FOR_BASE_P (XEXP (X, 0)) \ + && (xfooa = XEXP (X, 1), \ + INDEX_TERM_P (xfooa, MODE))) \ + goto ADDR; \ + if (GET_CODE (XEXP (X, 1)) == REG \ + && REG_OK_FOR_BASE_P (XEXP (X, 1)) \ + && (xfooa = XEXP (X, 0), \ + INDEX_TERM_P (xfooa, MODE))) \ + goto ADDR; } } + +/* Is the rtx X a valid memory address for operand of mode MODE? */ +/* If it is, go to ADDR */ + +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ +{ register rtx xfoo, xfoo0, xfoo1; \ + GO_IF_NONINDEXED_ADDRESS (X, ADDR); \ + if (GET_CODE (X) == PLUS) \ + { xfoo = XEXP (X, 0); \ + if (INDEX_TERM_P (xfoo, MODE)) \ + { GO_IF_NONINDEXED_ADDRESS (XEXP (X, 1), ADDR); } \ + xfoo = XEXP (X, 1); \ + if (INDEX_TERM_P (xfoo, MODE)) \ + { GO_IF_NONINDEXED_ADDRESS (XEXP (X, 0), ADDR); } \ + if (CONSTANT_ADDRESS_P (XEXP (X, 0))) \ + { if (GET_CODE (XEXP (X, 1)) == REG \ + && REG_OK_FOR_BASE_P (XEXP (X, 1))) \ + goto ADDR; \ + GO_IF_REG_PLUS_INDEX (XEXP (X, 1), MODE, ADDR); } \ + if (CONSTANT_ADDRESS_P (XEXP (X, 1))) \ + { if (GET_CODE (XEXP (X, 0)) == REG \ + && REG_OK_FOR_BASE_P (XEXP (X, 0))) \ + goto ADDR; \ + GO_IF_REG_PLUS_INDEX (XEXP (X, 0), MODE, ADDR); } } } + +/* Register 16 can never be used for index or base */ + +#ifndef REG_OK_STRICT +#define REG_OK_FOR_INDEX_P(X) (REGNO(X) != 16) +#define REG_OK_FOR_BASE_P(X) (REGNO(X) != 16) +#else +#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X)) +#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X)) +#endif + +/* Addressing is too simple to allow optimizing here */ + +#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {} + +/* Post_inc and pre_dec always adds 4 */ + +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \ + { if (GET_CODE(ADDR) == POST_INC || GET_CODE(ADDR) == PRE_DEC) \ + goto LABEL; \ + if (GET_CODE (ADDR) == PLUS) \ + { if (CONSTANT_ADDRESS_P (XEXP (ADDR, 0)) \ + && GET_CODE (XEXP (ADDR, 1)) == REG); \ + else if (CONSTANT_ADDRESS_P (XEXP (ADDR, 1)) \ + && GET_CODE (XEXP (ADDR, 0)) == REG); \ + else goto LABEL; }} + +/* Double's are not legitimate as immediate operands */ + +#define LEGITIMATE_CONSTANT_P(X) \ + (GET_CODE (X) != CONST_DOUBLE) + + +/* + * Miscellaneous Parameters + */ + +/* the elements in the case jump table are all words */ + +#define CASE_VECTOR_MODE HImode + +/* each of the table elements in a case are relative to the jump address */ + +#define CASE_VECTOR_PC_RELATIVE + +/* tahoe case instructions just fall through to the next instruction */ +/* if not satisfied. It doesn't support a default action */ + +#define CASE_DROPS_THROUGH + +/* the standard answer is given here and work ok */ + +#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR + +/* in a general div case, it's easiest to use TRUNC_DIV_EXPR */ + +#define EASY_DIV_EXPR TRUNC_DIV_EXPR + +/* the standard seems to be leaving char's as signed so we left it */ +/* this way even though we think they should be unsigned! */ + +#define DEFAULT_SIGNED_CHAR 1 + +/* the most we can move without cutting down speed is 4 bytes */ + +#define MOVE_MAX 4 + +/* our int is 32 bits */ + +#define INT_TYPE_SIZE 32 + +/* byte access isn't really slower than anything else */ + +#define SLOW_BYTE_ACCESS 0 + +/* zero extension is more than one instruction so try to avoid it */ + +#define SLOW_ZERO_EXTEND + +/* any bits higher than the low 4 are ignored in the shift count */ +/* so don't bother zero extending or sign extending them */ + +#define SHIFT_COUNT_TRUNCATED 1 + +/* we don't need to officially convert from one fixed type to another */ +/* in order to use it as that type. We can just assume it's the same */ + +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1 + +/* pass chars as ints */ + +#define PROMOTE_PROTOTYPES + +/* pointers can be represented by an si mode expression */ + +#define Pmode SImode + +/* function addresses are made by specifying a byte address */ + +#define FUNCTION_MODE QImode + +/* Define this if addresses of constant functions + shouldn't be put through pseudo regs where they can be cse'd. + On the tahoe a call with a constant address is much faster than one with a + register. */ + +#define NO_FUNCTION_CSE + +/* specify the costs of various sorts of constants, + and also indicate that multiplication is cheap on this machine. */ + +#define CONST_COSTS(RTX,CODE,OUTER_CODE) \ + case CONST_INT: \ + /* Constant zero is super cheap due to clr instruction. */ \ + if (RTX == const0_rtx) return 0; \ + if ((unsigned) INTVAL (RTX) < 077) return 1; \ + if (INTVAL (RTX) <= 127 && INTVAL (RTX) >= -128) return 2; \ + case CONST: \ + case LABEL_REF: \ + case SYMBOL_REF: \ + return 3; \ + case CONST_DOUBLE: \ + return 5; \ + case MULT: \ + total = 2; + + +/* + * Condition Code Information + */ + +/* Nonzero if the results of the previous comparison are + in the floating point condition code register. */ + +#define CC_UNCHANGED 04000 + + +#define NOTICE_UPDATE_CC(EXP, INSN) \ +{ if (cc_status.flags & CC_UNCHANGED) \ + /* Happens for cvtld and a few other insns. */ \ + cc_status.flags &= ~CC_UNCHANGED; \ + else if (GET_CODE (EXP) == SET) \ + { if (GET_CODE (SET_SRC (EXP)) == CALL) \ + CC_STATUS_INIT; \ + else if (GET_CODE (SET_DEST (EXP)) != PC) \ + { cc_status.flags = 0; \ + cc_status.value1 = SET_DEST (EXP); \ + cc_status.value2 = SET_SRC (EXP); } } \ + else if (GET_CODE (EXP) == PARALLEL \ + && GET_CODE (XVECEXP (EXP, 0, 0)) == SET \ + && GET_CODE (SET_DEST (XVECEXP (EXP, 0, 0))) != PC) \ + { cc_status.flags = 0; \ + cc_status.value1 = SET_DEST (XVECEXP (EXP, 0, 0)); \ + cc_status.value2 = SET_SRC (XVECEXP (EXP, 0, 0)); } \ + /* PARALLELs whose first element sets the PC are aob, sob insns. \ + They do change the cc's. So drop through and forget the cc's. */ \ + else CC_STATUS_INIT; \ + if (cc_status.value1 && GET_CODE (cc_status.value1) == REG \ + && cc_status.value2 \ + && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) \ + cc_status.value2 = 0; \ + if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM \ + && cc_status.value2 \ + && GET_CODE (cc_status.value2) == MEM) \ + cc_status.value2 = 0; } +/* Actual condition, one line up, should be that value2's address + depends on value1, but that is too much of a pain. */ + + +/* + * Output of Assembler Code + */ + +/* print which tahoe version compiled this code and print a directive */ +/* to the gnu assembler to say that the following is normal assembly */ + +#ifdef HCX_UX +#define ASM_FILE_START(FILE) \ +{ fprintf (FILE, "#gcc hcx 1.0\n\n"); \ + output_file_directive ((FILE), main_input_filename);} while (0) +#else +#define ASM_FILE_START(FILE) fprintf (FILE, "#gcc tahoe 1.0\n#NO_APP\n"); +#endif + +/* the instruction that turns on the APP for the gnu assembler */ + +#define ASM_APP_ON "#APP\n" + +/* the instruction that turns off the APP for the gnu assembler */ + +#define ASM_APP_OFF "#NO_APP\n" + +/* what to output before read-only data. */ + +#define TEXT_SECTION_ASM_OP ".text" + +/* what to output before writable data. */ + +#define DATA_SECTION_ASM_OP ".data" + +/* this is what we call each of the regs. notice that the FPP reg is */ +/* called "ac". This should never get used due to the way we've set */ +/* up FPP instructions in the md file. But we call it "ac" here to */ +/* fill the list. */ + +#define REGISTER_NAMES \ +{"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "fp", "sp", "pc", "ac"} + +#ifdef HCX_UX +/* allow generation of sdb info in the assembly */ +#define SDB_DEBUGGING_INFO +#else +/* allow generation of dbx info in the assembly */ + +#define DBX_DEBUGGING_INFO + +/* our dbx doesn't support this */ + +#define DBX_NO_XREFS + +/* we don't want symbols broken up */ + +#define DBX_CONTIN_LENGTH 0 + +/* this'll really never be used, but we'll leave it at this */ + +#define DBX_CONTIN_CHAR '?' + +#endif /* HCX_UX */ + +/* registers are called the same thing in dbx anything else */ +/* This is necessary even if we generate SDB output */ + +#define DBX_REGISTER_NUMBER(REGNO) (REGNO) + +/* labels are the label followed by a colon and a newline */ +/* must be a statement, so surround it in a null loop */ + +#define ASM_OUTPUT_LABEL(FILE,NAME) \ + do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0) + +/* use the .globl directive to make labels global for the linker */ + +#define ASM_GLOBALIZE_LABEL(FILE,NAME) \ + do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0) + +/* output a label by appending an underscore to it */ + +#define ASM_OUTPUT_LABELREF(FILE,NAME) \ + fprintf (FILE, "_%s", NAME) + +/* use the standard format for printing internal labels */ + +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, "%s%d:\n", PREFIX, NUM) + +/* a * is used for label indirection in unix assembly */ + +#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ + sprintf (LABEL, "*%s%d", PREFIX, NUM) + +/* outputting a double is easy cause we only have one kind */ + +#ifdef HCX_UX +#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ + fprintf (FILE, "\t.double 0d%.20e\n", (VALUE)) +#else +#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ +{ \ + union { int i[2]; double d;} temp; \ + temp.d = (VALUE); \ + if (TARGET_HEX_FLOAT) \ + fprintf ((FILE), "\t.long 0x%x,0x%x # %.20e\n", \ + temp.i[0], temp.i[1], temp.d); \ + else \ + fprintf (FILE, "\t.dfloat 0d%.20e\n", temp.d); \ +} +#endif + +/* This is how to output an assembler line defining a `float' constant. */ + +#ifdef HCX_UX +#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ + fprintf (FILE, "\t.float 0f%.20e\n", (VALUE)) +#else +#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ +{ \ + union { int i; float f;} temp; \ + temp.f = (float) (VALUE); \ + if (TARGET_HEX_FLOAT) \ + fprintf ((FILE), "\t.long 0x%x # %.20e\n", \ + temp.i, temp.f); \ + else \ + fprintf (FILE, "\t.float 0f%.20e\n", temp.f); \ +} +#endif + +/* This is how to output an assembler line defining an `int' constant. */ + +#define ASM_OUTPUT_INT(FILE,VALUE) \ +( fprintf (FILE, "\t.long "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +/* Likewise for `char' and `short' constants. */ + +#define ASM_OUTPUT_SHORT(FILE,VALUE) \ +( fprintf (FILE, "\t.word "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +#define ASM_OUTPUT_CHAR(FILE,VALUE) \ +( fprintf (FILE, "\t.byte "), \ + output_addr_const (FILE, (VALUE)), \ + fprintf (FILE, "\n")) + +#ifdef HCX_UX +/* This is how to output an assembler line for an ASCII string. */ + +#define ASM_OUTPUT_ASCII(FILE, p, size) \ +do { register int i; \ + fprintf ((FILE), "\t.ascii \""); \ + for (i = 0; i < (size); i++) \ + { \ + register int c = (p)[i]; \ + if (c == '\'' || c == '\\') \ + putc ('\\', (FILE)); \ + if (c >= ' ' && c < 0177 && c != '\"') \ + putc (c, (FILE)); \ + else \ + { \ + fprintf ((FILE), "\\%03o", c); \ + } \ + } \ + fprintf ((FILE), "\"\n"); } while (0) +#endif + +/* This is how to output an assembler line for a numeric constant byte. */ + +#define ASM_OUTPUT_BYTE(FILE,VALUE) \ + fprintf (FILE, "\t.byte 0x%x\n", (VALUE)) + +/* this is the insn to push a register onto the stack */ + +#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ + fprintf (FILE, "\tpushl %s\n", reg_names[REGNO]) + +/* this is the insn to pop a register from the stack */ + +#define ASM_OUTPUT_REG_POP(FILE,REGNO) \ + fprintf (FILE, "\tmovl (sp)+,%s\n", reg_names[REGNO]) + +/* this is required even thought tahoe doesn't support it */ +/* cause the C code expects it to be defined */ + +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \ + fprintf (FILE, "\t.long L%d\n", VALUE) + +/* This is how to output an element of a case-vector that is relative. */ + +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ + fprintf (FILE, "\t.word L%d-L%d\n", VALUE, REL) + +/* This is how to output an assembler line + that says to advance the location counter + to a multiple of 2**LOG bytes. */ + +#ifdef HCX_UX +#define CASE_ALIGNMENT 2 +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG)) +#else +#define CASE_ALIGNMENT 1 +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + LOG ? fprintf (FILE, "\t.align %d\n", (LOG)) : 0 +#endif + +/* This is how to skip over some space */ + +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ + fprintf (FILE, "\t.space %u\n", (SIZE)) + +/* This defines common variables across files */ + +#ifdef HCX_UX +#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ +( fputs (".comm ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%u\n", (SIZE))) +#else +#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \ +( fputs (".comm ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%u\n", (ROUNDED))) +#endif + +/* This says how to output an assembler line + to define a local common symbol. */ + +#ifdef HCX_UX +#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ +( fputs ("\t.bss ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%u,4\n", (SIZE),(ROUNDED))) +#else +#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \ +( fputs (".lcomm ", (FILE)), \ + assemble_name ((FILE), (NAME)), \ + fprintf ((FILE), ",%u\n", (ROUNDED))) +#endif + +/* code to generate a label */ + +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ +( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \ + sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO))) + +/* Define the parentheses used to group arithmetic operations + in assembler code. */ + +#define ASM_OPEN_PAREN "(" +#define ASM_CLOSE_PAREN ")" + +/* Define results of standard character escape sequences. */ + +#define TARGET_BELL 007 +#define TARGET_BS 010 +#define TARGET_TAB 011 +#define TARGET_NEWLINE 012 +#define TARGET_VT 013 +#define TARGET_FF 014 +#define TARGET_CR 015 + +/* Print an instruction operand X on file FILE. + CODE is the code from the %-spec that requested printing this operand; + if `%z3' was used to print operand 3, then CODE is 'z'. + On the Vax, the only code used is `#', indicating that either + `d' or `g' should be printed, depending on whether we're using dfloat + or gfloat. */ +/* Print an operand. Some difference from the vax code, + since the tahoe can't support immediate floats and doubles. + + %@ means print the proper alignment operand for aligning after a casesi. + This depends on the assembler syntax. + This is 1 for our assembler, since .align is logarithmic. + + %s means the number given is supposed to be a shift value, but on + the tahoe it should be converted to a number that can be used as a + multiplicative constant (cause multiplication is a whole lot faster + than shifting). So make the number 2^n instead. */ + +#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ + ((CODE) == '@') + +#define PRINT_OPERAND(FILE, X, CODE) \ +{ if (CODE == '@') \ + putc ('0' + CASE_ALIGNMENT, FILE); \ + else if (CODE == 's') \ + fprintf (FILE, "$%d", 1 << INTVAL(X)); \ + else if (GET_CODE (X) == REG) \ + fprintf (FILE, "%s", reg_names[REGNO (X)]); \ + else if (GET_CODE (X) == MEM) \ + output_address (XEXP (X, 0)); \ + else { putc ('$', FILE); output_addr_const (FILE, X); }} + +/* When the operand is an address, call print_operand_address to */ +/* do the work from output-tahoe.c. */ + +#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \ + print_operand_address (FILE, ADDR) + +/* This is for G++ */ + +#define CRT0_DUMMIES +#define DOT_GLOBAL_START +#ifdef HCX_UX +#define NO_GNU_LD /* because of COFF format */ +#define LINK_SPEC "-L/usr/staff/lib" +#endif diff --git a/gnu/usr.bin/gcc/config/tahoe/tahoe.md b/gnu/usr.bin/gcc/config/tahoe/tahoe.md new file mode 100644 index 00000000000..eaa92d05d5e --- /dev/null +++ b/gnu/usr.bin/gcc/config/tahoe/tahoe.md @@ -0,0 +1,2113 @@ +;; Machine description for GNU compiler, Tahoe version +;; Copyright (C) 1989, 1994 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. + + +; File: tahoe.md +; +; Original port made at the University of Buffalo by Devon Bowen, +; Dale Wiles and Kevin Zachmann. +; +; Piet van Oostrum (piet@cs.ruu.nl) made changes for HCX/UX, fixed +; some bugs and made some improvements (hopefully). +; +; Mail bugs reports or fixes to: gcc@cs.buffalo.edu + + +; movdi must call the output_move_double routine to move it around since +; the tahoe doesn't efficiently support 8 bit moves. + +(define_insn "movdi" + [(set (match_operand:DI 0 "general_operand" "=g") + (match_operand:DI 1 "general_operand" "g"))] + "" + "* +{ + CC_STATUS_INIT; + return output_move_double (operands); +}") + + +; the trick in the movsi is accessing the contents of the sp register. The +; tahoe doesn't allow you to access it directly so you have to access the +; address of the top of the stack instead. + +(define_insn "movsi" + [(set (match_operand:SI 0 "general_operand" "=g") + (match_operand:SI 1 "general_operand" "g"))] + "" + "* +{ + rtx link; + if (operands[1] == const1_rtx + && (link = find_reg_note (insn, REG_WAS_0, 0)) + && ! INSN_DELETED_P (XEXP (link, 0)) + && GET_CODE (XEXP (link, 0)) != NOTE + && no_labels_between_p (XEXP (link, 0), insn) + /* Make sure the reg hasn't been clobbered. */ + && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) + return \"incl %0\"; + if (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST) + { + if (push_operand (operands[0], SImode)) + return \"pushab %a1\"; + return \"movab %a1,%0\"; + } + if (operands[1] == const0_rtx) + return \"clrl %0\"; + if (push_operand (operands[0], SImode)) + return \"pushl %1\"; + if (GET_CODE(operands[1]) == REG && REGNO(operands[1]) == 14) + return \"moval (sp),%0\"; + return \"movl %1,%0\"; +}") + + +(define_insn "movhi" + [(set (match_operand:HI 0 "general_operand" "=g") + (match_operand:HI 1 "general_operand" "g"))] + "" + "* +{ + rtx link; + if (operands[1] == const1_rtx + && (link = find_reg_note (insn, REG_WAS_0, 0)) + && ! INSN_DELETED_P (XEXP (link, 0)) + && GET_CODE (XEXP (link, 0)) != NOTE + && no_labels_between_p (XEXP (link, 0), insn) + /* Make sure the reg hasn't been clobbered. */ + && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) + return \"incw %0\"; + if (operands[1] == const0_rtx) + return \"clrw %0\"; + return \"movw %1,%0\"; +}") + + +(define_insn "movqi" + [(set (match_operand:QI 0 "general_operand" "=g") + (match_operand:QI 1 "general_operand" "g"))] + "" + "* +{ + if (operands[1] == const0_rtx) + return \"clrb %0\"; + return \"movb %1,%0\"; +}") + + +; movsf has three cases since they can move from one place to another +; or to/from the fpp and since different instructions are needed for +; each case. The fpp related instructions don't set the flags properly. + +(define_insn "movsf" + [(set (match_operand:SF 0 "general_operand" "=g,=a,=g") + (match_operand:SF 1 "general_operand" "g,g,a"))] + "" + "* +{ + CC_STATUS_INIT; + switch (which_alternative) + { + case 0: return \"movl %1,%0\"; + case 1: return \"ldf %1\"; + case 2: return \"stf %0\"; + } +}") + + +; movdf has a number of different cases. If it's going to or from +; the fpp, use the special instructions to do it. If not, use the +; output_move_double function. + +(define_insn "movdf" + [(set (match_operand:DF 0 "general_operand" "=a,=g,?=g") + (match_operand:DF 1 "general_operand" "g,a,g"))] + "" + "* +{ + CC_STATUS_INIT; + switch (which_alternative) + { + case 0: + return \"ldd %1\"; + case 1: + if (push_operand (operands[0], DFmode)) + return \"pushd\"; + else + return \"std %0\"; + case 2: + return output_move_double (operands); + } +}") + + +;======================================================================== +; The tahoe has the following semantics for byte (and similar for word) +; operands: if the operand is a register or immediate, it takes the full 32 +; bit operand, if the operand is memory, it sign-extends the byte. The +; operation is performed on the 32 bit values. If the destination is a +; register, the full 32 bit result is stored, if the destination is memory, +; of course only the low part is stored. The condition code is based on the +; 32 bit operation. Only on the movz instructions the byte from memory is +; zero-extended rather than sign-extended. + +; This means that for arithmetic instructions we can use addb etc. to +; perform a long add from a signed byte from memory to a register. Of +; course this would also work for logical operations, but that doesn't seem +; very useful. + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")) + (sign_extend:SI (match_operand:QI 2 "memory_operand" "m"))))] + "" + "addb3 %1,%2,%0") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_operand:SI 1 "nonmemory_operand" "%ri") + (sign_extend:SI (match_operand:QI 2 "memory_operand" "m"))))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"addb2 %2,%0\"; + return \"addb3 %1,%2,%0\"; +}") + +; We can also consider the result to be a half integer + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (plus:HI (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")) + (sign_extend:HI (match_operand:QI 2 "memory_operand" "m"))))] + "" + "addb3 %1,%2,%0") + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (plus:HI (match_operand:HI 1 "nonmemory_operand" "%ri") + (sign_extend:HI (match_operand:QI 2 "memory_operand" "m"))))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"addb2 %2,%0\"; + return \"addb3 %1,%2,%0\"; +}") + +; The same applies to words (HI) + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")) + (sign_extend:SI (match_operand:HI 2 "memory_operand" "m"))))] + "" + "addw3 %1,%2,%0") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_operand:SI 1 "nonmemory_operand" "%ri") + (sign_extend:SI (match_operand:HI 2 "memory_operand" "m"))))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"addw2 %2,%0\"; + return \"addw3 %1,%2,%0\"; +}") + +; ======================= Now for subtract ============================== + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")) + (sign_extend:SI (match_operand:QI 2 "memory_operand" "m"))))] + "" + "subb3 %2,%1,%0") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_operand:SI 1 "nonmemory_operand" "ri") + (sign_extend:SI (match_operand:QI 2 "memory_operand" "m"))))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"subb2 %2,%0\"; + return \"subb3 %2,%1,%0\"; +}") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")) + (match_operand:SI 2 "nonmemory_operand" "ri")))] + "" + "subb3 %2,%1,%0") + +; We can also consider the result to be a half integer + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (minus:HI (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")) + (sign_extend:HI (match_operand:QI 2 "memory_operand" "m"))))] + "" + "subb3 %2,%1,%0") + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (minus:HI (match_operand:HI 1 "nonmemory_operand" "%ri") + (sign_extend:HI (match_operand:QI 2 "memory_operand" "m"))))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"subb2 %2,%0\"; + return \"subb3 %2,%1,%0\"; +}") + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (minus:HI (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")) + (match_operand:HI 2 "nonmemory_operand" "ri")))] + "" + "subb3 %2,%1,%0") + +; The same applies to words (HI) + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")) + (sign_extend:SI (match_operand:HI 2 "memory_operand" "m"))))] + "" + "subw3 %2,%1,%0") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_operand:SI 1 "nonmemory_operand" "ri") + (sign_extend:SI (match_operand:HI 2 "memory_operand" "m"))))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"subw2 %2,%0\"; + return \"subw3 %2,%1,%0\"; +}") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")) + (match_operand:SI 2 "nonmemory_operand" "ri")))] + "" + "subw3 %2,%1,%0") + +; ======================= Now for neg ============================== + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (sign_extend:SI (match_operand:QI 1 "memory_operand" "m"))))] + "" + "mnegb %1,%0") + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r") + (neg:HI (sign_extend:HI (match_operand:QI 1 "memory_operand" "m"))))] + "" + "mnegb %1,%0") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))))] + "" + "mnegw %1,%0") + +;======================================================================== + + +(define_insn "addsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (plus:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + { + if (operands[2] == const1_rtx) + return \"incl %0\"; + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == -1) + return \"decl %0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) (- INTVAL (operands[2])) < 64) + return \"subl2 $%n2,%0\"; + return \"addl2 %2,%0\"; + } + if (rtx_equal_p (operands[0], operands[2])) + return \"addl2 %1,%0\"; + if (GET_CODE (operands[2]) == CONST_INT + && GET_CODE (operands[1]) == REG) + { + if (push_operand (operands[0], SImode)) + return \"pushab %c2(%1)\"; + return \"movab %c2(%1),%0\"; + } + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) (- INTVAL (operands[2])) < 64) + return \"subl3 $%n2,%1,%0\"; + return \"addl3 %1,%2,%0\"; +}") + + +(define_insn "addhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (plus:HI (match_operand:HI 1 "general_operand" "g") + (match_operand:HI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + { + if (operands[2] == const1_rtx) + return \"incw %0\"; + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == -1) + return \"decw %0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) (- INTVAL (operands[2])) < 64) + return \"subw2 $%n2,%0\"; + return \"addw2 %2,%0\"; + } + if (rtx_equal_p (operands[0], operands[2])) + return \"addw2 %1,%0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) (- INTVAL (operands[2])) < 64) + return \"subw3 $%n2,%1,%0\"; + return \"addw3 %1,%2,%0\"; +}") + + +(define_insn "addqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (plus:QI (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + { + if (operands[2] == const1_rtx) + return \"incb %0\"; + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == -1) + return \"decb %0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) (- INTVAL (operands[2])) < 64) + return \"subb2 $%n2,%0\"; + return \"addb2 %2,%0\"; + } + if (rtx_equal_p (operands[0], operands[2])) + return \"addb2 %1,%0\"; + if (GET_CODE (operands[2]) == CONST_INT + && (unsigned) (- INTVAL (operands[2])) < 64) + return \"subb3 $%n2,%1,%0\"; + return \"addb3 %1,%2,%0\"; +}") + +; addsf3 can only add into the fpp register since the fpp is treated +; as a separate unit in the machine. It also doesn't set the flags at +; all. + +(define_insn "addsf3" + [(set (match_operand:SF 0 "register_operand" "=a") + (plus:SF (match_operand:SF 1 "register_operand" "%0") + (match_operand:SF 2 "general_operand" "g")))] + "" + "* +{ + CC_STATUS_INIT; + return \"addf %2\"; +}") + + +; adddf3 can only add into the fpp reg since the fpp is treated as a +; separate entity. Doubles can only be read from a register or memory +; since a double is not an immediate mode. Flags are not set by this +; instruction. + +(define_insn "adddf3" + [(set (match_operand:DF 0 "register_operand" "=a") + (plus:DF (match_operand:DF 1 "register_operand" "%0") + (match_operand:DF 2 "general_operand" "rm")))] + "" + "* +{ + CC_STATUS_INIT; + return \"addd %2\"; +}") + + +; Subtraction from the sp (needed by the built in alloc function) needs +; to be different since the sp cannot be directly read on the tahoe. +; If it's a simple constant, you just use displacement. Otherwise, you +; push the sp, and then do the subtraction off the stack. + +(define_insn "subsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (minus:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + { + if (operands[2] == const1_rtx) + return \"decl %0\"; + if (GET_CODE(operands[0]) == REG && REGNO(operands[0]) == 14) + { + if (GET_CODE(operands[2]) == CONST_INT) + return \"movab %n2(sp),sp\"; + else + return \"pushab (sp)\;subl3 %2,(sp),sp\"; + } + return \"subl2 %2,%0\"; + } + if (rtx_equal_p (operands[1], operands[2])) + return \"clrl %0\"; + return \"subl3 %2,%1,%0\"; +}") + + +(define_insn "subhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (minus:HI (match_operand:HI 1 "general_operand" "g") + (match_operand:HI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + { + if (operands[2] == const1_rtx) + return \"decw %0\"; + return \"subw2 %2,%0\"; + } + if (rtx_equal_p (operands[1], operands[2])) + return \"clrw %0\"; + return \"subw3 %2,%1,%0\"; +}") + + +(define_insn "subqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (minus:QI (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + { + if (operands[2] == const1_rtx) + return \"decb %0\"; + return \"subb2 %2,%0\"; + } + if (rtx_equal_p (operands[1], operands[2])) + return \"clrb %0\"; + return \"subb3 %2,%1,%0\"; +}") + + +; subsf3 can only subtract into the fpp accumulator due to the way +; the fpp reg is limited by the instruction set. This also doesn't +; bother setting up flags. + +(define_insn "subsf3" + [(set (match_operand:SF 0 "register_operand" "=a") + (minus:SF (match_operand:SF 1 "register_operand" "0") + (match_operand:SF 2 "general_operand" "g")))] + "" + "* +{ + CC_STATUS_INIT; + return \"subf %2\"; +}") + + +; subdf3 is set up to subtract into the fpp reg due to limitations +; of the fpp instruction set. Doubles can not be immediate. This +; instruction does not set the flags. + +(define_insn "subdf3" + [(set (match_operand:DF 0 "register_operand" "=a") + (minus:DF (match_operand:DF 1 "register_operand" "0") + (match_operand:DF 2 "general_operand" "rm")))] + "" + "* +{ + CC_STATUS_INIT; + return \"subd %2\"; +}") + + +(define_insn "mulsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (mult:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"mull2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"mull2 %1,%0\"; + return \"mull3 %1,%2,%0\"; +}") + + +; mulsf3 can only multiply into the fpp accumulator due to limitations +; of the fpp. It also does not set the condition codes properly. + +(define_insn "mulsf3" + [(set (match_operand:SF 0 "register_operand" "=a") + (mult:SF (match_operand:SF 1 "register_operand" "%0") + (match_operand:SF 2 "general_operand" "g")))] + "" + "* +{ + CC_STATUS_INIT; + return \"mulf %2\"; +}") + + +; muldf3 can only multiply into the fpp reg since the fpp is limited +; from the rest. Doubles may not be immediate mode. This does not set +; the flags like gcc would expect. + +(define_insn "muldf3" + [(set (match_operand:DF 0 "register_operand" "=a") + (mult:DF (match_operand:DF 1 "register_operand" "%0") + (match_operand:DF 2 "general_operand" "rm")))] + "" + "* +{ + CC_STATUS_INIT; + return \"muld %2\"; +}") + + + +(define_insn "divsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (div:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[1], operands[2])) + return \"movl $1,%0\"; + if (operands[1] == const0_rtx) + return \"clrl %0\"; + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == -1) + return \"mnegl %1,%0\"; + if (rtx_equal_p (operands[0], operands[1])) + return \"divl2 %2,%0\"; + return \"divl3 %2,%1,%0\"; +}") + + +; divsf3 must divide into the fpp accumulator. Flags are not set by +; this instruction, so they are cleared. + +(define_insn "divsf3" + [(set (match_operand:SF 0 "register_operand" "=a") + (div:SF (match_operand:SF 1 "register_operand" "0") + (match_operand:SF 2 "general_operand" "g")))] + "" + "* +{ + CC_STATUS_INIT; + return \"divf %2\"; +}") + + +; divdf3 also must divide into the fpp reg so optimization isn't +; possible. Note that doubles cannot be immediate. The flags here +; are not set correctly so they must be ignored. + +(define_insn "divdf3" + [(set (match_operand:DF 0 "register_operand" "=a") + (div:DF (match_operand:DF 1 "register_operand" "0") + (match_operand:DF 2 "general_operand" "rm")))] + "" + "* +{ + CC_STATUS_INIT; + return \"divd %2\"; +}") + + + +(define_insn "andsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (and:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"andl2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"andl2 %1,%0\"; + return \"andl3 %2,%1,%0\"; +}") + + + +(define_insn "andhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (and:HI (match_operand:HI 1 "general_operand" "g") + (match_operand:HI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"andw2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"andw2 %1,%0\"; + return \"andw3 %2,%1,%0\"; +}") + + +(define_insn "andqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (and:QI (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"andb2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"andb2 %1,%0\"; + return \"andb3 %2,%1,%0\"; +}") + + +(define_insn "iorsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (ior:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"orl2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"orl2 %1,%0\"; + return \"orl3 %2,%1,%0\"; +}") + + + +(define_insn "iorhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (ior:HI (match_operand:HI 1 "general_operand" "g") + (match_operand:HI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"orw2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"orw2 %1,%0\"; + return \"orw3 %2,%1,%0\"; +}") + + + +(define_insn "iorqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (ior:QI (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"orb2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"orb2 %1,%0\"; + return \"orb3 %2,%1,%0\"; +}") + + +(define_insn "xorsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (xor:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:SI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"xorl2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"xorl2 %1,%0\"; + return \"xorl3 %2,%1,%0\"; +}") + + +(define_insn "xorhi3" + [(set (match_operand:HI 0 "general_operand" "=g") + (xor:HI (match_operand:HI 1 "general_operand" "g") + (match_operand:HI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"xorw2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"xorw2 %1,%0\"; + return \"xorw3 %2,%1,%0\"; +}") + + +(define_insn "xorqi3" + [(set (match_operand:QI 0 "general_operand" "=g") + (xor:QI (match_operand:QI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"xorb2 %2,%0\"; + if (rtx_equal_p (operands[0], operands[2])) + return \"xorb2 %1,%0\"; + return \"xorb3 %2,%1,%0\"; +}") + + +; shifts on the tahoe are expensive, try some magic first... + +(define_insn "ashlsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (ashift:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + if (GET_CODE(operands[2]) == REG) + return \"mull3 ___shtab[%2],%1,%0\"; + /* if (GET_CODE(operands[2]) == REG) + if (rtx_equal_p (operands[0], operands[1])) + return \"mull2 ___shtab[%2],%1\"; + else + return \"mull3 ___shtab[%2],%1,%0\"; */ + if (GET_CODE(operands[1]) == REG) + { + if (operands[2] == const1_rtx) + { + CC_STATUS_INIT; + return \"movaw 0[%1],%0\"; + } + if (GET_CODE(operands[2]) == CONST_INT && INTVAL(operands[2]) == 2) + { + CC_STATUS_INIT; + return \"moval 0[%1],%0\"; + } + } + if (GET_CODE(operands[2]) != CONST_INT || INTVAL(operands[2]) == 1) + return \"shal %2,%1,%0\"; + if (rtx_equal_p (operands[0], operands[1])) + return \"mull2 %s2,%1\"; + else + return \"mull3 %s2,%1,%0\"; +}") + + +(define_insn "ashrsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (ashiftrt:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "shar %2,%1,%0") + + +; shifts are very expensive, try some magic first... + +(define_insn "lshrsi3" + [(set (match_operand:SI 0 "general_operand" "=g") + (lshiftrt:SI (match_operand:SI 1 "general_operand" "g") + (match_operand:QI 2 "general_operand" "g")))] + "" + "shrl %2,%1,%0") + + +(define_insn "negsi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (neg:SI (match_operand:SI 1 "general_operand" "g")))] + "" + "mnegl %1,%0") + + +(define_insn "neghi2" + [(set (match_operand:HI 0 "general_operand" "=g") + (neg:HI (match_operand:HI 1 "general_operand" "g")))] + "" + "mnegw %1,%0") + + +(define_insn "negqi2" + [(set (match_operand:QI 0 "general_operand" "=g") + (neg:QI (match_operand:QI 1 "general_operand" "g")))] + "" + "mnegb %1,%0") + + +; negsf2 can only negate the value already in the fpp accumulator. +; The value remains in the fpp accumulator. No flags are set. + +(define_insn "negsf2" + [(set (match_operand:SF 0 "register_operand" "=a,=a") + (neg:SF (match_operand:SF 1 "register_operand" "a,g")))] + "" + "* +{ + CC_STATUS_INIT; + switch (which_alternative) + { + case 0: return \"negf\"; + case 1: return \"lnf %1\"; + } +}") + + +; negdf2 can only negate the value already in the fpp accumulator. +; The value remains in the fpp accumulator. No flags are set. + +(define_insn "negdf2" + [(set (match_operand:DF 0 "register_operand" "=a,=a") + (neg:DF (match_operand:DF 1 "register_operand" "a,g")))] + "" + "* +{ + CC_STATUS_INIT; + switch (which_alternative) + { + case 0: return \"negd\"; + case 1: return \"lnd %1\"; + } +}") + + +; sqrtsf2 tahoe can calculate the square root of a float in the +; fpp accumulator. The answer remains in the fpp accumulator. No +; flags are set by this function. + +(define_insn "sqrtsf2" + [(set (match_operand:SF 0 "register_operand" "=a") + (sqrt:SF (match_operand:SF 1 "register_operand" "0")))] + "" + "* +{ + CC_STATUS_INIT; + return \"sqrtf\"; +}") + + +; ffssi2 tahoe instruction gives one less than gcc desired result for +; any given input. So the increment is necessary here. + +(define_insn "ffssi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (ffs:SI (match_operand:SI 1 "general_operand" "g")))] + "" + "* +{ + if (push_operand(operands[0], SImode)) + return \"ffs %1,%0\;incl (sp)\"; + return \"ffs %1,%0\;incl %0\"; +}") + + +(define_insn "one_cmplsi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (not:SI (match_operand:SI 1 "general_operand" "g")))] + "" + "mcoml %1,%0") + + +(define_insn "one_cmplhi2" + [(set (match_operand:HI 0 "general_operand" "=g") + (not:HI (match_operand:HI 1 "general_operand" "g")))] + "" + "mcomw %1,%0") + + +(define_insn "one_cmplqi2" + [(set (match_operand:QI 0 "general_operand" "=g") + (not:QI (match_operand:QI 1 "general_operand" "g")))] + "" + "mcomb %1,%0") + + +; cmpsi works fine, but due to microcode problems, the tahoe doesn't +; properly compare hi's and qi's. Leaving them out seems to be acceptable +; to the compiler, so they were left out. Compares of the stack are +; possible, though. + +; There are optimized cases possible, however. These follow first. + +(define_insn "" + [(set (cc0) + (compare (sign_extend:SI (match_operand:HI 0 "memory_operand" "m")) + (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))))] + "" + "cmpw %0,%1") + +(define_insn "" + [(set (cc0) + (compare (match_operand:SI 0 "nonmemory_operand" "ri") + (sign_extend:SI (match_operand:HI 1 "memory_operand" "m"))))] + "" + "cmpw %0,%1") + +(define_insn "" + [(set (cc0) + (compare (sign_extend:SI (match_operand:HI 0 "memory_operand" "m")) + (match_operand:SI 1 "nonmemory_operand" "ri")))] + "" + "cmpw %0,%1") + +; zero-extended compares give the same result as sign-extended compares, if +; the compare is unsigned. Just see: if both operands are <65536 they are the +; same in both cases. If both are >=65536 the you effectively compare x+D +; with y+D, where D=2**32-2**16, so the result is the same. if x<65536 and +; y>=65536 then you compare x with y+D, and in both cases the result is x<y. + +(define_insn "" + [(set (cc0) + (compare (zero_extend:SI (match_operand:HI 0 "memory_operand" "m")) + (zero_extend:SI (match_operand:HI 1 "memory_operand" "m"))))] + "tahoe_cmp_check (insn, operands[0], 0)" + "cmpw %0,%1") + +(define_insn "" + [(set (cc0) + (compare (zero_extend:SI (match_operand:HI 0 "memory_operand" "m")) + (match_operand:SI 1 "immediate_operand" "i")))] + "tahoe_cmp_check(insn, operands[1], 65535)" + "* +{ + if (INTVAL (operands[1]) > 32767) + operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) + 0xffff0000); + return \"cmpw %0,%1\"; +}") + + +(define_insn "" + [(set (cc0) + (compare (sign_extend:SI (match_operand:QI 0 "memory_operand" "m")) + (sign_extend:SI (match_operand:QI 1 "memory_operand" "m"))))] + "" + "cmpb %0,%1") + +(define_insn "" + [(set (cc0) + (compare (match_operand:SI 0 "nonmemory_operand" "ri") + (sign_extend:SI (match_operand:QI 1 "memory_operand" "m"))))] + "" + "cmpb %0,%1") + +(define_insn "" + [(set (cc0) + (compare (sign_extend:SI (match_operand:QI 0 "memory_operand" "m")) + (match_operand:SI 1 "nonmemory_operand" "ri")))] + "" + "cmpb %0,%1") + +; zero-extended compares give the same result as sign-extended compares, if +; the compare is unsigned. Just see: if both operands are <128 they are the +; same in both cases. If both are >=128 the you effectively compare x+D +; with y+D, where D=2**32-2**8, so the result is the same. if x<128 and +; y>=128 then you compare x with y+D, and in both cases the result is x<y. + +(define_insn "" + [(set (cc0) + (compare (zero_extend:SI (match_operand:QI 0 "memory_operand" "m")) + (zero_extend:SI (match_operand:QI 1 "memory_operand" "m"))))] + "tahoe_cmp_check (insn, operands[0], 0)" + "cmpb %0,%1") + +(define_insn "" + [(set (cc0) + (compare (zero_extend:SI (match_operand:QI 0 "memory_operand" "m")) + (match_operand:SI 1 "immediate_operand" "i")))] + "tahoe_cmp_check(insn, operands[1], 255)" + "* +{ + if (INTVAL (operands[1]) > 127) + operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) + 0xffffff00); + return \"cmpb %0,%1\"; +}") + + +(define_insn "cmpsi" + [(set (cc0) + (compare (match_operand:SI 0 "nonimmediate_operand" "g") + (match_operand:SI 1 "general_operand" "g")))] + "" + "cmpl %0,%1") + + +; cmpsf similar to vax, but first operand is expected to be in the +; fpp accumulator. + +(define_insn "cmpsf" + [(set (cc0) + (compare (match_operand:SF 0 "general_operand" "a,g") + (match_operand:SF 1 "general_operand" "g,g")))] + "" + "* +{ + switch (which_alternative) + { + case 0: return \"cmpf %1\"; + case 1: return \"cmpf2 %0,%1\"; + } +}") + + +; cmpdf similar to vax, but first operand is expected to be in the +; fpp accumulator. Immediate doubles not allowed. + +(define_insn "cmpdf" + [(set (cc0) + (compare (match_operand:DF 0 "general_operand" "a,rm") + (match_operand:DF 1 "general_operand" "rm,rm")))] + "" + "* +{ + switch (which_alternative) + { + case 0: return \"cmpd %1\"; + case 1: return \"cmpd2 %0,%1\"; + } +}") + +;; We don't want to allow a constant operand for test insns because +;; (set (cc0) (const_int foo)) has no mode information. Such insns will +;; be folded while optimizing anyway. + +(define_insn "tstsi" + [(set (cc0) + (match_operand:SI 0 "nonimmediate_operand" "g"))] + "" + "tstl %0") + + +; small tests from memory are normal, but testing from registers doesn't +; expand the data properly. So test in this case does a convert and tests +; the new register data from the stack. + +; First some special cases that do work + + +(define_insn "" + [(set (cc0) + (sign_extend:SI (match_operand:HI 0 "memory_operand" "m")))] + "" + "tstw %0") + +(define_insn "" + [(set (cc0) + (zero_extend:SI (match_operand:HI 0 "memory_operand" "m")))] + "tahoe_cmp_check (insn, operands[0], 0)" + "tstw %0") + + +(define_insn "tsthi" + [(set (cc0) + (match_operand:HI 0 "extendable_operand" "m,!r"))] + "GET_MODE (operands[0]) != VOIDmode" + "* +{ + rtx xoperands[2]; + extern rtx tahoe_reg_conversion_loc; + switch (which_alternative) + { + case 0: + return \"tstw %0\"; + case 1: + xoperands[0] = operands[0]; + xoperands[1] = tahoe_reg_conversion_loc; + output_asm_insn (\"movl %0,%1\", xoperands); + xoperands[1] = plus_constant (XEXP (tahoe_reg_conversion_loc, 0), 2); + output_asm_insn (\"tstw %a1\", xoperands); + return \"\"; + } +}") + + +(define_insn "" + [(set (cc0) + (sign_extend:SI (match_operand:QI 0 "memory_operand" "m")))] + "" + "tstb %0") + +(define_insn "" + [(set (cc0) + (zero_extend:SI (match_operand:QI 0 "memory_operand" "m")))] + "tahoe_cmp_check (insn, operands[0], 0)" + "tstb %0") + + +(define_insn "tstqi" + [(set (cc0) + (match_operand:QI 0 "extendable_operand" "m,!r"))] + "GET_MODE (operands[0]) != VOIDmode" + "* +{ + rtx xoperands[2]; + extern rtx tahoe_reg_conversion_loc; + switch (which_alternative) + { + case 0: + return \"tstb %0\"; + case 1: + xoperands[0] = operands[0]; + xoperands[1] = tahoe_reg_conversion_loc; + output_asm_insn (\"movl %0,%1\", xoperands); + xoperands[1] = plus_constant (XEXP (tahoe_reg_conversion_loc, 0), 3); + output_asm_insn (\"tstb %a1\", xoperands); + return \"\"; + } +}") + +; tstsf compares a given value to a value already in the fpp accumulator. +; No flags are set by this so ignore them. + +(define_insn "tstsf" + [(set (cc0) + (match_operand:SF 0 "register_operand" "a"))] + "" + "tstf") + + +; tstdf compares a given value to a value already in the fpp accumulator. +; immediate doubles not allowed. Flags are ignored after this. + +(define_insn "tstdf" + [(set (cc0) + (match_operand:DF 0 "register_operand" "a"))] + "" + "tstd") + + + +; movstrhi tahoe instruction does not load registers by itself like +; the vax counterpart does. registers 0-2 must be primed by hand. +; we have loaded the registers in the order: dst, src, count. + +(define_insn "movstrhi" + [(set (match_operand:BLK 0 "general_operand" "p") + (match_operand:BLK 1 "general_operand" "p")) + (use (match_operand:HI 2 "general_operand" "g")) + (clobber (reg:SI 0)) + (clobber (reg:SI 1)) + (clobber (reg:SI 2))] + "" + "movab %0,r1\;movab %1,r0\;movl %2,r2\;movblk") + + +; floatsisf2 on tahoe converts the long from reg/mem into the fpp +; accumulator. There are no hi and qi counterparts. Flags are not +; set correctly here. + +(define_insn "floatsisf2" + [(set (match_operand:SF 0 "register_operand" "=a") + (float:SF (match_operand:SI 1 "general_operand" "g")))] + "" + "* +{ + CC_STATUS_INIT; + return \"cvlf %1\"; +}") + + +; floatsidf2 on tahoe converts the long from reg/mem into the fpp +; accumulator. There are no hi and qi counterparts. Flags are not +; set correctly here. + +(define_insn "floatsidf2" + [(set (match_operand:DF 0 "register_operand" "=a") + (float:DF (match_operand:SI 1 "general_operand" "g")))] + "" + "* +{ + CC_STATUS_INIT; + return \"cvld %1\"; +}") + + +; fix_truncsfsi2 to convert a float to long, tahoe must have the float +; in the fpp accumulator. Flags are not set here. + +(define_insn "fix_truncsfsi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "a"))))] + "" + "* +{ + CC_STATUS_INIT; + return \"cvfl %0\"; +}") + + +; fix_truncsfsi2 to convert a double to long, tahoe must have the double +; in the fpp accumulator. Flags are not set here. + +(define_insn "fix_truncdfsi2" + [(set (match_operand:SI 0 "general_operand" "=g") + (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "a"))))] + "" + "* +{ + CC_STATUS_INIT; + return \"cvdl %0\"; +}") + + +(define_insn "truncsihi2" + [(set (match_operand:HI 0 "general_operand" "=g") + (truncate:HI (match_operand:SI 1 "general_operand" "g")))] + "" + "cvtlw %1,%0") + + +(define_insn "truncsiqi2" + [(set (match_operand:QI 0 "general_operand" "=g") + (truncate:QI (match_operand:SI 1 "general_operand" "g")))] + "" + "cvtlb %1,%0") + + +(define_insn "trunchiqi2" + [(set (match_operand:QI 0 "general_operand" "=g") + (truncate:QI (match_operand:HI 1 "general_operand" "g")))] + "" + "cvtwb %1,%0") + + +; The fpp related instructions don't set flags, so ignore them +; after this instruction. + +(define_insn "truncdfsf2" + [(set (match_operand:SF 0 "register_operand" "=a") + (float_truncate:SF (match_operand:DF 1 "register_operand" "0")))] + "" + "* +{ + CC_STATUS_INIT; + return \"cvdf\"; +}") + + +; This monster is to cover for the Tahoe's nasty habit of not extending +; a number if the source is in a register. (It just moves it!) Case 0 is +; a normal extend from memory. Case 1 does the extension from the top of +; the stack. Extension from the stack doesn't set the flags right since +; the moval changes them. + +(define_insn "extendhisi2" + [(set (match_operand:SI 0 "general_operand" "=g,?=g") + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))] + "" + "* +{ + switch (which_alternative) + { + case 0: + return \"cvtwl %1,%0\"; + case 1: + if (push_operand (operands[0], SImode)) + return \"pushl %1\;cvtwl 2(sp),(sp)\"; + else + { + CC_STATUS_INIT; + return \"pushl %1\;cvtwl 2(sp),%0\;moval 4(sp),sp\"; + } + } +}") + +; This monster is to cover for the Tahoe's nasty habit of not extending +; a number if the source is in a register. (It just moves it!) Case 0 is +; a normal extend from memory. Case 1 does the extension from the top of +; the stack. Extension from the stack doesn't set the flags right since +; the moval changes them. + +(define_insn "extendqisi2" + [(set (match_operand:SI 0 "general_operand" "=g,?=g") + (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] + "" + "* +{ + switch (which_alternative) + { + case 0: + return \"cvtbl %1,%0\"; + case 1: + if (push_operand (operands[0], SImode)) + return \"pushl %1\;cvtbl 3(sp),(sp)\"; + else + { + CC_STATUS_INIT; + return \"pushl %1\;cvtbl 3(sp),%0\;moval 4(sp),sp\"; + } + } +}") + + +; This monster is to cover for the Tahoe's nasty habit of not extending +; a number if the source is in a register. (It just moves it!) Case 0 is +; a normal extend from memory. Case 1 does the extension from the top of +; the stack. Extension from the stack doesn't set the flags right since +; the moval changes them. + +(define_insn "extendqihi2" + [(set (match_operand:HI 0 "general_operand" "=g,?=g") + (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] + "" + "* +{ + switch (which_alternative) + { + case 0: + return \"cvtbw %1,%0\"; + case 1: + if (push_operand (operands[0], SImode)) + return \"pushl %1\;cvtbw 3(sp),(sp)\"; + else + { + CC_STATUS_INIT; + return \"pushl %1\;cvtbw 3(sp),%0\;moval 4(sp),sp\"; + } + } +}") + + +; extendsfdf2 tahoe uses the fpp accumulator to do the extension. +; It takes a float and loads it up directly as a double. + +(define_insn "extendsfdf2" + [(set (match_operand:DF 0 "register_operand" "=a") + (float_extend:DF (match_operand:SF 1 "general_operand" "g")))] + "" + "* +{ + CC_STATUS_INIT; + return \"ldfd %1\"; +}") + + +; movz works fine from memory but not from register for the same reasons +; the cvt instructions don't work right. So we use the normal instruction +; from memory and we use an and to simulate it from register. This is faster +; than pulling it off the stack. + + +(define_insn "zero_extendhisi2" + [(set (match_operand:SI 0 "general_operand" "=g,?=g") + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "m,r")))] + "" + "* +{ + switch (which_alternative) + { + case 0: return \"movzwl %1,%0\"; + case 1: return \"andl3 $0xffff,%1,%0\"; + } +}") + +; movz works fine from memory but not from register for the same reasons +; the cvt instructions don't work right. So we use the normal instruction +; from memory and we use an and to simulate it from register. This is faster +; than pulling it off the stack. + +(define_insn "zero_extendqihi2" + [(set (match_operand:HI 0 "general_operand" "=g,?=g") + (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] + "" + "* +{ + switch (which_alternative) + { + case 0: return \"movzbw %1,%0\"; + case 1: return \"andw3 $0xff,%1,%0\"; + } +}") + + +; movz works fine from memory but not from register for the same reasons +; the cvt instructions don't work right. So we use the normal instruction +; from memory and we use an and to simulate it from register. This is faster +; than pulling it off the stack. + +(define_insn "zero_extendqisi2" + [(set (match_operand:SI 0 "general_operand" "=g,?=g") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "m,r")))] + "" + "* +{ + switch (which_alternative) + { + case 0: return \"movzbl %1,%0\"; + case 1: return \"andl3 $0xff,%1,%0\"; + } +}") + + +(define_insn "beq" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jeql %l0") + + +(define_insn "bne" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jneq %l0") + + +(define_insn "bgt" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jgtr %l0") + + +(define_insn "bgtu" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jgtru %l0") + + +(define_insn "blt" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jlss %l0") + + +(define_insn "bltu" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jlssu %l0") + + +(define_insn "bge" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jgeq %l0") + + +(define_insn "bgeu" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jgequ %l0") + + +(define_insn "ble" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jleq %l0") + + +(define_insn "bleu" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (label_ref (match_operand 0 "" "")) + (pc)))] + "" + "jlequ %l0") + + +; gcc does not account for register mask/argc longword. Thus the number +; for the call = number bytes for args + 4 + +(define_insn "call" + [(call (match_operand:QI 0 "memory_operand" "m") + (match_operand:QI 1 "general_operand" "g"))] + "" + "* +{ + operands[1] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[1]) + 4)); + if (GET_CODE(operands[0]) == MEM + && CONSTANT_ADDRESS_P (XEXP(operands[0], 0)) + && INTVAL (operands[1]) < 64) + return \"callf %1,%0\"; /* this is much faster */ + return \"calls %1,%0\"; +}") + +; gcc does not account for register mask/argc longword. Thus the number +; for the call = number bytes for args + 4 + +(define_insn "call_value" + [(set (match_operand 0 "" "=g") + (call (match_operand:QI 1 "memory_operand" "m") + (match_operand:QI 2 "general_operand" "g")))] + "" + "* +{ + operands[2] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[2]) + 4)); + if (GET_CODE(operands[1]) == MEM + && CONSTANT_ADDRESS_P (XEXP(operands[1], 0)) + && INTVAL (operands[2]) < 64) + return \"callf %2,%1\"; /* this is much faster */ + return \"calls %2,%1\"; +}") + + +(define_insn "return" + [(return)] + "" + "ret") + +(define_insn "nop" + [(const_int 0)] + "" + "nop") + +; casesi this code extracted from the vax code. The instructions are +; very similar. Tahoe requires that the table be word aligned. GCC +; places the table immediately after, thus the alignment directive. + +(define_insn "casesi" + [(set (pc) + (if_then_else (le (minus:SI (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")) + (match_operand:SI 2 "general_operand" "g")) + (plus:SI (sign_extend:SI + (mem:HI (plus:SI (pc) + (minus:SI (match_dup 0) + (match_dup 1))))) + (label_ref:SI (match_operand 3 "" ""))) + (pc)))] + "" + "casel %0,%1,%2\;.align %@") + + +(define_insn "jump" + [(set (pc) + (label_ref (match_operand 0 "" "")))] + "" + "jbr %l0") + + +;; This is the list of all the non-standard insn patterns + + +; This is used to access the address of a byte. This is similar to +; movqi, but the second operand had to be "address_operand" type, so +; it had to be an unnamed one. + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (match_operand:QI 1 "address_operand" "p"))] + "" + "* +{ + if (push_operand (operands[0], SImode)) + return \"pushab %a1\"; + return \"movab %a1,%0\"; +}") + +; This is used to access the address of a word. This is similar to +; movhi, but the second operand had to be "address_operand" type, so +; it had to be an unnamed one. + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (match_operand:HI 1 "address_operand" "p"))] + "" + "* +{ + if (push_operand (operands[0], SImode)) + return \"pushaw %a1\"; + return \"movaw %a1,%0\"; +}") + +; This is used to access the address of a long. This is similar to +; movsi, but the second operand had to be "address_operand" type, so +; it had to be an unnamed one. + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=g") + (match_operand:SI 1 "address_operand" "p"))] + "" + "* +{ + if (push_operand (operands[0], SImode)) + return \"pushal %a1\"; + return \"moval %a1,%0\"; +}") + + +; bit test longword instruction, same as vax + +(define_insn "" + [(set (cc0) + (and:SI (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")))] + "" + "bitl %0,%1") + + +; bit test word instructions, same as vax + +(define_insn "" + [(set (cc0) + (and:HI (match_operand:HI 0 "general_operand" "g") + (match_operand:HI 1 "general_operand" "g")))] + "" + "bitw %0,%1") + + +; bit test instructions, same as vax + +(define_insn "" + [(set (cc0) + (and:QI (match_operand:QI 0 "general_operand" "g") + (match_operand:QI 1 "general_operand" "g")))] + "" + "bitb %0,%1") + + +; bne counterpart. in case gcc reverses the conditional. + +(define_insn "" + [(set (pc) + (if_then_else (eq (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jneq %l0") + + +; beq counterpart. in case gcc reverses the conditional. + +(define_insn "" + [(set (pc) + (if_then_else (ne (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jeql %l0") + + +; ble counterpart. in case gcc reverses the conditional. + +(define_insn "" + [(set (pc) + (if_then_else (gt (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jleq %l0") + + +; bleu counterpart. in case gcc reverses the conditional. + +(define_insn "" + [(set (pc) + (if_then_else (gtu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jlequ %l0") + + +; bge counterpart. in case gcc reverses the conditional. + +(define_insn "" + [(set (pc) + (if_then_else (lt (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jgeq %l0") + + +; bgeu counterpart. in case gcc reverses the conditional. + +(define_insn "" + [(set (pc) + (if_then_else (ltu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jgequ %l0") + + +; blt counterpart. in case gcc reverses the conditional. + +(define_insn "" + [(set (pc) + (if_then_else (ge (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jlss %l0") + + +; bltu counterpart. in case gcc reverses the conditional. + +(define_insn "" + [(set (pc) + (if_then_else (geu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jlssu %l0") + + +; bgt counterpart. in case gcc reverses the conditional. + +(define_insn "" + [(set (pc) + (if_then_else (le (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jgtr %l0") + + +; bgtu counterpart. in case gcc reverses the conditional. + +(define_insn "" + [(set (pc) + (if_then_else (leu (cc0) + (const_int 0)) + (pc) + (label_ref (match_operand 0 "" ""))))] + "" + "jgtru %l0") + + +; casesi alternate form as found in vax code. this form is to +; compensate for the table's offset being no distance (0 displacement) + +(define_insn "" + [(set (pc) + (if_then_else (le (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")) + (plus:SI (sign_extend:SI + (mem:HI (plus:SI (pc) + (minus:SI (match_dup 0) + (const_int 0))))) + (label_ref:SI (match_operand 3 "" ""))) + (pc)))] + "" + "casel %0,$0,%1\;.align %@") + + +; casesi alternate form as found in vax code. another form to +; compensate for the table's offset being no distance (0 displacement) + +(define_insn "" + [(set (pc) + (if_then_else (le (match_operand:SI 0 "general_operand" "g") + (match_operand:SI 1 "general_operand" "g")) + (plus:SI (sign_extend:SI + (mem:HI (plus:SI (pc) + (match_dup 0)))) + (label_ref:SI (match_operand 3 "" ""))) + (pc)))] + "" + "casel %0,$0,%1 \;.align %@") + +(define_insn "" + [(set (pc) + (if_then_else + (lt (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int 1)) + (match_operand:SI 1 "general_operand" "g")) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "" + "aoblss %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (le (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int 1)) + (match_operand:SI 1 "general_operand" "g")) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "" + "aobleq %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (ge (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int 1)) + (match_operand:SI 1 "general_operand" "g")) + (pc) + (label_ref (match_operand 2 "" "")))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "" + "aoblss %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (gt (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int 1)) + (match_operand:SI 1 "general_operand" "g")) + (pc) + (label_ref (match_operand 2 "" "")))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "" + "aobleq %1,%0,%l2") + +; bbs/bbc + +(define_insn "" + [(set (pc) + (if_then_else + (ne (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") + (const_int 1) + (subreg:QI (match_operand:SI 1 "general_operand" "g") 0)) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc)))] + "" + "bbs %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") + (const_int 1) + (subreg:QI (match_operand:SI 1 "general_operand" "g") 0)) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc)))] + "" + "bbc %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (ne (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") + (const_int 1) + (subreg:QI (match_operand:SI 1 "general_operand" "g") 0)) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" ""))))] + "" + "bbc %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") + (const_int 1) + (subreg:QI (match_operand:SI 1 "general_operand" "g") 0)) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" ""))))] + "" + "bbs %1,%0,%l2") + +; if the shift count is a byte in a register we can use it as a long + +(define_insn "" + [(set (pc) + (if_then_else + (ne (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") + (const_int 1) + (match_operand:QI 1 "register_operand" "r")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc)))] + "" + "bbs %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") + (const_int 1) + (match_operand:QI 1 "register_operand" "r")) + (const_int 0)) + (label_ref (match_operand 2 "" "")) + (pc)))] + "" + "bbc %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (ne (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") + (const_int 1) + (match_operand:QI 1 "register_operand" "r")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" ""))))] + "" + "bbc %1,%0,%l2") + +(define_insn "" + [(set (pc) + (if_then_else + (eq (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm") + (const_int 1) + (match_operand:QI 1 "register_operand" "r")) + (const_int 0)) + (pc) + (label_ref (match_operand 2 "" ""))))] + "" + "bbs %1,%0,%l2") + +; special case for 1 << constant. We don't do these because they are slower +; than the bitl instruction + +;(define_insn "" +; [(set (pc) +; (if_then_else +; (ne (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm") +; (match_operand:SI 1 "immediate_operand" "i")) +; (const_int 0)) +; (label_ref (match_operand 2 "" "")) +; (pc)))] +; "GET_CODE (operands[1]) == CONST_INT +; && exact_log2 (INTVAL (operands[1])) >= 0" +; "* +;{ +; operands[1] +; = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1]))); +; return \"bbs %1,%0,%l2\"; +;}") +; +;(define_insn "" +; [(set (pc) +; (if_then_else +; (eq (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm") +; (match_operand:SI 1 "immediate_operand" "i")) +; (const_int 0)) +; (label_ref (match_operand 2 "" "")) +; (pc)))] +; "GET_CODE (operands[1]) == CONST_INT +; && exact_log2 (INTVAL (operands[1])) >= 0" +; "* +;{ +; operands[1] +; = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1]))); +; return \"bbc %1,%0,%l2\"; +;}") +; +;(define_insn "" +; [(set (pc) +; (if_then_else +; (ne (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm") +; (match_operand:SI 1 "immediate_operand" "i")) +; (const_int 0)) +; (pc) +; (label_ref (match_operand 2 "" ""))))] +; "GET_CODE (operands[1]) == CONST_INT +; && exact_log2 (INTVAL (operands[1])) >= 0" +; "* +;{ +; operands[1] +; = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1]))); +; return \"bbc %1,%0,%l2\"; +;}") +; +;(define_insn "" +; [(set (pc) +; (if_then_else +; (eq (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm") +; (match_operand:SI 1 "immediate_operand" "i")) +; (const_int 0)) +; (pc) +; (label_ref (match_operand 2 "" ""))))] +; "GET_CODE (operands[1]) == CONST_INT +; && exact_log2 (INTVAL (operands[1])) >= 0" +; "* +;{ +; operands[1] +; = gen_rtx (CONST_INT, VOIDmode, exact_log2 (INTVAL (operands[1]))); +; return \"bbs %1,%0,%l2\"; +;}") diff --git a/gnu/usr.bin/gcc/config/tahoe/xm-tahoe.h b/gnu/usr.bin/gcc/config/tahoe/xm-tahoe.h new file mode 100644 index 00000000000..1af7bdda31e --- /dev/null +++ b/gnu/usr.bin/gcc/config/tahoe/xm-tahoe.h @@ -0,0 +1,59 @@ +/* Configuration for GNU C-compiler for Tahoe. + Copyright (C) 1987, 1993 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. */ + +/* + * File: xm-tahoe.h + * + * 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) + * + * Mail bugs reports or fixes to: gcc@cs.buffalo.edu + */ + + +/* This file has the same stuff the vax version does */ + +/* defines that need visibility everywhere */ + +#define FALSE 0 +#define TRUE 1 + +/* target machine dependencies + tm.h is a symbolic link to the actual target specific file. */ + +#include "tm.h" + +/* This describes the machine the compiler is hosted on. */ + +#define HOST_BITS_PER_CHAR 8 +#define HOST_BITS_PER_SHORT 16 +#define HOST_BITS_PER_INT 32 +#define HOST_BITS_PER_LONG 32 +#define HOST_BITS_PER_LONGLONG 64 + +#define HOST_WORDS_BIG_ENDIAN + +/* Arguments to use with `exit'. */ + +#define SUCCESS_EXIT_CODE 0 +#define FATAL_EXIT_CODE 33 |