yann@1: --------- snip ------- yann@1: Downloaded from ftp://ftp.linux.org.uk/pub/armlinux/toolchain/src-2.95.3/gcc-2.95.3.diff.bz2 yann@1: Not sure what it fixes, but this appears to be The Patch used with gcc-2.95.3 on arm. yann@1: --------- snip ------- yann@1: yann@1: diff -urN gcc-2.95.3-orig/gcc/config/arm/arm.c gcc-2.95.3/gcc/config/arm/arm.c yann@1: --- gcc-2.95.3-orig/gcc/config/arm/arm.c Thu Jan 25 15:03:24 2001 yann@1: +++ gcc-2.95.3/gcc/config/arm/arm.c Fri Jul 20 19:39:11 2001 yann@1: @@ -1529,27 +1529,34 @@ yann@1: return gen_rtx_PLUS (Pmode, base, offset); yann@1: } yann@1: else if (GET_CODE (orig) == LABEL_REF) yann@1: - current_function_uses_pic_offset_table = 1; yann@1: - yann@1: - return orig; yann@1: -} yann@1: + { yann@1: + current_function_uses_pic_offset_table = 1; yann@1: yann@1: -static rtx pic_rtx; yann@1: + if (NEED_PLT_GOT) yann@1: + { yann@1: + rtx pic_ref, address = gen_reg_rtx (Pmode); yann@1: + yann@1: + emit_insn (gen_pic_load_addr (address, orig)); yann@1: + pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, yann@1: + address); yann@1: + emit_move_insn (address, pic_ref); yann@1: + return address; yann@1: + } yann@1: + } yann@1: yann@1: -int yann@1: -is_pic(x) yann@1: - rtx x; yann@1: -{ yann@1: - if (x == pic_rtx) yann@1: - return 1; yann@1: - return 0; yann@1: + return orig; yann@1: } yann@1: yann@1: +/* Generate code to load the PIC register. PROLOGUE is true if yann@1: + called from arm_expand_prologue (in which case we want the yann@1: + generated insns at the start of the function); false if called yann@1: + by an exception receiver that needs the PIC register reloaded yann@1: + (in which case the insns are just dumped at the current location). */ yann@1: void yann@1: -arm_finalize_pic () yann@1: +arm_finalize_pic (int prologue) yann@1: { yann@1: #ifndef AOF_ASSEMBLER yann@1: - rtx l1, pic_tmp, pic_tmp2, seq; yann@1: + rtx l1, pic_tmp, pic_tmp2, seq, pic_rtx; yann@1: rtx global_offset_table; yann@1: yann@1: if (current_function_uses_pic_offset_table == 0) yann@1: @@ -1578,7 +1585,10 @@ yann@1: yann@1: seq = gen_sequence (); yann@1: end_sequence (); yann@1: - emit_insn_after (seq, get_insns ()); yann@1: + if (prologue) yann@1: + emit_insn_after (seq, get_insns ()); yann@1: + else yann@1: + emit_insn (seq); yann@1: yann@1: /* Need to emit this whether or not we obey regdecls, yann@1: since setjmp/longjmp can cause life info to screw up. */ yann@1: @@ -5327,7 +5337,13 @@ yann@1: if (frame_pointer_needed) yann@1: live_regs += 4; yann@1: yann@1: - if (live_regs) yann@1: + if (live_regs == 1 && regs_ever_live[LR_REGNUM] yann@1: + && ! lr_save_eliminated && ! really_return) yann@1: + { yann@1: + output_asm_insn (reverse ? "ldr%?%D0\t%|lr, [%|sp}, #4" yann@1: + : "ldr%?%d0\t%|lr, [%|sp], #4", &operand); yann@1: + } yann@1: + else if (live_regs) yann@1: { yann@1: if (lr_save_eliminated || ! regs_ever_live[14]) yann@1: live_regs++; yann@1: @@ -5446,7 +5462,7 @@ yann@1: rtx x; yann@1: yann@1: length = strlen (name); yann@1: - alignlength = (length + 1) + 3 & ~3; yann@1: + alignlength = ((length + 1) + 3) & ~3; yann@1: yann@1: ASM_OUTPUT_ASCII (stream, name, length + 1); yann@1: ASM_OUTPUT_ALIGN (stream, 2); yann@1: @@ -5838,6 +5854,9 @@ yann@1: int store_arg_regs = 0; yann@1: int volatile_func = (optimize > 0 yann@1: && TREE_THIS_VOLATILE (current_function_decl)); yann@1: + rtx ip_rtx; yann@1: + int fp_offset = 0; yann@1: + rtx insn; yann@1: yann@1: /* Naked functions don't have prologues. */ yann@1: if (arm_naked_function_p (current_function_decl)) yann@1: @@ -5859,11 +5878,59 @@ yann@1: live_regs_mask |= 0x4000; yann@1: } yann@1: yann@1: + ip_rtx = gen_rtx_REG (SImode, IP_REGNUM); yann@1: + yann@1: if (frame_pointer_needed) yann@1: { yann@1: + if (current_function_needs_context) yann@1: + { yann@1: + /* The Static chain register is the same as the IP register yann@1: + used as a scratch register during stack frame creation. yann@1: + To get around this need to find somewhere to store IP yann@1: + whilst the frame is being created. We try the following yann@1: + places in order: yann@1: + yann@1: + 1. An unused argument register. yann@1: + 2. A slot on the stack above the frame. (This only yann@1: + works if the function is not a varargs function). yann@1: + yann@1: + If neither of these places is available, we abort (for now). */ yann@1: + if (regs_ever_live[3] == 0) yann@1: + { yann@1: + insn = gen_rtx_REG (SImode, 3); yann@1: + insn = gen_rtx_SET (SImode, insn, ip_rtx); yann@1: + insn = emit_insn (insn); yann@1: + RTX_FRAME_RELATED_P (insn) = 1; yann@1: + } yann@1: + else if (current_function_pretend_args_size == 0) yann@1: + { yann@1: + insn = gen_rtx_PRE_DEC (SImode, stack_pointer_rtx); yann@1: + insn = gen_rtx_MEM (SImode, insn); yann@1: + insn = gen_rtx_SET (VOIDmode, insn, ip_rtx); yann@1: + insn = emit_insn (insn); yann@1: + RTX_FRAME_RELATED_P (insn) = 1; yann@1: + fp_offset = 4; yann@1: + } yann@1: + else yann@1: + /* FIXME - the way to handle this situation is to allow yann@1: + the pretend args to be dumped onto the stack, then yann@1: + reuse r3 to save IP. This would involve moving the yann@1: + copying os SP into IP until after the pretend args yann@1: + have been dumped, but this is not too hard. */ yann@1: + error ("Unable to find a temporary location for static chanin register"); yann@1: + } yann@1: + yann@1: live_regs_mask |= 0xD800; yann@1: - emit_insn (gen_movsi (gen_rtx_REG (SImode, 12), yann@1: - stack_pointer_rtx)); yann@1: + if (fp_offset) yann@1: + { yann@1: + insn = gen_rtx_PLUS (SImode, stack_pointer_rtx, GEN_INT (fp_offset)); yann@1: + insn = gen_rtx_SET (SImode, ip_rtx, insn); yann@1: + } yann@1: + else yann@1: + insn = gen_movsi (ip_rtx, stack_pointer_rtx); yann@1: + yann@1: + insn = emit_insn (insn); yann@1: + RTX_FRAME_RELATED_P (insn) = 1; yann@1: } yann@1: yann@1: if (current_function_pretend_args_size) yann@1: @@ -5927,9 +5994,31 @@ yann@1: } yann@1: yann@1: if (frame_pointer_needed) yann@1: - emit_insn (gen_addsi3 (hard_frame_pointer_rtx, gen_rtx_REG (SImode, 12), yann@1: - (GEN_INT yann@1: - (-(4 + current_function_pretend_args_size))))); yann@1: + { yann@1: + insn = GEN_INT (-(4 + current_function_pretend_args_size + fp_offset)); yann@1: + insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, ip_rtx, insn)); yann@1: + RTX_FRAME_RELATED_P (insn) = 1; yann@1: + yann@1: + if (current_function_needs_context) yann@1: + { yann@1: + /* Recover the static chain register. */ yann@1: + if (regs_ever_live [3] == 0) yann@1: + { yann@1: + insn = gen_rtx_REG (SImode, 3); yann@1: + insn = gen_rtx_SET (SImode, ip_rtx, insn); yann@1: + insn = emit_insn (insn); yann@1: + RTX_FRAME_RELATED_P (insn) = 1; yann@1: + } yann@1: + else /* if (current_function_pretend_args_size == 0) */ yann@1: + { yann@1: + insn = gen_rtx_PLUS (SImode, hard_frame_pointer_rtx, GEN_INT (4)); yann@1: + insn = gen_rtx_MEM (SImode, insn); yann@1: + insn = gen_rtx_SET (SImode, ip_rtx, insn); yann@1: + insn = emit_insn (insn); yann@1: + RTX_FRAME_RELATED_P (insn) = 1; yann@1: + } yann@1: + } yann@1: + } yann@1: yann@1: if (amount != const0_rtx) yann@1: { yann@1: diff -urN gcc-2.95.3-orig/gcc/config/arm/arm.h gcc-2.95.3/gcc/config/arm/arm.h yann@1: --- gcc-2.95.3-orig/gcc/config/arm/arm.h Thu Jan 25 15:03:26 2001 yann@1: +++ gcc-2.95.3/gcc/config/arm/arm.h Fri Jul 20 19:39:11 2001 yann@1: @@ -601,14 +601,20 @@ yann@1: (TREE_CODE (EXP) == STRING_CST \ yann@1: && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN)) yann@1: yann@1: +#ifndef STRUCTURE_SIZE_BOUNDARY yann@1: /* Every structures size must be a multiple of 32 bits. */ yann@1: /* This is for compatibility with ARMCC. ARM SDT Reference Manual yann@1: (ARM DUI 0020D) page 2-20 says "Structures are aligned on word yann@1: boundaries". */ yann@1: -#ifndef STRUCTURE_SIZE_BOUNDARY yann@1: -#define STRUCTURE_SIZE_BOUNDARY 32 yann@1: +/* Setting this to 32 produces more efficient code, but the value set in previous yann@1: + versions of this toolchain was 8, which produces more compact structures. The yann@1: + command line option -mstructure_size_boundary= can be used to change this yann@1: + value. */ yann@1: +#define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary yann@1: #endif yann@1: yann@1: +extern int arm_structure_size_boundary; yann@1: + yann@1: /* Used when parsing command line option -mstructure_size_boundary. */ yann@1: extern const char * structure_size_string; yann@1: yann@1: @@ -768,6 +774,9 @@ yann@1: /* Specify the registers used for certain standard purposes. yann@1: The values of these macros are register numbers. */ yann@1: yann@1: +/* Register which holds return address from a subroutine call. */ yann@1: +#define LR_REGNUM 14 yann@1: + yann@1: /* Define this if the program counter is overloaded on a register. */ yann@1: #define PC_REGNUM 15 yann@1: yann@1: @@ -777,6 +786,9 @@ yann@1: /* Base register for access to local variables of the function. */ yann@1: #define FRAME_POINTER_REGNUM 25 yann@1: yann@1: +/* Scratch register - used in all kinds of places, eg trampolines. */ yann@1: +#define IP_REGNUM 12 yann@1: + yann@1: /* Define this to be where the real frame pointer is if it is not possible to yann@1: work out the offset between the frame pointer and the automatic variables yann@1: until after register allocation has taken place. FRAME_POINTER_REGNUM yann@1: @@ -798,7 +810,7 @@ yann@1: /* The native (Norcroft) Pascal compiler for the ARM passes the static chain yann@1: as an invisible last argument (possible since varargs don't exist in yann@1: Pascal), so the following is not true. */ yann@1: -#define STATIC_CHAIN_REGNUM 8 yann@1: +#define STATIC_CHAIN_REGNUM 12 yann@1: yann@1: /* Register in which address to store a structure value yann@1: is passed to a function. */ yann@1: @@ -1248,7 +1260,12 @@ yann@1: { \ yann@1: int volatile_func = arm_volatile_func (); \ yann@1: if ((FROM) == ARG_POINTER_REGNUM && (TO) == HARD_FRAME_POINTER_REGNUM)\ yann@1: - (OFFSET) = 0; \ yann@1: + { \ yann@1: + if (! current_function_needs_context || ! frame_pointer_needed) \ yann@1: + (OFFSET) = 0; \ yann@1: + else \ yann@1: + (OFFSET) = 4; \ yann@1: + } \ yann@1: else if ((FROM) == FRAME_POINTER_REGNUM \ yann@1: && (TO) == STACK_POINTER_REGNUM) \ yann@1: (OFFSET) = (current_function_outgoing_args_size \ yann@1: @@ -1379,8 +1396,10 @@ yann@1: yann@1: On the ARM, allow any integer (invalid ones are removed later by insn yann@1: patterns), nice doubles and symbol_refs which refer to the function's yann@1: - constant pool XXX. */ yann@1: -#define LEGITIMATE_CONSTANT_P(X) (! label_mentioned_p (X)) yann@1: + constant pool XXX. yann@1: + yann@1: + When generating PIC code, allow anything. */ yann@1: +#define LEGITIMATE_CONSTANT_P(X) (flag_pic || ! label_mentioned_p (X)) yann@1: yann@1: /* Symbols in the text segment can be accessed without indirecting via the yann@1: constant pool; it may take an extra binary operation, but this is still yann@1: @@ -1496,9 +1515,8 @@ yann@1: && INTVAL (op) <= 31) \ yann@1: goto LABEL; \ yann@1: } \ yann@1: - /* NASTY: Since this limits the addressing of unsigned byte loads */ \ yann@1: range = ((MODE) == HImode || (MODE) == QImode) \ yann@1: - ? (arm_arch4 ? 256 : 4095) : 4096; \ yann@1: + ? (((MODE) == HImode && arm_arch4) ? 256 : 4095) : 4096; \ yann@1: if (code == CONST_INT && INTVAL (INDEX) < range \ yann@1: && INTVAL (INDEX) > -range) \ yann@1: goto LABEL; \ yann@1: @@ -1812,14 +1830,15 @@ yann@1: data addresses in memory. */ yann@1: #define PIC_OFFSET_TABLE_REGNUM arm_pic_register yann@1: yann@1: -#define FINALIZE_PIC arm_finalize_pic () yann@1: +#define FINALIZE_PIC arm_finalize_pic (1) yann@1: yann@1: -/* We can't directly access anything that contains a symbol, yann@1: +/* We can't directly access anything that contains a symbol or label, yann@1: nor can we indirect via the constant pool. */ yann@1: #define LEGITIMATE_PIC_OPERAND_P(X) \ yann@1: - (! symbol_mentioned_p (X) \ yann@1: + (! symbol_mentioned_p (X) && ! label_mentioned_p (X) \ yann@1: && (! CONSTANT_POOL_ADDRESS_P (X) \ yann@1: - || ! symbol_mentioned_p (get_pool_constant (X)))) yann@1: + || (! symbol_mentioned_p (get_pool_constant (X))) \ yann@1: + && (! label_mentioned_p (get_pool_constant (X))))) yann@1: yann@1: /* We need to know when we are making a constant pool; this determines yann@1: whether data needs to be in the GOT or can be referenced via a GOT yann@1: @@ -2046,17 +2065,9 @@ yann@1: else output_addr_const(STREAM, X); \ yann@1: } yann@1: yann@1: -/* Handles PIC addr specially */ yann@1: #define OUTPUT_INT_ADDR_CONST(STREAM,X) \ yann@1: { \ yann@1: - if (flag_pic && GET_CODE(X) == CONST && is_pic(X)) \ yann@1: - { \ yann@1: - output_addr_const(STREAM, XEXP (XEXP (XEXP (X, 0), 0), 0)); \ yann@1: - fputs(" - (", STREAM); \ yann@1: - output_addr_const(STREAM, XEXP (XEXP (XEXP (X, 0), 1), 0)); \ yann@1: - fputs(")", STREAM); \ yann@1: - } \ yann@1: - else output_addr_const(STREAM, X); \ yann@1: + output_addr_const(STREAM, X); \ yann@1: \ yann@1: /* Mark symbols as position independent. We only do this in the \ yann@1: .text segment, not in the .data segment. */ \ yann@1: @@ -2170,8 +2181,7 @@ yann@1: int arm_return_in_memory PROTO ((Tree)); yann@1: int legitimate_pic_operand_p PROTO ((Rtx)); yann@1: Rtx legitimize_pic_address PROTO ((Rtx, Mmode, Rtx)); yann@1: -int is_pic PROTO ((Rtx)); yann@1: -void arm_finalize_pic PROTO ((void)); yann@1: +void arm_finalize_pic PROTO ((int)); yann@1: int arm_rtx_costs RTX_CODE_PROTO ((Rtx, Rcode)); yann@1: int arm_adjust_cost PROTO ((Rtx, Rtx, Rtx, int)); yann@1: int const_double_rtx_ok_for_fpu PROTO ((Rtx)); yann@1: diff -urN gcc-2.95.3-orig/gcc/config/arm/arm.md gcc-2.95.3/gcc/config/arm/arm.md yann@1: --- gcc-2.95.3-orig/gcc/config/arm/arm.md Thu Jan 25 15:03:27 2001 yann@1: +++ gcc-2.95.3/gcc/config/arm/arm.md Fri Jul 20 19:39:11 2001 yann@1: @@ -2629,7 +2629,8 @@ yann@1: : preserve_subexpressions_p ())); yann@1: DONE; yann@1: } yann@1: - if (CONSTANT_P (operands[1]) && flag_pic) yann@1: + if ((CONSTANT_P (operands[1]) || symbol_mentioned_p (operands[1]) yann@1: + || label_mentioned_p (operands[1])) && flag_pic) yann@1: operands[1] = legitimize_pic_address (operands[1], SImode, yann@1: ((reload_in_progress yann@1: || reload_completed) yann@1: @@ -2721,6 +2722,15 @@ yann@1: return \"add%?\\t%0, %|pc, %0\"; yann@1: ") yann@1: yann@1: +(define_expand "builtin_setjmp_receiver" yann@1: + [(label_ref (match_operand 0 "" ""))] yann@1: + "flag_pic" yann@1: + " yann@1: +{ yann@1: + arm_finalize_pic (0); yann@1: + DONE; yann@1: +}") yann@1: + yann@1: ;; If copying one reg to another we can set the condition codes according to yann@1: ;; its value. Such a move is common after a return from subroutine and the yann@1: ;; result is being tested against zero. yann@1: @@ -6184,15 +6194,20 @@ yann@1: abort (); yann@1: return \"\"; yann@1: } yann@1: - strcpy (pattern, \"stmfd\\t%m0!, {%1\"); yann@1: - for (i = 1; i < XVECLEN (operands[2], 0); i++) yann@1: + if (XVECLEN (operands[2], 0) > 1) yann@1: { yann@1: - strcat (pattern, \", %|\"); yann@1: - strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), yann@1: + strcpy (pattern, \"stmfd\\t%m0!, {%1\"); yann@1: + for (i = 1; i < XVECLEN (operands[2], 0); i++) yann@1: + { yann@1: + strcat (pattern, \", %|\"); yann@1: + strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), yann@1: 0))]); yann@1: + } yann@1: + strcat (pattern, \"}\"); yann@1: + output_asm_insn (pattern, operands); yann@1: } yann@1: - strcat (pattern, \"}\"); yann@1: - output_asm_insn (pattern, operands); yann@1: + else yann@1: + output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands); yann@1: return \"\"; yann@1: }" yann@1: [(set_attr "type" "store4")]) yann@1: diff -urN gcc-2.95.3-orig/gcc/config/arm/elf.h gcc-2.95.3/gcc/config/arm/elf.h yann@1: --- gcc-2.95.3-orig/gcc/config/arm/elf.h Mon May 31 10:21:53 1999 yann@1: +++ gcc-2.95.3/gcc/config/arm/elf.h Fri Jul 20 19:39:11 2001 yann@1: @@ -167,15 +167,6 @@ yann@1: #define MULTILIB_DEFAULTS { "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork" } yann@1: #endif yann@1: yann@1: -/* Setting this to 32 produces more efficient code, but the value set in previous yann@1: - versions of this toolchain was 8, which produces more compact structures. The yann@1: - command line option -mstructure_size_boundary= can be used to change this yann@1: - value. */ yann@1: -#undef STRUCTURE_SIZE_BOUNDARY yann@1: -#define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary yann@1: - yann@1: -extern int arm_structure_size_boundary; yann@1: - yann@1: /* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS yann@1: is a valid machine specific attribute for DECL. yann@1: The attributes in ATTRIBUTES have previously been assigned to DECL. */ yann@1: diff -urN gcc-2.95.3-orig/gcc/config/arm/linux-gas.h gcc-2.95.3/gcc/config/arm/linux-gas.h yann@1: --- gcc-2.95.3-orig/gcc/config/arm/linux-gas.h Mon Feb 22 17:47:57 1999 yann@1: +++ gcc-2.95.3/gcc/config/arm/linux-gas.h Fri Jul 20 19:39:11 2001 yann@1: @@ -1,6 +1,6 @@ yann@1: /* Definitions of target machine for GNU compiler. yann@1: ARM Linux-based GNU systems version. yann@1: - Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. yann@1: + Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. yann@1: Contributed by Russell King . yann@1: yann@1: This file is part of GNU CC. yann@1: @@ -79,5 +79,7 @@ yann@1: register unsigned long _beg __asm ("a1") = (unsigned long) (BEG); \ yann@1: register unsigned long _end __asm ("a2") = (unsigned long) (END); \ yann@1: register unsigned long _flg __asm ("a3") = 0; \ yann@1: - __asm __volatile ("swi 0x9f0002"); \ yann@1: + __asm __volatile ("swi 0x9f0002 @ sys_cacheflush" \ yann@1: + : "=r" (_beg) \ yann@1: + : "0" (_beg), "r" (_end), "r" (_flg)); \ yann@1: } yann@1: diff -urN gcc-2.95.3-orig/gcc/config/arm/t-linux gcc-2.95.3/gcc/config/arm/t-linux yann@1: --- gcc-2.95.3-orig/gcc/config/arm/t-linux Fri Mar 26 16:30:20 1999 yann@1: +++ gcc-2.95.3/gcc/config/arm/t-linux Fri Jul 20 20:46:19 2001 yann@1: @@ -1,6 +1,6 @@ yann@1: # Just for these, we omit the frame pointer since it makes such a big yann@1: # difference. It is then pointless adding debugging. yann@1: -TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC yann@1: +TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fPIC yann@1: LIBGCC2_DEBUG_CFLAGS = -g0 yann@1: yann@1: # Don't build enquire yann@1: diff -urN gcc-2.95.3-orig/gcc/final.c gcc-2.95.3/gcc/final.c yann@1: --- gcc-2.95.3-orig/gcc/final.c Mon Mar 12 13:07:59 2001 yann@1: +++ gcc-2.95.3/gcc/final.c Fri Jul 20 19:39:11 2001 yann@1: @@ -3652,8 +3652,9 @@ yann@1: yann@1: output_addr_const (file, XEXP (x, 0)); yann@1: fprintf (file, "-"); yann@1: - if (GET_CODE (XEXP (x, 1)) == CONST_INT yann@1: - && INTVAL (XEXP (x, 1)) < 0) yann@1: + if ((GET_CODE (XEXP (x, 1)) == CONST_INT yann@1: + && INTVAL (XEXP (x, 1)) < 0) yann@1: + || GET_CODE (XEXP (x, 1)) != CONST_INT) yann@1: { yann@1: fprintf (file, ASM_OPEN_PAREN); yann@1: output_addr_const (file, XEXP (x, 1)); yann@1: diff -urN gcc-2.95.3-orig/gcc/function.c gcc-2.95.3/gcc/function.c yann@1: --- gcc-2.95.3-orig/gcc/function.c Thu Jan 25 15:03:15 2001 yann@1: +++ gcc-2.95.3/gcc/function.c Fri Jul 20 19:39:10 2001 yann@1: @@ -3053,6 +3053,105 @@ yann@1: extracted by usage MEM with narrower mode. */ yann@1: static rtx purge_addressof_replacements; yann@1: yann@1: +/* Return 1 if X and Y are identical-looking rtx's. yann@1: + This is the Lisp function EQUAL for rtx arguments. */ yann@1: + yann@1: +int yann@1: +rtx_equal_for_addressof_p (x, y) yann@1: + rtx x, y; yann@1: +{ yann@1: + register int i; yann@1: + register int j; yann@1: + register enum rtx_code code; yann@1: + register char *fmt; yann@1: + yann@1: + if (x == y) yann@1: + return 1; yann@1: + if (x == 0 || y == 0) yann@1: + return 0; yann@1: + yann@1: + code = GET_CODE (x); yann@1: + /* Rtx's of different codes cannot be equal. */ yann@1: + if (code != GET_CODE (y)) yann@1: + return 0; yann@1: + yann@1: + /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. yann@1: + (REG:SI x) and (REG:HI x) are NOT equivalent. yann@1: + But (MEM:SI x) and (MEM:HI x) are equivalent for our purposes. */ yann@1: + yann@1: + if (code != MEM && (GET_MODE (x) != GET_MODE (y))) yann@1: + return 0; yann@1: + yann@1: + /* REG, LABEL_REF, and SYMBOL_REF can be compared nonrecursively. */ yann@1: + yann@1: + if (code == REG) yann@1: + return REGNO (x) == REGNO (y); yann@1: + else if (code == LABEL_REF) yann@1: + return XEXP (x, 0) == XEXP (y, 0); yann@1: + else if (code == SYMBOL_REF) yann@1: + return XSTR (x, 0) == XSTR (y, 0); yann@1: + else if (code == SCRATCH || code == CONST_DOUBLE) yann@1: + return 0; yann@1: + yann@1: + /* Compare the elements. If any pair of corresponding elements yann@1: + fail to match, return 0 for the whole things. */ yann@1: + yann@1: + fmt = GET_RTX_FORMAT (code); yann@1: + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) yann@1: + { yann@1: + switch (fmt[i]) yann@1: + { yann@1: + case 'w': yann@1: + if (XWINT (x, i) != XWINT (y, i)) yann@1: + return 0; yann@1: + break; yann@1: + yann@1: + case 'n': yann@1: + case 'i': yann@1: + if (XINT (x, i) != XINT (y, i)) yann@1: + return 0; yann@1: + break; yann@1: + yann@1: + case 'V': yann@1: + case 'E': yann@1: + /* Two vectors must have the same length. */ yann@1: + if (XVECLEN (x, i) != XVECLEN (y, i)) yann@1: + return 0; yann@1: + yann@1: + /* And the corresponding elements must match. */ yann@1: + for (j = 0; j < XVECLEN (x, i); j++) yann@1: + if (rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0) yann@1: + return 0; yann@1: + break; yann@1: + yann@1: + case 'e': yann@1: + if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0) yann@1: + return 0; yann@1: + break; yann@1: + yann@1: + case 'S': yann@1: + case 's': yann@1: + if (strcmp (XSTR (x, i), XSTR (y, i))) yann@1: + return 0; yann@1: + break; yann@1: + yann@1: + case 'u': yann@1: + /* These are just backpointers, so they don't matter. */ yann@1: + break; yann@1: + yann@1: + case '0': yann@1: + break; yann@1: + yann@1: + /* It is believed that rtx's at this level will never yann@1: + contain anything but integers and other rtx's, yann@1: + except for within LABEL_REFs and SYMBOL_REFs. */ yann@1: + default: yann@1: + abort (); yann@1: + } yann@1: + } yann@1: + return 1; yann@1: +} yann@1: + yann@1: /* Helper function for purge_addressof. See if the rtx expression at *LOC yann@1: in INSN needs to be changed. If FORCE, always put any ADDRESSOFs into yann@1: the stack. */ yann@1: @@ -3133,7 +3232,7 @@ yann@1: for (tem = purge_bitfield_addressof_replacements; yann@1: tem != NULL_RTX; yann@1: tem = XEXP (XEXP (tem, 1), 1)) yann@1: - if (rtx_equal_p (x, XEXP (tem, 0))) yann@1: + if (rtx_equal_for_addressof_p (x, XEXP (tem, 0))) yann@1: { yann@1: *loc = XEXP (XEXP (tem, 1), 0); yann@1: return; yann@1: @@ -3143,7 +3242,7 @@ yann@1: for (tem = purge_addressof_replacements; yann@1: tem != NULL_RTX; yann@1: tem = XEXP (XEXP (tem, 1), 1)) yann@1: - if (rtx_equal_p (XEXP (x, 0), XEXP (tem, 0))) yann@1: + if (rtx_equal_for_addressof_p (XEXP (x, 0), XEXP (tem, 0))) yann@1: { yann@1: rtx z = XEXP (XEXP (tem, 1), 0); yann@1: yann@1: diff -urN gcc-2.95.3-orig/gcc/jump.c gcc-2.95.3/gcc/jump.c yann@1: --- gcc-2.95.3-orig/gcc/jump.c Thu Oct 21 08:24:03 1999 yann@1: +++ gcc-2.95.3/gcc/jump.c Fri Jul 20 19:39:10 2001 yann@1: @@ -115,7 +115,7 @@ yann@1: static rtx delete_unreferenced_labels PROTO((rtx)); yann@1: static void delete_noop_moves PROTO((rtx)); yann@1: static int calculate_can_reach_end PROTO((rtx, int, int)); yann@1: -static int duplicate_loop_exit_test PROTO((rtx)); yann@1: +static int duplicate_loop_exit_test PROTO((rtx, int)); yann@1: static void find_cross_jump PROTO((rtx, rtx, int, rtx *, rtx *)); yann@1: static void do_cross_jump PROTO((rtx, rtx, rtx)); yann@1: static int jump_back_p PROTO((rtx, rtx)); yann@1: @@ -338,7 +338,7 @@ yann@1: && simplejump_p (temp1)) yann@1: { yann@1: temp = PREV_INSN (insn); yann@1: - if (duplicate_loop_exit_test (insn)) yann@1: + if (duplicate_loop_exit_test (insn, after_regscan)) yann@1: { yann@1: changed = 1; yann@1: next = NEXT_INSN (temp); yann@1: @@ -2548,8 +2548,9 @@ yann@1: values of regno_first_uid and regno_last_uid. */ yann@1: yann@1: static int yann@1: -duplicate_loop_exit_test (loop_start) yann@1: +duplicate_loop_exit_test (loop_start, after_regscan) yann@1: rtx loop_start; yann@1: + int after_regscan; yann@1: { yann@1: rtx insn, set, reg, p, link; yann@1: rtx copy = 0, first_copy = 0; yann@1: @@ -2662,6 +2663,9 @@ yann@1: reg_map[REGNO (reg)] = gen_reg_rtx (GET_MODE (reg)); yann@1: } yann@1: } yann@1: + yann@1: + if (after_regscan) yann@1: + reg_scan_update (exitcode, lastexit, max_reg); yann@1: yann@1: /* Now copy each insn. */ yann@1: for (insn = exitcode; insn != lastexit; insn = NEXT_INSN (insn)) yann@1: diff -urN gcc-2.95.3-orig/gcc/varasm.c gcc-2.95.3/gcc/varasm.c yann@1: --- gcc-2.95.3-orig/gcc/varasm.c Mon Feb 19 15:02:02 2001 yann@1: +++ gcc-2.95.3/gcc/varasm.c Fri Jul 20 19:39:11 2001 yann@1: @@ -3286,7 +3286,10 @@ yann@1: value->un.addr.offset = - INTVAL (XEXP (x, 1)); yann@1: } yann@1: else yann@1: - abort (); yann@1: + { yann@1: + value->un.addr.base = x; yann@1: + value->un.addr.offset = 0; yann@1: + } yann@1: break; yann@1: yann@1: default: