From: Michael Meissner Date: Sat, 29 Jun 1996 11:28:52 +0000 (+0000) Subject: Fix int<->floating point conversion routines X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a7df97e69d2ec38647ca8eac2126062603a908ab;p=gcc.git Fix int<->floating point conversion routines From-SVN: r12379 --- diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 5a097d69449..ea35f4c59fe 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -36,6 +36,7 @@ Boston, MA 02111-1307, USA. */ #include "expr.h" #include "obstack.h" #include "tree.h" +#include "function.h" #ifndef TARGET_NO_PROTOTYPE #define TARGET_NO_PROTOTYPE 0 @@ -2083,6 +2084,66 @@ rs6000_finalize_pic () } } + +/* Define the structure for the machine field in struct function. */ +struct machine_function +{ + int sysv_varargs_p; + int save_toc_p; + int fpmem_size; + int fpmem_offset; +}; + +/* Functions to save and restore rs6000_fpmem_size. + These will be called, via pointer variables, + from push_function_context and pop_function_context. */ + +void +rs6000_save_machine_status (p) + struct function *p; +{ + struct machine_function *machine = + (struct machine_function *) xmalloc (sizeof (struct machine_function)); + + p->machine = machine; + machine->sysv_varargs_p = rs6000_sysv_varargs_p; + machine->save_toc_p = rs6000_save_toc_p; + machine->fpmem_size = rs6000_fpmem_size; + machine->fpmem_offset = rs6000_fpmem_offset; +} + +void +rs6000_restore_machine_status (p) + struct function *p; +{ + struct machine_function *machine = p->machine; + + rs6000_sysv_varargs_p = machine->sysv_varargs_p; + rs6000_save_toc_p = machine->save_toc_p; + rs6000_fpmem_size = machine->fpmem_size; + rs6000_fpmem_offset = machine->fpmem_offset; + + free (machine); + p->machine = (struct machine_function *)0; +} + +/* Do anything needed before RTL is emitted for each function. */ + +void +rs6000_init_expanders () +{ + /* Reset varargs and save TOC indicator */ + rs6000_sysv_varargs_p = 0; + rs6000_save_toc_p = 0; + rs6000_fpmem_size = 0; + rs6000_fpmem_offset = 0; + pic_offset_table_rtx = (rtx)0; + + /* Arrange to save and restore machine status around nested functions. */ + save_machine_status = rs6000_save_machine_status; + restore_machine_status = rs6000_restore_machine_status; +} + /* Print an operand. Recognize special options, documented below. */ @@ -2720,15 +2781,15 @@ rs6000_makes_calls () +---------------------------------------+ | Parameter save area (P) | 24 +---------------------------------------+ - | Float/int conversion temporary (X) | 24+P + | Alloca space (A) | 24+P +---------------------------------------+ - | Alloca space (A) | 24+P+X + | Local variable space (L) | 24+P+A +---------------------------------------+ - | Local variable space (L) | 24+P+X+A + | Float/int conversion temporary (X) | 24+P+A+L +---------------------------------------+ - | Save area for GP registers (G) | 24+P+X+A+L + | Save area for GP registers (G) | 24+P+A+X+L +---------------------------------------+ - | Save area for FP registers (F) | 24+P+X+A+L+G + | Save area for FP registers (F) | 24+P+A+X+L+G +---------------------------------------+ old SP->| back chain to caller's caller | +---------------------------------------+ @@ -2742,19 +2803,19 @@ rs6000_makes_calls () +---------------------------------------+ | Parameter save area (P) | 8 +---------------------------------------+ - | Float/int conversion temporary (X) | 8+P - +---------------------------------------+ - | Alloca space (A) | 8+P+X - +---------------------------------------+ - | Varargs save area (V) | 8+P+X+A - +---------------------------------------+ - | Local variable space (L) | 8+P+X+A+V + | Alloca space (A) | 8+P + +---------------------------------------+ + | Varargs save area (V) | 8+P+A + +---------------------------------------+ + | Local variable space (L) | 8+P+A+V + +---------------------------------------+ + | Float/int conversion temporary (X) | 8+P+A+V+L +---------------------------------------+ - | saved CR (C) | 8+P+X+A+V+L - +---------------------------------------+ - | Save area for GP registers (G) | 8+P+X+A+V+L+C - +---------------------------------------+ - | Save area for FP registers (F) | 8+P+X+A+V+L+C+G + | saved CR (C) | 8+P+A+V+L+X + +---------------------------------------+ + | Save area for GP registers (G) | 8+P+A+V+L+X+C + +---------------------------------------+ + | Save area for FP registers (F) | 8+P+A+V+L+X+C+G +---------------------------------------+ old SP->| back chain to caller's caller | +---------------------------------------+ @@ -2777,23 +2838,23 @@ rs6000_makes_calls () +---------------------------------------+ | Parameter save area (P) | 24 +---------------------------------------+ - | Float/int conversion temporary (X) | 24+P - +---------------------------------------+ - | Alloca space (A) | 24+P+X - +---------------------------------------+ - | Local variable space (L) | 24+P+X+A - +---------------------------------------+ - | Save area for FP registers (F) | 24+P+X+A+L - +---------------------------------------+ - | Possible alignment area (X) | 24+P+X+A+L+F + | Alloca space (A) | 24+P + +---------------------------------------+ + | Local variable space (L) | 24+P+A + +---------------------------------------+ + | Float/int conversion temporary (X) | 24+P+A+L +---------------------------------------+ - | Save area for GP registers (G) | 24+P+X+A+L+F+X - +---------------------------------------+ - | Save area for CR (C) | 24+P+X+A+L+F+X+G - +---------------------------------------+ - | Save area for TOC (T) | 24+P+X+A+L+F+X+G+C - +---------------------------------------+ - | Save area for LR (R) | 24+P+X+A+L+F+X+G+C+T + | Save area for FP registers (F) | 24+P+A+L+X + +---------------------------------------+ + | Possible alignment area (Y) | 24+P+A+L+X+F + +---------------------------------------+ + | Save area for GP registers (G) | 24+P+A+L+X+F+Y + +---------------------------------------+ + | Save area for CR (C) | 24+P+A+L+X+F+Y+G + +---------------------------------------+ + | Save area for TOC (T) | 24+P+A+L+X+F+Y+G+C + +---------------------------------------+ + | Save area for LR (R) | 24+P+A+L+X+F+Y+G+C+T +---------------------------------------+ old SP->| back chain to caller's caller | +---------------------------------------+ @@ -2941,7 +3002,6 @@ rs6000_stack_info () || info_ptr->total_size > 220); /* Calculate the offsets */ - info_ptr->fpmem_offset = info_ptr->total_size - info_ptr->parm_size; switch (abi) { case ABI_NONE: @@ -2961,9 +3021,9 @@ rs6000_stack_info () case ABI_SOLARIS: info_ptr->fp_save_offset = - info_ptr->fp_size; info_ptr->gp_save_offset = info_ptr->fp_save_offset - info_ptr->gp_size; - info_ptr->cr_save_offset = info_ptr->gp_save_offset - reg_size; - info_ptr->toc_save_offset = info_ptr->cr_save_offset - info_ptr->cr_size; - info_ptr->main_save_offset = info_ptr->toc_save_offset - info_ptr->toc_size; + info_ptr->cr_save_offset = info_ptr->gp_save_offset - info_ptr->cr_size; + info_ptr->toc_save_offset = info_ptr->cr_save_offset - info_ptr->toc_size; + info_ptr->main_save_offset = info_ptr->toc_save_offset - info_ptr->main_size; info_ptr->lr_save_offset = reg_size; break; @@ -2980,6 +3040,9 @@ rs6000_stack_info () break; } + if (info_ptr->fpmem_p) + info_ptr->fpmem_offset = STARTING_FRAME_OFFSET - info_ptr->total_size + info_ptr->vars_size; + /* Zero offsets if we're not saving those registers */ if (!info_ptr->fp_size) info_ptr->fp_save_offset = 0; @@ -3004,9 +3067,7 @@ rs6000_stack_info () else { rs6000_fpmem_size = info_ptr->fpmem_size; - rs6000_fpmem_offset = STACK_DYNAMIC_OFFSET (current_function_decl) - info_ptr->fpmem_size; - if (rs6000_fpmem_offset > 32767) - abort (); + rs6000_fpmem_offset = info_ptr->total_size + info_ptr->fpmem_offset; } return info_ptr; @@ -3792,13 +3853,6 @@ output_epilog (file, size) fputs ("\t.byte 31\n", file); } - /* Reset varargs and save TOC indicator */ - rs6000_sysv_varargs_p = 0; - rs6000_save_toc_p = 0; - rs6000_fpmem_size = 0; - rs6000_fpmem_offset = 0; - pic_offset_table_rtx = (rtx)0; - if (DEFAULT_ABI == ABI_NT) { RS6000_OUTPUT_BASENAME (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index f157f0ec01b..7626eff03c5 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1190,6 +1190,10 @@ extern int rs6000_sysv_varargs_p; /* Align an address */ #define ALIGN(n,a) (((n) + (a) - 1) & ~((a) - 1)) +/* Initialize data used by insn expanders. This is called from + init_emit, once for each function, before code is generated. */ +#define INIT_EXPANDERS rs6000_init_expanders () + /* Size of V.4 varargs area in bytes */ #define RS6000_VARARGS_SIZE \ ((GP_ARG_NUM_REG * (TARGET_32BIT ? 4 : 8)) + (FP_ARG_NUM_REG * 8) + 8) @@ -1197,7 +1201,6 @@ extern int rs6000_sysv_varargs_p; /* Offset of V.4 varargs area */ #define RS6000_VARARGS_OFFSET \ (ALIGN (current_function_outgoing_args_size, 8) \ - + ALIGN (rs6000_fpmem_size, 8) \ + RS6000_SAVE_AREA) /* Offset within stack frame to start allocating local variables at. @@ -1211,7 +1214,6 @@ extern int rs6000_sysv_varargs_p; #define STARTING_FRAME_OFFSET \ (ALIGN (current_function_outgoing_args_size, 8) \ - + ALIGN (rs6000_fpmem_size, 8) \ + RS6000_VARARGS_AREA \ + RS6000_SAVE_AREA) @@ -1223,7 +1225,6 @@ extern int rs6000_sysv_varargs_p; machines. See `function.c' for details. */ #define STACK_DYNAMIC_OFFSET(FUNDECL) \ (ALIGN (current_function_outgoing_args_size, 8) \ - + ALIGN (rs6000_fpmem_size, 8) \ + (STACK_POINTER_OFFSET)) /* If we generate an insn to push BYTES bytes, @@ -3009,6 +3010,7 @@ do { \ extern int flag_pic; extern int optimize; extern int flag_expensive_optimizations; +extern int frame_pointer_needed; /* Declare functions in rs6000.c */ extern void output_options (); @@ -3071,6 +3073,9 @@ extern int addrs_ok_for_quad_peep (); extern enum reg_class secondary_reload_class (); extern int ccr_bit (); extern void rs6000_finalize_pic (); +extern void rs6000_save_machine_status (); +extern void rs6000_restore_machine_status (); +extern void rs6000_init_expanders (); extern void print_operand (); extern void print_operand_address (); extern int first_reg_to_save (); diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index be5c4f354c4..c015c3dfcf7 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -3550,6 +3550,7 @@ (use (match_dup 2)) (use (match_dup 3)) (clobber (match_dup 4)) + (clobber (match_dup 5)) (clobber (reg:DF 76))])] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" " @@ -3557,6 +3558,7 @@ operands[2] = force_reg (SImode, GEN_INT (0x43300000)); operands[3] = force_reg (DFmode, rs6000_float_const (\"4503601774854144\", DFmode)); operands[4] = gen_reg_rtx (SImode); + operands[5] = gen_reg_rtx (Pmode); }") (define_insn "*floatsidf2_internal" @@ -3565,10 +3567,11 @@ (use (match_operand:SI 2 "gpc_reg_operand" "r")) (use (match_operand:DF 3 "gpc_reg_operand" "f")) (clobber (match_operand:SI 4 "gpc_reg_operand" "=r")) + (clobber (match_operand:SI 5 "gpc_reg_operand" "=b")) (clobber (reg:DF 76))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" "#" - [(set_attr "length" "20")]) + [(set_attr "length" "24")]) (define_split [(set (match_operand:DF 0 "gpc_reg_operand" "") @@ -3576,28 +3579,31 @@ (use (match_operand:SI 2 "gpc_reg_operand" "")) (use (match_operand:DF 3 "gpc_reg_operand" "")) (clobber (match_operand:SI 4 "gpc_reg_operand" "")) + (clobber (match_operand:SI 5 "gpc_reg_operand" "")) (clobber (reg:DF 76))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" [(set (match_dup 4) (xor:SI (match_dup 1) - (match_dup 5))) - (set (match_dup 6) - (unspec [(match_dup 4) ;; low word - (reg:SI 1)] 11)) - (set (match_dup 6) - (unspec [(match_dup 2) ;; high word - (reg:SI 1) - (match_dup 6)] 12)) + (match_dup 6))) + (set (match_dup 5) + (unspec [(const_int 0)] 11)) + (set (match_dup 7) + (unspec [(match_dup 4) + (match_dup 5)] 12)) ;; low word + (set (match_dup 7) + (unspec [(match_dup 2) + (match_dup 5) + (match_dup 7)] 13)) ;; high word (set (match_dup 0) - (unspec [(match_dup 6) - (reg:SI 1)] 13)) + (unspec [(match_dup 7) + (match_dup 5)] 14)) (set (match_dup 0) (minus:DF (match_dup 0) (match_dup 3)))] " { - operands[5] = GEN_INT (0x80000000); - operands[6] = gen_rtx (REG, DFmode, FPMEM_REGNUM); + operands[6] = GEN_INT (0x80000000); + operands[7] = gen_rtx (REG, DFmode, FPMEM_REGNUM); }") (define_expand "floatunssidf2" @@ -3605,12 +3611,14 @@ (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" ""))) (use (match_dup 2)) (use (match_dup 3)) + (clobber (match_dup 4)) (clobber (reg:DF 76))])] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" " { operands[2] = force_reg (SImode, GEN_INT (0x43300000)); operands[3] = force_reg (DFmode, rs6000_float_const (\"4503599627370496\", DFmode)); + operands[4] = gen_reg_rtx (Pmode); }") (define_insn "*floatunssidf2_internal" @@ -3618,84 +3626,135 @@ (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r"))) (use (match_operand:SI 2 "gpc_reg_operand" "r")) (use (match_operand:DF 3 "gpc_reg_operand" "f")) + (clobber (match_operand:SI 4 "gpc_reg_operand" "=b")) (clobber (reg:DF 76))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" "#" - [(set_attr "length" "16")]) + [(set_attr "length" "20")]) (define_split [(set (match_operand:DF 0 "gpc_reg_operand" "") (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" ""))) (use (match_operand:SI 2 "gpc_reg_operand" "")) (use (match_operand:DF 3 "gpc_reg_operand" "")) + (clobber (match_operand:SI 4 "gpc_reg_operand" "=b")) (clobber (reg:DF 76))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" [(set (match_dup 4) - (unspec [(match_dup 1) ;; low word - (reg:SI 1)] 11)) - (set (match_dup 4) - (unspec [(match_dup 2) ;; high word - (reg:SI 1) - (reg:DF 76)] 12)) + (unspec [(const_int 0)] 11)) + (set (match_dup 5) + (unspec [(match_dup 1) + (match_dup 4)] 12)) ;; low word + (set (match_dup 5) + (unspec [(match_dup 2) + (match_dup 4) + (match_dup 5)] 13)) ;; high word (set (match_dup 0) - (unspec [(match_dup 4) - (reg:SI 1)] 13)) + (unspec [(match_dup 5) + (reg:SI 1)] 14)) (set (match_dup 0) (minus:DF (match_dup 0) (match_dup 3)))] - "operands[4] = gen_rtx (REG, DFmode, FPMEM_REGNUM);") + "operands[5] = gen_rtx (REG, DFmode, FPMEM_REGNUM);") + +;; Load up scratch register with base address + offset if needed +(define_insn "*floatsidf2_loadaddr" + [(set (match_operand:SI 0 "gpc_reg_operand" "=b") + (unspec [(const_int 0)] 11))] + "TARGET_HARD_FLOAT" + "* +{ + if (rs6000_fpmem_offset > 32760) + { + rtx xop[3]; -;; Note, we list r1 in the unspec, so that the optimizer is not tempted to optimize -;; around an alloca call (the memory address is constructed directly from r1). + xop[0] = operands[0]; + xop[1] = (frame_pointer_needed) ? frame_pointer_rtx : stack_pointer_rtx; + xop[2] = GEN_INT ((rs6000_fpmem_offset >> 16) & 0xffff); + output_asm_insn (\"{cau %0,%2(%1)|addis %0,%1,%2}\", xop); + } + else if (rs6000_fpmem_offset < 0) + abort (); + + return \"\"; +}" + [(set_attr "length" "4")]) (define_insn "*floatsidf2_store1" [(set (reg:DF 76) (unspec [(match_operand:SI 0 "gpc_reg_operand" "r") - (reg:SI 1)] 11))] + (match_operand:SI 1 "gpc_reg_operand" "r")] 12))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" "* { - operands[1] = gen_rtx (MEM, SImode, + rtx indx; + + if (rs6000_fpmem_offset > 32760) + indx = operands[1]; + else if (frame_pointer_needed) + indx = frame_pointer_rtx; + else + indx = stack_pointer_rtx; + + operands[2] = gen_rtx (MEM, SImode, gen_rtx (PLUS, Pmode, - stack_pointer_rtx, - GEN_INT (rs6000_fpmem_offset + indx, + GEN_INT ((rs6000_fpmem_offset & 0xffff) + ((WORDS_BIG_ENDIAN != 0) * 4)))); - return \"{st|stw} %0,%1\"; + return \"{st|stw} %0,%2\"; }" [(set_attr "type" "store")]) (define_insn "*floatsidf2_store2" [(set (reg:DF 76) (unspec [(match_operand:SI 0 "gpc_reg_operand" "r") - (reg:SI 1) - (reg:DF 76)] 12))] + (match_operand:SI 1 "gpc_reg_operand" "r") + (reg:DF 76)] 13))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" "* { - operands[1] = gen_rtx (MEM, SImode, + rtx indx; + + if (rs6000_fpmem_offset > 32760) + indx = operands[1]; + else if (frame_pointer_needed) + indx = frame_pointer_rtx; + else + indx = stack_pointer_rtx; + + operands[2] = gen_rtx (MEM, SImode, gen_rtx (PLUS, Pmode, - stack_pointer_rtx, - GEN_INT (rs6000_fpmem_offset + indx, + GEN_INT ((rs6000_fpmem_offset & 0xffff) + ((WORDS_BIG_ENDIAN == 0) * 4)))); - return \"{st|stw} %0,%1\"; + return \"{st|stw} %0,%2\"; }" [(set_attr "type" "store")]) (define_insn "*floatsidf2_load" [(set (match_operand:DF 0 "gpc_reg_operand" "=f") (unspec [(reg:DF 76) - (reg:SI 1)] 13))] + (match_operand:SI 1 "gpc_reg_operand" "b")] 14))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT" "* { - operands[1] = gen_rtx (MEM, SImode, + rtx indx; + + if (rs6000_fpmem_offset > 32760) + indx = operands[1]; + else if (frame_pointer_needed) + indx = frame_pointer_rtx; + else + indx = stack_pointer_rtx; + + operands[2] = gen_rtx (MEM, SImode, gen_rtx (PLUS, Pmode, - stack_pointer_rtx, + indx, GEN_INT (rs6000_fpmem_offset))); - return \"lfd %0,%1\"; + return \"lfd %0,%2\"; }" [(set_attr "type" "fpload")]) @@ -3703,7 +3762,8 @@ [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") (fix:SI (match_operand:DF 1 "gpc_reg_operand" ""))) (clobber (match_dup 2)) - (clobber (match_dup 3))])] + (clobber (match_dup 3)) + (clobber (match_dup 4))])] "TARGET_HARD_FLOAT" " { @@ -3715,13 +3775,15 @@ } operands[2] = gen_reg_rtx (DImode); - operands[3] = gen_rtx (REG, DImode, FPMEM_REGNUM); + operands[3] = gen_reg_rtx (Pmode); + operands[4] = gen_rtx (REG, DImode, FPMEM_REGNUM); }") (define_insn "*fix_truncdfsi2_internal" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))) (clobber (match_operand:DI 2 "gpc_reg_operand" "=f")) + (clobber (match_operand:SI 3 "gpc_reg_operand" "=b")) (clobber (reg:DI 76))] "TARGET_HARD_FLOAT" "#" @@ -3731,17 +3793,20 @@ [(set (match_operand:SI 0 "gpc_reg_operand" "") (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))) (clobber (match_operand:DI 2 "gpc_reg_operand" "")) + (clobber (match_operand:SI 3 "gpc_reg_operand" "")) (clobber (reg:DI 76))] "TARGET_HARD_FLOAT" [(set (match_dup 2) (sign_extend:DI (fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))) (set (match_dup 3) + (unspec [(const_int 0)] 11)) + (set (match_dup 4) (unspec [(match_dup 2) - (reg:SI 1)] 14)) + (match_dup 3)] 15)) (set (match_operand:SI 0 "gpc_reg_operand" "") - (unspec [(match_dup 3) - (reg:SI 1)] 15))] - "operands[3] = gen_rtx (REG, DImode, FPMEM_REGNUM);") + (unspec [(match_dup 4) + (match_dup 3)] 16))] + "operands[4] = gen_rtx (REG, DImode, FPMEM_REGNUM);") (define_insn "*fctiwz" [(set (match_operand:DI 0 "gpc_reg_operand" "=f") @@ -3753,32 +3818,51 @@ (define_insn "*fix_truncdfsi2_store" [(set (reg:DI 76) (unspec [(match_operand:DI 0 "gpc_reg_operand" "f") - (reg:SI 1)] 14))] + (match_operand:SI 1 "gpc_reg_operand" "b")] 15))] "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT" "* { - operands[1] = gen_rtx (MEM, DFmode, + rtx indx; + + if (rs6000_fpmem_offset > 32760) + indx = operands[1]; + else if (frame_pointer_needed) + indx = frame_pointer_rtx; + else + indx = stack_pointer_rtx; + + operands[2] = gen_rtx (MEM, DFmode, gen_rtx (PLUS, Pmode, - stack_pointer_rtx, - GEN_INT (rs6000_fpmem_offset))); + indx, + GEN_INT ((rs6000_fpmem_offset & 0xffff)))); - return \"stfd %0,%1\"; + return \"stfd %0,%2\"; }" [(set_attr "type" "fpstore")]) (define_insn "*fix_truncdfsi2_load" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (unspec [(reg:DI 76) - (reg:SI 1)] 15))] + (match_operand:SI 1 "gpc_reg_operand" "b")] 16))] "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT" "* { - operands[1] = gen_rtx (MEM, DFmode, + rtx indx; + + if (rs6000_fpmem_offset > 32760) + indx = operands[1]; + else if (frame_pointer_needed) + indx = frame_pointer_rtx; + else + indx = stack_pointer_rtx; + + operands[2] = gen_rtx (MEM, DFmode, gen_rtx (PLUS, Pmode, - stack_pointer_rtx, - GEN_INT (rs6000_fpmem_offset + ((WORDS_BIG_ENDIAN) ? 4 : 0)))); + indx, + GEN_INT ((rs6000_fpmem_offset & 0xffff) + + ((WORDS_BIG_ENDIAN) ? 4 : 0)))); - return \"{l|lwz} %0,%1\"; + return \"{l|lwz} %0,%2\"; }" [(set_attr "type" "load")])