2012-10-22 Hans-Peter Nilsson <hp@bitrange.com>
+ * config/mmix/mmix.md ("nonlocal_goto_receiver"): Refer to the
+ frame-pointer as an operand.
+ ("*nonlocal_goto_receiver_expanded"): Ditto. Use
+ mmix_output_register_setting instead of naked output_asm_insn for
+ the offset from the frame-pointer to the saved rO.
+ * config/mmix/mmix.c (mmix_output_register_setting): Emit NEGU for
+ values -255..0.
+ * config/mmix/predicates.md ("frame_pointer_operand"): New.
+ * config/mmix/constraints.md ("Yf"): New.
+
* stmt.c (expand_nl_goto_receiver): Remove almost-copy of
expand_builtin_setjmp_receiver.
(expand_label): Adjust, call expand_builtin_setjmp_receiver
;; of "pop 0,0" until rO equals the saved value. (If it goes lower, we
;; should die with a trap.)
(define_expand "nonlocal_goto_receiver"
- [(parallel [(unspec_volatile [(const_int 0)] 1)
+ [(parallel [(unspec_volatile [(match_dup 1)] 1)
(clobber (scratch:DI))
(clobber (reg:DI MMIX_rJ_REGNUM))])
(set (reg:DI MMIX_rJ_REGNUM) (match_dup 0))]
= mmix_get_hard_reg_initial_val (Pmode,
MMIX_INCOMING_RETURN_ADDRESS_REGNUM);
+ /* We need the frame-pointer to be live or the equivalent
+ expression, so refer to in in the pattern. We can't use a MEM
+ (that may contain out-of-range offsets in the final expression)
+ for fear that middle-end will legitimize it or replace the address
+ using temporary registers (which are not revived at this point). */
+ operands[1] = frame_pointer_rtx;
+
/* Mark this function as containing a landing-pad. */
cfun->machine->has_landing_pad = 1;
}")
;; address and re-use them after the register stack unwind, so it's best
;; to form the address ourselves.
(define_insn "*nonlocal_goto_receiver_expanded"
- [(unspec_volatile [(const_int 0)] 1)
+ [(unspec_volatile [(match_operand:DI 1 "frame_pointer_operand" "Yf")] 1)
(clobber (match_scratch:DI 0 "=&r"))
(clobber (reg:DI MMIX_rJ_REGNUM))]
""
{
- rtx temp_reg = operands[0];
- rtx my_operands[2];
- HOST_WIDEST_INT offs;
+ rtx my_operands[3];
const char *my_template
= "GETA $255,0f\;PUT rJ,$255\;LDOU $255,%a0\n\
0:\;GET %1,rO\;CMPU %1,%1,$255\;BNP %1,1f\;POP 0,0\n1:";
- my_operands[1] = temp_reg;
+ my_operands[1] = operands[0];
+ my_operands[2] = GEN_INT (-MMIX_fp_rO_OFFSET);
- /* If we have a frame-pointer (hence unknown stack-pointer offset),
- just use the frame-pointer and the known offset. */
- if (frame_pointer_needed)
+ if (operands[1] == hard_frame_pointer_rtx)
{
- my_operands[0] = GEN_INT (-MMIX_fp_rO_OFFSET);
-
- output_asm_insn ("NEGU %1,0,%0", my_operands);
- my_operands[0] = gen_rtx_PLUS (Pmode, frame_pointer_rtx, temp_reg);
+ mmix_output_register_setting (asm_out_file, REGNO (operands[0]),
+ MMIX_fp_rO_OFFSET, 1);
+ my_operands[0]
+ = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, operands[0]);
}
else
{
- /* We know the fp-based offset, so "eliminate" it to be sp-based. */
- offs
- = (mmix_initial_elimination_offset (MMIX_FRAME_POINTER_REGNUM,
- MMIX_STACK_POINTER_REGNUM)
- + MMIX_fp_rO_OFFSET);
+ HOST_WIDEST_INT offs = INTVAL (XEXP (operands[1], 1));
+ offs += MMIX_fp_rO_OFFSET;
- if (offs >= 0 && offs <= 255)
+ if (insn_const_int_ok_for_constraint (offs, CONSTRAINT_I))
my_operands[0]
= gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offs));
else
{
- mmix_output_register_setting (asm_out_file, REGNO (temp_reg),
+ mmix_output_register_setting (asm_out_file, REGNO (operands[0]),
offs, 1);
- my_operands[0] = gen_rtx_PLUS (Pmode, stack_pointer_rtx, temp_reg);
+ my_operands[0]
+ = gen_rtx_PLUS (Pmode, stack_pointer_rtx, operands[0]);
}
}