#include "output.h"
#include "basic-block.h"
#include "varray.h"
+#include "reload.h"
#ifdef STACK_REGS
rtx subreg;
if (FP_REG_P (subreg = SUBREG_REG (*pat)))
{
- *pat = FP_MODE_REG (REGNO (subreg) + SUBREG_WORD (*pat),
+ int regno_off = subreg_regno_offset (REGNO (subreg),
+ GET_MODE (subreg),
+ SUBREG_BYTE (*pat),
+ GET_MODE (*pat));
+ *pat = FP_MODE_REG (REGNO (subreg) + regno_off,
GET_MODE (subreg));
default:
return pat;
malformed_asm = 1;
}
else
- reg_used_as_output[REGNO (recog_data.operand[i])] = 1;
+ {
+ int j;
+
+ for (j = 0; j < n_clobbers; j++)
+ if (REGNO (recog_data.operand[i]) == REGNO (clobber_reg[j]))
+ {
+ error_for_asm (insn, "Output constraint %d cannot be specified together with \"%s\" clobber",
+ i, reg_names [REGNO (clobber_reg[j])]);
+ malformed_asm = 1;
+ break;
+ }
+ if (j == n_clobbers)
+ reg_used_as_output[REGNO (recog_data.operand[i])] = 1;
+ }
}
rtx pop_insn, pop_rtx;
int hard_regno;
+ /* For complex types take care to pop both halves. These may survive in
+ CLOBBER and USE expressions. */
+ if (COMPLEX_MODE_P (GET_MODE (reg)))
+ {
+ rtx reg1 = FP_MODE_REG (REGNO (reg), DFmode);
+ rtx reg2 = FP_MODE_REG (REGNO (reg) + 1, DFmode);
+
+ pop_insn = NULL_RTX;
+ if (get_hard_regnum (regstack, reg1) >= 0)
+ pop_insn = emit_pop_insn (insn, regstack, reg1, where);
+ if (get_hard_regnum (regstack, reg2) >= 0)
+ pop_insn = emit_pop_insn (insn, regstack, reg2, where);
+ if (!pop_insn)
+ abort ();
+ return pop_insn;
+ }
+
hard_regno = get_hard_regnum (regstack, reg);
if (hard_regno < FIRST_STACK_REG)
while (tmp != limit)
{
if (GET_CODE (tmp) == CODE_LABEL
+ || GET_CODE (tmp) == CALL_INSN
|| NOTE_INSN_BASIC_BLOCK_P (tmp)
|| (GET_CODE (tmp) == INSN
&& stack_regs_mentioned (tmp)))
stack is not full, and then write the value to memory via
a pop. */
rtx push_rtx, push_insn;
- rtx top_stack_reg = FP_MODE_REG (FIRST_STACK_REG, XFmode);
+ rtx top_stack_reg = FP_MODE_REG (FIRST_STACK_REG, GET_MODE (src));
- push_rtx = gen_movxf (top_stack_reg, top_stack_reg);
+ if (GET_MODE (src) == TFmode)
+ push_rtx = gen_movtf (top_stack_reg, top_stack_reg);
+ else
+ push_rtx = gen_movxf (top_stack_reg, top_stack_reg);
push_insn = emit_insn_before (push_rtx, insn);
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, top_stack_reg,
REG_NOTES (insn));
PATTERN (insn) = pat;
move_for_stack_reg (insn, regstack, pat);
}
+ if (! note && COMPLEX_MODE_P (GET_MODE (*dest))
+ && get_hard_regnum (regstack, FP_MODE_REG (REGNO (*dest), DFmode)) == -1)
+ {
+ pat = gen_rtx_SET (VOIDmode,
+ FP_MODE_REG (REGNO (*dest) + 1, SFmode),
+ nan);
+ PATTERN (insn) = pat;
+ move_for_stack_reg (insn, regstack, pat);
+ }
}
}
break;
case SET:
{
- rtx *src1 = (rtx *) NULL_PTR, *src2;
+ rtx *src1 = (rtx *) 0, *src2;
rtx src1_note, src2_note;
rtx pat_src;
}
}
- /* Care for EH edges specially. The normal return path may return
- a value in st(0), but the EH path will not, and there's no need
- to add popping code to the edge. */
- if (e->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
+ /* Care for non-call EH edges specially. The normal return path have
+ values in registers. These will be popped en masse by the unwind
+ library. */
+ if ((e->flags & (EDGE_EH | EDGE_ABNORMAL_CALL)) == EDGE_EH)
+ target_stack->top = -1;
+
+ /* Other calls may appear to have values live in st(0), but the
+ abnormal return path will not have actually loaded the values. */
+ else if (e->flags & EDGE_ABNORMAL_CALL)
{
/* Assert that the lifetimes are as we expect -- one value
live at st(0) on the end of the source block, and no