mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-24 16:30:53 +08:00
m32c-pragma.c (m32c_register_pragmas): Register the __far address space.
* config/m32c/m32c-pragma.c (m32c_register_pragmas): Register the __far address space. * config/m32c/m32c.h (ADDR_SPACE_FAR): New. Add support for "__far" address space for R8C and M16C processor variants. * config/m32c/m32c.c (m32c_addr_space_legitimate_address_p): New. (far_addr_space_p): New. (encode_pattern_1): Add sign and zero extend support. (m32c_hard_regno_nregs_1): Large pointers in A16 mode are SImode. (m32c_extra_constraint_p2): Add SF constraint. (m32c_legitimate_address_p): Support __far addresses. (m32c_addr_space_pointer_mode): New. (m32c_addr_space_address_mode): New. (m32c_addr_space_legitimate_address_p): New. (m32c_addr_space_legitimize_address): New. (m32c_addr_space_subset_p): New. (m32c_addr_space_convert): New. (conversions): Add __far operand patterns. (m32c_prepare_move): Force constants into registers for __far moves. (m32c_split_move): __far moves are always split. * config/m32c/addsub.md (addsi3_1): Support SImode symbols. * config/m32c/mov.md (mov<mode>_far_op1): New. (mov<mode>_far_op2): New. (movqi_op): Add __far (SF) support. (movhi_op): Likewise. (movsi_splittable): Split A1A0 also. From-SVN: r165865
This commit is contained in:
parent
bf1a7f6635
commit
5fd5d7136e
@ -1,3 +1,32 @@
|
||||
2010-10-22 DJ Delorie <dj@redhat.com>
|
||||
|
||||
* config/m32c/m32c-pragma.c (m32c_register_pragmas): Register the
|
||||
__far address space.
|
||||
* config/m32c/m32c.h (ADDR_SPACE_FAR): New. Add support for
|
||||
"__far" address space for R8C and M16C processor variants.
|
||||
* config/m32c/m32c.c (m32c_addr_space_legitimate_address_p): New.
|
||||
(far_addr_space_p): New.
|
||||
(encode_pattern_1): Add sign and zero extend support.
|
||||
(m32c_hard_regno_nregs_1): Large pointers in A16 mode are SImode.
|
||||
(m32c_extra_constraint_p2): Add SF constraint.
|
||||
(m32c_legitimate_address_p): Support __far addresses.
|
||||
(m32c_addr_space_pointer_mode): New.
|
||||
(m32c_addr_space_address_mode): New.
|
||||
(m32c_addr_space_legitimate_address_p): New.
|
||||
(m32c_addr_space_legitimize_address): New.
|
||||
(m32c_addr_space_subset_p): New.
|
||||
(m32c_addr_space_convert): New.
|
||||
(conversions): Add __far operand patterns.
|
||||
(m32c_prepare_move): Force constants into registers for __far
|
||||
moves.
|
||||
(m32c_split_move): __far moves are always split.
|
||||
* config/m32c/addsub.md (addsi3_1): Support SImode symbols.
|
||||
* config/m32c/mov.md (mov<mode>_far_op1): New.
|
||||
(mov<mode>_far_op2): New.
|
||||
(movqi_op): Add __far (SF) support.
|
||||
(movhi_op): Likewise.
|
||||
(movsi_splittable): Split A1A0 also.
|
||||
|
||||
2010-10-22 Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
|
||||
Andrew Pinski <pinskia@gmail.com>
|
||||
|
||||
|
@ -93,9 +93,17 @@
|
||||
case 1:
|
||||
return \"add.w %X2,%h0\;adcf.w %H0\";
|
||||
case 2:
|
||||
output_asm_insn (\"add.w %X2,%h0\",operands);
|
||||
operands[2]= GEN_INT (INTVAL (operands[2]) >> 16);
|
||||
return \"adc.w %X2,%H0\";
|
||||
if (GET_CODE (operands[2]) == SYMBOL_REF)
|
||||
{
|
||||
output_asm_insn (\"add.w #%%lo(%d2),%h0\",operands);
|
||||
return \"adc.w #%%hi(%d2),%H0\";
|
||||
}
|
||||
else
|
||||
{
|
||||
output_asm_insn (\"add.w %X2,%h0\",operands);
|
||||
operands[2]= GEN_INT (INTVAL (operands[2]) >> 16);
|
||||
return \"adc.w %X2,%H0\";
|
||||
}
|
||||
case 3:
|
||||
return \"add.w %h2,%h0\;adc.w %H2,%H0\";
|
||||
case 4:
|
||||
|
@ -131,4 +131,13 @@ m32c_register_pragmas (void)
|
||||
c_register_pragma ("GCC", "memregs", m32c_pragma_memregs);
|
||||
c_register_pragma (NULL, "ADDRESS", m32c_pragma_address);
|
||||
c_register_pragma (NULL, "address", m32c_pragma_address);
|
||||
|
||||
/* R8C and M16C have 16-bit pointers in a 20-bit address zpace.
|
||||
M32C has 24-bit pointers in a 24-bit address space, so does not
|
||||
need far pointers, but we accept the qualifier anyway, as a
|
||||
no-op. */
|
||||
if (TARGET_A16)
|
||||
c_register_addr_space ("__far", ADDR_SPACE_FAR);
|
||||
else
|
||||
c_register_addr_space ("__far", ADDR_SPACE_GENERIC);
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *);
|
||||
static struct machine_function *m32c_init_machine_status (void);
|
||||
static void m32c_insert_attributes (tree, tree *);
|
||||
static bool m32c_legitimate_address_p (enum machine_mode, rtx, bool);
|
||||
static bool m32c_addr_space_legitimate_address_p (enum machine_mode, rtx, bool, addr_space_t);
|
||||
static rtx m32_function_arg (CUMULATIVE_ARGS *, enum machine_mode
|
||||
const_tree, bool);
|
||||
static bool m32c_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
|
||||
@ -124,6 +125,18 @@ static GTY(()) rtx patternr[30];
|
||||
#define IS_CR_REGNO(regno) ((regno) >= SB_REGNO && (regno) <= PC_REGNO)
|
||||
#define IS_CR_REG(rtx) (GET_CODE (rtx) == REG && IS_CR_REGNO (REGNO (rtx)))
|
||||
|
||||
static int
|
||||
far_addr_space_p (rtx x)
|
||||
{
|
||||
if (GET_CODE (x) != MEM)
|
||||
return 0;
|
||||
#if DEBUG0
|
||||
fprintf(stderr, "\033[35mfar_addr_space: "); debug_rtx(x);
|
||||
fprintf(stderr, " = %d\033[0m\n", MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR);
|
||||
#endif
|
||||
return MEM_ADDR_SPACE (x) == ADDR_SPACE_FAR;
|
||||
}
|
||||
|
||||
/* We do most RTX matching by converting the RTX into a string, and
|
||||
using string compares. This vastly simplifies the logic in many of
|
||||
the functions in this file.
|
||||
@ -166,6 +179,16 @@ encode_pattern_1 (rtx x)
|
||||
case CONST:
|
||||
encode_pattern_1 (XEXP (x, 0));
|
||||
break;
|
||||
case SIGN_EXTEND:
|
||||
*patternp++ = '^';
|
||||
*patternp++ = 'S';
|
||||
encode_pattern_1 (XEXP (x, 0));
|
||||
break;
|
||||
case ZERO_EXTEND:
|
||||
*patternp++ = '^';
|
||||
*patternp++ = 'Z';
|
||||
encode_pattern_1 (XEXP (x, 0));
|
||||
break;
|
||||
case PLUS:
|
||||
*patternp++ = '+';
|
||||
encode_pattern_1 (XEXP (x, 0));
|
||||
@ -553,7 +576,7 @@ m32c_hard_regno_nregs_1 (int regno, enum machine_mode mode)
|
||||
return nregs_table[regno].qi_regs;
|
||||
if (GET_MODE_SIZE (mode) <= 2)
|
||||
return nregs_table[regno].hi_regs;
|
||||
if (regno == A0_REGNO && mode == PSImode && TARGET_A16)
|
||||
if (regno == A0_REGNO && mode == SImode && TARGET_A16)
|
||||
return 2;
|
||||
if ((GET_MODE_SIZE (mode) <= 3 || mode == PSImode) && TARGET_A24)
|
||||
return nregs_table[regno].pi_regs;
|
||||
@ -993,6 +1016,8 @@ m32c_const_ok_for_constraint_p (HOST_WIDE_INT value,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define A0_OR_PSEUDO(x) (IS_REG(x, A0_REGNO) || REGNO (x) >= FIRST_PSEUDO_REGISTER)
|
||||
|
||||
/* Implements EXTRA_CONSTRAINT_STR (see next function too). 'S' is
|
||||
for memory constraints, plus "Rpa" for PARALLEL rtx's we use for
|
||||
call return values. */
|
||||
@ -1000,6 +1025,29 @@ int
|
||||
m32c_extra_constraint_p2 (rtx value, char c ATTRIBUTE_UNUSED, const char *str)
|
||||
{
|
||||
encode_pattern (value);
|
||||
|
||||
if (far_addr_space_p (value))
|
||||
{
|
||||
if (memcmp (str, "SF", 2) == 0)
|
||||
{
|
||||
return ( (RTX_IS ("mr")
|
||||
&& A0_OR_PSEUDO (patternr[1])
|
||||
&& GET_MODE (patternr[1]) == SImode)
|
||||
|| (RTX_IS ("m+^Sri")
|
||||
&& A0_OR_PSEUDO (patternr[4])
|
||||
&& GET_MODE (patternr[4]) == HImode)
|
||||
|| (RTX_IS ("m+^Srs")
|
||||
&& A0_OR_PSEUDO (patternr[4])
|
||||
&& GET_MODE (patternr[4]) == HImode)
|
||||
|| (RTX_IS ("m+^S+ris")
|
||||
&& A0_OR_PSEUDO (patternr[5])
|
||||
&& GET_MODE (patternr[5]) == HImode)
|
||||
|| RTX_IS ("ms")
|
||||
);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memcmp (str, "Sd", 2) == 0)
|
||||
{
|
||||
/* This is the common "src/dest" address */
|
||||
@ -1067,6 +1115,10 @@ m32c_extra_constraint_p2 (rtx value, char c ATTRIBUTE_UNUSED, const char *str)
|
||||
{
|
||||
return r1h_operand (value, QImode);
|
||||
}
|
||||
else if (memcmp (str, "SF", 2) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
gcc_assert (str[0] != 'S');
|
||||
|
||||
@ -1837,6 +1889,11 @@ m32c_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
|
||||
if (CONSTANT_P (x))
|
||||
return 1;
|
||||
|
||||
if (TARGET_A16 && GET_MODE (x) != HImode && GET_MODE (x) != SImode)
|
||||
return 0;
|
||||
if (TARGET_A24 && GET_MODE (x) != PSImode)
|
||||
return 0;
|
||||
|
||||
/* Wide references to memory will be split after reload, so we must
|
||||
ensure that all parts of such splits remain legitimate
|
||||
addresses. */
|
||||
@ -1871,11 +1928,13 @@ m32c_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
|
||||
to please the assembler. */
|
||||
switch (REGNO (patternr[0]))
|
||||
{
|
||||
case A0_REGNO:
|
||||
case A1_REGNO:
|
||||
case SB_REGNO:
|
||||
case FB_REGNO:
|
||||
case SP_REGNO:
|
||||
if (TARGET_A16 && GET_MODE (x) == SImode)
|
||||
return 0;
|
||||
case A0_REGNO:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
@ -1884,6 +1943,10 @@ m32c_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (TARGET_A16 && GET_MODE (x) == SImode)
|
||||
return 0;
|
||||
|
||||
if (RTX_IS ("+ri"))
|
||||
{
|
||||
/* This is more interesting, because different base registers
|
||||
@ -2097,6 +2160,204 @@ m32c_legitimate_constant_p (rtx x ATTRIBUTE_UNUSED)
|
||||
}
|
||||
|
||||
|
||||
/* Return the appropriate mode for a named address pointer. */
|
||||
#undef TARGET_ADDR_SPACE_POINTER_MODE
|
||||
#define TARGET_ADDR_SPACE_POINTER_MODE m32c_addr_space_pointer_mode
|
||||
static enum machine_mode
|
||||
m32c_addr_space_pointer_mode (addr_space_t addrspace)
|
||||
{
|
||||
switch (addrspace)
|
||||
{
|
||||
case ADDR_SPACE_GENERIC:
|
||||
return TARGET_A24 ? PSImode : HImode;
|
||||
case ADDR_SPACE_FAR:
|
||||
return SImode;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the appropriate mode for a named address address. */
|
||||
#undef TARGET_ADDR_SPACE_ADDRESS_MODE
|
||||
#define TARGET_ADDR_SPACE_ADDRESS_MODE m32c_addr_space_address_mode
|
||||
static enum machine_mode
|
||||
m32c_addr_space_address_mode (addr_space_t addrspace)
|
||||
{
|
||||
switch (addrspace)
|
||||
{
|
||||
case ADDR_SPACE_GENERIC:
|
||||
return TARGET_A24 ? PSImode : HImode;
|
||||
case ADDR_SPACE_FAR:
|
||||
return SImode;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Like m32c_legitimate_address_p, except with named addresses. */
|
||||
#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
|
||||
#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
|
||||
m32c_addr_space_legitimate_address_p
|
||||
static bool
|
||||
m32c_addr_space_legitimate_address_p (enum machine_mode mode, rtx x,
|
||||
bool strict, addr_space_t as)
|
||||
{
|
||||
if (as == ADDR_SPACE_FAR)
|
||||
{
|
||||
if (TARGET_A24)
|
||||
return 0;
|
||||
encode_pattern (x);
|
||||
if (RTX_IS ("r"))
|
||||
{
|
||||
if (GET_MODE (x) != SImode)
|
||||
return 0;
|
||||
switch (REGNO (patternr[0]))
|
||||
{
|
||||
case A0_REGNO:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
if (IS_PSEUDO (patternr[0], strict))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (RTX_IS ("+^Sri"))
|
||||
{
|
||||
int rn = REGNO (patternr[3]);
|
||||
HOST_WIDE_INT offs = INTVAL (patternr[4]);
|
||||
if (GET_MODE (patternr[3]) != HImode)
|
||||
return 0;
|
||||
switch (rn)
|
||||
{
|
||||
case A0_REGNO:
|
||||
return (offs >= 0 && offs <= 0xfffff);
|
||||
|
||||
default:
|
||||
if (IS_PSEUDO (patternr[3], strict))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (RTX_IS ("+^Srs"))
|
||||
{
|
||||
int rn = REGNO (patternr[3]);
|
||||
if (GET_MODE (patternr[3]) != HImode)
|
||||
return 0;
|
||||
switch (rn)
|
||||
{
|
||||
case A0_REGNO:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
if (IS_PSEUDO (patternr[3], strict))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (RTX_IS ("+^S+ris"))
|
||||
{
|
||||
int rn = REGNO (patternr[4]);
|
||||
if (GET_MODE (patternr[4]) != HImode)
|
||||
return 0;
|
||||
switch (rn)
|
||||
{
|
||||
case A0_REGNO:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
if (IS_PSEUDO (patternr[4], strict))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (RTX_IS ("s"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
else if (as != ADDR_SPACE_GENERIC)
|
||||
gcc_unreachable ();
|
||||
|
||||
return m32c_legitimate_address_p (mode, x, strict);
|
||||
}
|
||||
|
||||
/* Like m32c_legitimate_address, except with named address support. */
|
||||
#undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
|
||||
#define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS m32c_addr_space_legitimize_address
|
||||
static rtx
|
||||
m32c_addr_space_legitimize_address (rtx x, rtx oldx, enum machine_mode mode,
|
||||
addr_space_t as)
|
||||
{
|
||||
if (as != ADDR_SPACE_GENERIC)
|
||||
{
|
||||
#if DEBUG0
|
||||
fprintf (stderr, "\033[36mm32c_addr_space_legitimize_address for mode %s\033[0m\n", mode_name[mode]);
|
||||
debug_rtx (x);
|
||||
fprintf (stderr, "\n");
|
||||
#endif
|
||||
|
||||
if (GET_CODE (x) != REG)
|
||||
{
|
||||
x = force_reg (SImode, x);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
return m32c_legitimize_address (x, oldx, mode);
|
||||
}
|
||||
|
||||
/* Determine if one named address space is a subset of another. */
|
||||
#undef TARGET_ADDR_SPACE_SUBSET_P
|
||||
#define TARGET_ADDR_SPACE_SUBSET_P m32c_addr_space_subset_p
|
||||
static bool
|
||||
m32c_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
|
||||
{
|
||||
gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_FAR);
|
||||
gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_FAR);
|
||||
|
||||
if (subset == superset)
|
||||
return true;
|
||||
|
||||
else
|
||||
return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_FAR);
|
||||
}
|
||||
|
||||
#undef TARGET_ADDR_SPACE_CONVERT
|
||||
#define TARGET_ADDR_SPACE_CONVERT m32c_addr_space_convert
|
||||
/* Convert from one address space to another. */
|
||||
static rtx
|
||||
m32c_addr_space_convert (rtx op, tree from_type, tree to_type)
|
||||
{
|
||||
addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
|
||||
addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
|
||||
rtx result;
|
||||
|
||||
gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_FAR);
|
||||
gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_FAR);
|
||||
|
||||
if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_FAR)
|
||||
{
|
||||
/* This is unpredictable, as we're truncating off usable address
|
||||
bits. */
|
||||
|
||||
result = gen_reg_rtx (HImode);
|
||||
emit_move_insn (result, simplify_subreg (HImode, op, SImode, 0));
|
||||
return result;
|
||||
}
|
||||
else if (to_as == ADDR_SPACE_FAR && from_as == ADDR_SPACE_GENERIC)
|
||||
{
|
||||
/* This always works. */
|
||||
result = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_zero_extendhisi2 (result, op));
|
||||
return result;
|
||||
}
|
||||
else
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Condition Code Status */
|
||||
|
||||
#undef TARGET_FIXED_CONDITION_CODE_REGS
|
||||
@ -2350,6 +2611,12 @@ const conversions[] = {
|
||||
{ 0, "mr", "z[1]" },
|
||||
{ 0, "m+ri", "3[2]" },
|
||||
{ 0, "m+rs", "3[2]" },
|
||||
{ 0, "m+^Zrs", "5[4]" },
|
||||
{ 0, "m+^Zri", "5[4]" },
|
||||
{ 0, "m+^Z+ris", "7+6[5]" },
|
||||
{ 0, "m+^Srs", "5[4]" },
|
||||
{ 0, "m+^Sri", "5[4]" },
|
||||
{ 0, "m+^S+ris", "7+6[5]" },
|
||||
{ 0, "m+r+si", "4+5[2]" },
|
||||
{ 0, "ms", "1" },
|
||||
{ 0, "mi", "1" },
|
||||
@ -3392,6 +3659,11 @@ m32c_subreg (enum machine_mode outer,
|
||||
int
|
||||
m32c_prepare_move (rtx * operands, enum machine_mode mode)
|
||||
{
|
||||
if (far_addr_space_p (operands[0])
|
||||
&& CONSTANT_P (operands[1]))
|
||||
{
|
||||
operands[1] = force_reg (GET_MODE (operands[0]), operands[1]);
|
||||
}
|
||||
if (TARGET_A16 && mode == PSImode)
|
||||
return m32c_split_move (operands, mode, 1);
|
||||
if ((GET_CODE (operands[0]) == MEM)
|
||||
@ -3497,6 +3769,11 @@ m32c_split_move (rtx * operands, enum machine_mode mode, int split_all)
|
||||
if (m32c_extra_constraint_p (operands[0], 'S', "Ss"))
|
||||
split_all = 3;
|
||||
|
||||
if (TARGET_A16
|
||||
&& (far_addr_space_p (operands[0])
|
||||
|| far_addr_space_p (operands[1])))
|
||||
split_all |= 1;
|
||||
|
||||
/* We don't need to split these. */
|
||||
if (TARGET_A24
|
||||
&& split_all != 3
|
||||
|
@ -567,6 +567,10 @@ typedef struct m32c_cumulative_args
|
||||
|
||||
#define LEGITIMATE_CONSTANT_P(X) m32c_legitimate_constant_p (X)
|
||||
|
||||
/* Address spaces. */
|
||||
#define ADDR_SPACE_FAR 1
|
||||
|
||||
|
||||
/* Condition Code Status */
|
||||
|
||||
#define REVERSIBLE_CC_MODE(MODE) 1
|
||||
|
@ -28,22 +28,45 @@
|
||||
;; example is code like this: a = *b where both a and b are spilled to
|
||||
;; the stack.
|
||||
|
||||
(define_insn "mov<mode>_far_op1"
|
||||
[(set (match_operand:QHI 0 "register_operand" "=Rhi")
|
||||
(mem:QHI (plus:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "Ra0"))
|
||||
(match_operand 2 "immediate_operand" "si"))))
|
||||
]
|
||||
""
|
||||
"lde.<bwl>\t%D2[%1],%0"
|
||||
[(set_attr "flags" "sz")]
|
||||
)
|
||||
|
||||
(define_insn "mov<mode>_far_op2"
|
||||
[(set (mem:QHI (plus:SI (sign_extend:SI (match_operand:HI 0 "register_operand" "Ra0"))
|
||||
(match_operand 1 "immediate_operand" "si")))
|
||||
(match_operand:QHI 2 "register_operand"
|
||||
"=Rhi"))
|
||||
]
|
||||
""
|
||||
"ste.<bwl>\t%2,%D1[%0]"
|
||||
[(set_attr "flags" "sz")]
|
||||
)
|
||||
|
||||
;; Match push/pop before mov.b for passing char as arg,
|
||||
;; e.g. stdlib/efgcvt.c.
|
||||
(define_insn "movqi_op"
|
||||
[(set (match_operand:QI 0 "m32c_nonimmediate_operand"
|
||||
"=Rqi*Rmm, <, RqiSd*Rmm, SdSs, Rqi*Rmm, Sd")
|
||||
"=SF,Rhi*Rmm, Rqi*Rmm, <, RqiSd*Rmm, SdSs, Rqi*Rmm, Sd")
|
||||
(match_operand:QI 1 "m32c_any_operand"
|
||||
"iRqi*Rmm, iRqiSd*Rmm, >, Rqi*Rmm, SdSs, i"))]
|
||||
"Rhi*Rmm,SF, iRqi*Rmm, iRqiSd*Rmm, >, Rqi*Rmm, SdSs, i"))]
|
||||
"m32c_mov_ok (operands, QImode)"
|
||||
"@
|
||||
lde.b\t%1,%0
|
||||
ste.b\t%1,%0
|
||||
mov.b\t%1,%0
|
||||
push.b\t%1
|
||||
pop.b\t%0
|
||||
mov.b\t%1,%0
|
||||
mov.b\t%1,%0
|
||||
mov.b\t%1,%0"
|
||||
[(set_attr "flags" "sz,*,*,sz,sz,sz")]
|
||||
[(set_attr "flags" "sz,sz,sz,*,*,sz,sz,sz")]
|
||||
)
|
||||
|
||||
(define_expand "movqi"
|
||||
@ -56,11 +79,13 @@
|
||||
|
||||
(define_insn "movhi_op"
|
||||
[(set (match_operand:HI 0 "m32c_nonimmediate_operand"
|
||||
"=Rhi*Rmm, Sd, SdSs, *Rcr, RhiSd*Rmm, <, RhiSd*Rmm, <, *Rcr")
|
||||
"=SF,Rhi*Rmm, Rhi*Rmm, Sd, SdSs, *Rcr, RhiSd*Rmm, <, RhiSd*Rmm, <, *Rcr")
|
||||
(match_operand:HI 1 "m32c_any_operand"
|
||||
"iRhi*RmmSdSs, i, Rhi*Rmm, RhiSd*Rmm, *Rcr, iRhiSd*Rmm, >, *Rcr, >"))]
|
||||
" Rhi*Rmm,SF, iRhi*RmmSdSs, i, Rhi*Rmm, RhiSd*Rmm, *Rcr, iRhiSd*Rmm, >, *Rcr, >"))]
|
||||
"m32c_mov_ok (operands, HImode)"
|
||||
"@
|
||||
ste.w\t%1,%0
|
||||
lde.w\t%1,%0
|
||||
mov.w\t%1,%0
|
||||
mov.w\t%1,%0
|
||||
mov.w\t%1,%0
|
||||
@ -70,7 +95,7 @@
|
||||
pop.w\t%0
|
||||
pushc\t%1
|
||||
popc\t%0"
|
||||
[(set_attr "flags" "sz,sz,sz,n,n,n,n,n,n")]
|
||||
[(set_attr "flags" "sz,sz,sz,sz,sz,n,n,n,n,n,n")]
|
||||
)
|
||||
|
||||
(define_expand "movhi"
|
||||
@ -176,11 +201,11 @@
|
||||
|
||||
; All SI moves are split if TARGET_A16
|
||||
(define_insn_and_split "movsi_splittable"
|
||||
[(set (match_operand:SI 0 "m32c_nonimmediate_operand" "=Rsi<*Rmm,RsiSd*Rmm,Ss")
|
||||
(match_operand:SI 1 "m32c_any_operand" "iRsiSd*Rmm,iRsi>*Rmm,Rsi*Rmm"))]
|
||||
[(set (match_operand:SI 0 "m32c_nonimmediate_operand" "=RsiRaa<*Rmm, RsiRaaSd*Rmm, Ss")
|
||||
(match_operand:SI 1 "m32c_any_operand" "iRsiRaaSd*Rmm, iRsiRaa>*Rmm, RsiRaa*Rmm"))]
|
||||
"TARGET_A16"
|
||||
"#"
|
||||
"TARGET_A16 && reload_completed"
|
||||
"TARGET_A16"
|
||||
[(pc)]
|
||||
"m32c_split_move (operands, SImode, 1); DONE;"
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user