if (cfun->machine->need_to_save [10])
{
/* Check for a helper function. */
- helper_n = 7; /* for when the loop below never sees a match. */
+ helper_n = 7; /* For when the loop below never sees a match. */
for (i = 9; i >= 4; i--)
if (!cfun->machine->need_to_save [i])
{
&& ! is_critical_func ()
&& crtl->args.pretend_args_size == 0
/* Calling the helper takes as many bytes as the POP;RET sequence. */
- && helper_n != 1
+ && helper_n > 1
&& !is_eh)
{
emit_insn (gen_epilogue_helper (GEN_INT (helper_n)));
/* Note that the INTVAL is limited in value and length by the conditional above. */
int len = strlen (helper_name) + 4;
helper_const = (char *) xmalloc (len);
- snprintf (helper_const, len, "%s_%ld", helper_name, (int) INTVAL (operands[2]));
+ snprintf (helper_const, len, "%s_%d", helper_name, (int) INTVAL (operands[2]));
}
emit_move_insn (gen_rtx_REG (arg1mode, 12),
fputs (name, file);
}
-#undef TARGET_PRINT_OPERAND
-#define TARGET_PRINT_OPERAND msp430_print_operand
+/* Common code for msp430_print_operand... */
-/* Common code for msp430_print_operand(). */
static void
-msp430_print_operand_raw (FILE * file, rtx op, int letter ATTRIBUTE_UNUSED)
+msp430_print_operand_raw (FILE * file, rtx op)
{
int i;
}
}
+#undef TARGET_PRINT_OPERAND_ADDRESS
+#define TARGET_PRINT_OPERAND_ADDRESS msp430_print_operand_addr
+
+/* Output to stdio stream FILE the assembler syntax for an
+ instruction operand that is a memory reference whose address
+ is ADDR. */
+
+static void
+msp430_print_operand_addr (FILE * file, rtx addr)
+{
+ switch (GET_CODE (addr))
+ {
+ case PLUS:
+ msp430_print_operand_raw (file, XEXP (addr, 1));
+ gcc_assert (REG_P (XEXP (addr, 0)));
+ fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
+ return;
+
+ case REG:
+ fprintf (file, "@");
+ break;
+
+ case CONST:
+ case CONST_INT:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ fprintf (file, "&");
+ break;
+
+ default:
+ break;
+ }
+
+ msp430_print_operand_raw (file, addr);
+}
+
+#undef TARGET_PRINT_OPERAND
+#define TARGET_PRINT_OPERAND msp430_print_operand
+
static void
msp430_print_operand (FILE * file, rtx op, int letter)
{
case GT: fprintf (file, "GE"); break;
case LE: fprintf (file, "L"); break;
default:
- msp430_print_operand_raw (file, op, letter);
+ msp430_print_operand_raw (file, op);
break;
}
return;
case GT: fprintf (file, "L"); break;
case LE: fprintf (file, "GE"); break;
default:
- msp430_print_operand_raw (file, op, letter);
+ msp430_print_operand_raw (file, op);
break;
}
return;
fprintf (file, "%d",
msp430_initial_elimination_offset (ARG_POINTER_REGNUM, STACK_POINTER_REGNUM)
- 2);
- return ;
+ return;
}
switch (GET_CODE (op))
{
case REG:
- msp430_print_operand_raw (file, op, letter);
+ msp430_print_operand_raw (file, op);
break;
case MEM:
addr = XEXP (op, 0);
- switch (GET_CODE (addr))
- {
- case REG:
- fprintf (file, "@%s", reg_names [REGNO (addr)]);
- break;
- case PLUS:
- msp430_print_operand_raw (file, XEXP (addr, 1), letter);
- fprintf (file, "(%s)", reg_names [REGNO (XEXP (addr, 0))]);
- break;
- case CONST:
- case CONST_INT:
- case SYMBOL_REF:
- case LABEL_REF:
- fprintf (file, "&");
- msp430_print_operand_raw (file, addr, letter);
- break;
-
- default:
- print_rtl (file, addr);
- break;
- }
+ msp430_print_operand_addr (file, addr);
break;
case CONST_INT:
case LABEL_REF:
if (letter == 0)
fprintf (file, "#");
- msp430_print_operand_raw (file, op, letter);
+ msp430_print_operand_raw (file, op);
break;
case EQ: fprintf (file, "EQ"); break;
print_rtl (file, op);
break;
}
-
}
\f
)
(define_expand "movsi"
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
+ [(set (match_operand:SI 0 "nonimmediate_operand")
+ (match_operand:SI 1 "general_operand"))]
""
""
)
[(set (match_operand:PSI 0 "register_operand" "=r")
(subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))]
"TARGET_LARGE"
- "PUSH.W %H1 { PUSH.W %1 { POPM.A #1, %0"
+ "PUSH.W\t%H1 { PUSH.W %L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0"
)
;;------------------------------------------------------------
]
""
"@
- ADD %2, %1 ; cy
- ADD%X0 %2, %1 ; cy"
+ ADD\t%2, %1 ; cy
+ ADD%X0\t%2, %1 ; cy"
)
(define_insn "addhi3_cy_i"
]
""
"@
- ADD %2, %1 ; cy
- ADD%X0 %2, %1 ; cy"
+ ADD\t%2, %1 ; cy
+ ADD%X0\t%2, %1 ; cy"
)
; Version of addhi that adds the carry, for SImode adds.
]
""
"@
- ADDC %2, %1
- ADDC%X0 %2, %1"
+ ADDC\t%2, %1
+ ADDC%X0\t%2, %1"
)
; Split an SImode add into two HImode adds, keeping track of the carry
stored in the stack slot will be the value *after* the
stack pointer has been decremented. So allow for that
here. */
- return \"PUSHM.A #1, %1 { ADDX.W #4, @r1 { POPX.W %0 { POPX.W %H0\";
+ return \"PUSHM.A\t#1, %1 { ADDX.W #4, @r1 { POPX.W %L0 { POPX.W %H0 ; get stack pointer into %L0:%H0\";
+ else
+ return \"PUSHM.A\t#1, %1 { POPX.W %L0 { POPX.W %H0 ; move pointer in %1 into reg-pair %L0:%H0\";
+ "
+)
+
+;; We also need to be able to sign-extend pointer types (eg ptrdiff_t).
+;; Since (we assume) pushing a 20-bit value onto the stack zero-extends
+;; it, we use a different method here.
+
+(define_insn "extendpsisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:PSI 1 "register_operand" "r")))]
+ "TARGET_LARGE"
+ "*
+ /* The intention here is that we copy the bottom 16-bits of
+ %1 into %L0 (zeroing the top four bits). Then we copy the
+ entire 20-bits of %1 into %H0 and then arithmetically shift
+ it right by 16 bits, to get the top four bits of the pointer
+ sign-extended in %H0. */
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ return \"MOVX.A\t%1, %H0 { MOV.W %1, %L0 { RPT #16 { RRAX.A %H0 ; sign extend pointer in %1 into %L0:%H0\";
else
- return \"PUSHM.A #1, %1 { POPX.W %0 { POPX.W %H0\";
+ return \"MOV.W \t%1, %L0 { MOVX.A %1, %H0 { RPT #16 { RRAX.A %H0 ; sign extend pointer in %1 into %L0:%H0\";
"
)
(define_expand "call"
[(call:HI (match_operand 0 "")
- (match_operand 1 ""))]
+ (match_operand 1 ""))]
""
""
)
;; placeholder should get expanded into a regular-type epilogue that
;; also does the EH return.
(define_expand "eh_return"
- [(match_operand:HI 0 "" "")]
+ [(match_operand:HI 0 "")]
""
"msp430_expand_eh_return (operands[0]);
emit_jump_insn (gen_msp430_eh_epilogue ());
""
"BIS.W\t%0, %O0(SP)"
)
+
+;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int)))
+;; very late on in the compilation and not splitting it into separate
+;; instructions, so we provide a pattern to support it here.
+(define_insn "andneghi3"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (and:HI (neg:HI (match_operand:HI 1 "register_operand" "r"))
+ (match_operand 2 "immediate_operand" "n")))]
+ ""
+ "*
+ if (REGNO (operands[0]) != REGNO (operands[1]))
+ return \"MOV.W\t%1, %0 { SUB.W #0, %0 { AND.W %2, %0\";
+ else
+ return \"SUB.W\t#0, %0 { AND.W %2, %0\";
+ "
+ )