extend.texi: Document new xstormy16 attribute.
* doc/extend.texi: Document new xstormy16 attribute. * config/stormy16/stormy16.c (xstormy16_splittable_below100_operand): New. (xstormy16_splittable_below100_or_register): New. (combine_bnp): New. (xstormy16_reorg): New. (TARGET_MACHINE_DEPENDENT_REORG): Define. * config/stormy16/stormy16.md (movqi_internal): Make name public. (movhi_internal): Likewise. (cbhranchhi): Likewise. (cbhranchhi_neg): Likewise. (andhi3): Only allow splittable below100 operands. (iorhi3): Likewise. (peephole2): New and/zero_extend->and peephole. (peephole2): New load/ior/save->set1 peephole. (peephole2): New load/and/save->clr1 peephole. (bclrx, bclrx2, bclr7, bclr15): New. (bsetx, bsetx2, bset7, bset15): New. * config/stormy16/stormy16.c (xstormy16_print_operand): Be more liberal about acceptable 'B' masks. * config/stormy16/stormy16-protos.h (xstormy16_asm_output_aligned_common, xstormy16_below100_symbol, xstormy16_below100_operand, xstormy16_below100_or_register, xstormy16_onebit_set_operand, xstormy16_onebit_clr_operand): New. (PREDICATE_CODES): Add new predicates. * config/stormy16/stormy16.c (xstormy16_asm_output_aligned_common, xstormy16_below100_symbol, xstormy16_below100_operand, xstormy16_below100_or_register, xstormy16_onebit_set_operand, xstormy16_onebit_clr_operand): New. (xstormy16_expand_iorqi3, xstormy16_expand_andqi3): New. (xstormy16_legitimate_address_p): Allow below100 symbols. (xstormy16_extra_constraint_p): Add 'W' for below100 operands. (xstormy16_expand_move): Leave below100 operands as-is. (xstormy16_encode_section_info): Encode below100 symbols. (xstormy16_strip_name_encoding): New. (xstormy16_print_operand): Print 'b' as shift mask. (xstormy16_attribute_table): Add below100 attributes. (xstormy16_handle_below100_attribute): New. * config/stormy16/stormy16.h (EXTRA_SECTIONS): add in_bss100. (XSTORMY16_SECTION_FUNCTION): New. (EXTRA_SECTION_FUNCTIONS): Define using the above. (ASM_OUTPUT_ALIGNED_DECL_COMMON, ASM_OUTPUT_ALIGNED_DECL_LOCAL): New. (ASM_OUTPUT_SYMBOL_REF): Handle encoded symbols. (ASM_OUTPUT_LABELREF): Define. * config/stormy16/stormy16.md (movqi_internal): Add below100 support. (movhi_internal): Add below100 support. (andhi3): Add below100 support. (iorhi3): Add below100 support. (iorqi3, iorqi3_internal, andqi3, andqi3_internal): New. From-SVN: r86154
This commit is contained in:
parent
c3f84f61e3
commit
54e9a19d9d
@ -1,3 +1,62 @@
|
||||
2004-08-17 DJ Delorie <dj@redhat.com>
|
||||
|
||||
* doc/extend.texi: Document new xstormy16 attribute.
|
||||
|
||||
* config/stormy16/stormy16.c (xstormy16_splittable_below100_operand): New.
|
||||
(xstormy16_splittable_below100_or_register): New.
|
||||
(combine_bnp): New.
|
||||
(xstormy16_reorg): New.
|
||||
(TARGET_MACHINE_DEPENDENT_REORG): Define.
|
||||
|
||||
|
||||
* config/stormy16/stormy16.md (movqi_internal): Make name public.
|
||||
(movhi_internal): Likewise.
|
||||
(cbhranchhi): Likewise.
|
||||
(cbhranchhi_neg): Likewise.
|
||||
(andhi3): Only allow splittable below100 operands.
|
||||
(iorhi3): Likewise.
|
||||
(peephole2): New and/zero_extend->and peephole.
|
||||
(peephole2): New load/ior/save->set1 peephole.
|
||||
(peephole2): New load/and/save->clr1 peephole.
|
||||
(bclrx, bclrx2, bclr7, bclr15): New.
|
||||
(bsetx, bsetx2, bset7, bset15): New.
|
||||
|
||||
* config/stormy16/stormy16.c (xstormy16_print_operand): Be more
|
||||
liberal about acceptable 'B' masks.
|
||||
|
||||
* config/stormy16/stormy16-protos.h
|
||||
(xstormy16_asm_output_aligned_common, xstormy16_below100_symbol,
|
||||
xstormy16_below100_operand, xstormy16_below100_or_register,
|
||||
xstormy16_onebit_set_operand, xstormy16_onebit_clr_operand): New.
|
||||
(PREDICATE_CODES): Add new predicates.
|
||||
|
||||
* config/stormy16/stormy16.c
|
||||
(xstormy16_asm_output_aligned_common, xstormy16_below100_symbol,
|
||||
xstormy16_below100_operand, xstormy16_below100_or_register,
|
||||
xstormy16_onebit_set_operand, xstormy16_onebit_clr_operand): New.
|
||||
(xstormy16_expand_iorqi3, xstormy16_expand_andqi3): New.
|
||||
(xstormy16_legitimate_address_p): Allow below100 symbols.
|
||||
(xstormy16_extra_constraint_p): Add 'W' for below100 operands.
|
||||
(xstormy16_expand_move): Leave below100 operands as-is.
|
||||
(xstormy16_encode_section_info): Encode below100 symbols.
|
||||
(xstormy16_strip_name_encoding): New.
|
||||
(xstormy16_print_operand): Print 'b' as shift mask.
|
||||
(xstormy16_attribute_table): Add below100 attributes.
|
||||
(xstormy16_handle_below100_attribute): New.
|
||||
|
||||
* config/stormy16/stormy16.h (EXTRA_SECTIONS): add in_bss100.
|
||||
(XSTORMY16_SECTION_FUNCTION): New.
|
||||
(EXTRA_SECTION_FUNCTIONS): Define using the above.
|
||||
(ASM_OUTPUT_ALIGNED_DECL_COMMON, ASM_OUTPUT_ALIGNED_DECL_LOCAL): New.
|
||||
(ASM_OUTPUT_SYMBOL_REF): Handle encoded symbols.
|
||||
(ASM_OUTPUT_LABELREF): Define.
|
||||
|
||||
* config/stormy16/stormy16.md (movqi_internal): Add below100 support.
|
||||
(movhi_internal): Add below100 support.
|
||||
(andhi3): Add below100 support.
|
||||
(iorhi3): Add below100 support.
|
||||
(iorqi3, iorqi3_internal, andqi3, andqi3_internal): New.
|
||||
|
||||
2004-08-17 James E Wilson <wilson@specifixinc.com>
|
||||
|
||||
* config/mips/mips.c (gen_conditional_move): Use GET_MODE (op0) instead
|
||||
|
@ -29,6 +29,13 @@ extern int direct_return (void);
|
||||
extern int xstormy16_interrupt_function_p (void);
|
||||
extern int xstormy16_epilogue_uses (int);
|
||||
extern void xstormy16_function_profiler (void);
|
||||
extern const char *xstormy16_strip_name_encoding (const char *name);
|
||||
extern void bss100_section (void);
|
||||
|
||||
#if defined (TREE_CODE)
|
||||
extern void xstormy16_asm_output_aligned_common (FILE *, tree, const char *,
|
||||
int, int, int);
|
||||
#endif
|
||||
|
||||
#if defined (TREE_CODE) && defined (HAVE_MACHINE_MODES)
|
||||
extern CUMULATIVE_ARGS xstormy16_function_arg_advance
|
||||
@ -56,6 +63,8 @@ extern void xstormy16_print_operand_address (FILE *, rtx);
|
||||
extern void xstormy16_expand_casesi (rtx, rtx, rtx, rtx, rtx);
|
||||
extern void xstormy16_output_addr_vec (FILE *, rtx, rtx);
|
||||
extern void xstormy16_expand_call (rtx, rtx, rtx);
|
||||
extern void xstormy16_expand_iorqi3 (rtx *);
|
||||
extern void xstormy16_expand_andqi3 (rtx *);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_MACHINE_MODES) && defined (RTX_CODE)
|
||||
@ -79,5 +88,12 @@ extern void xstormy16_expand_arith (enum machine_mode, enum rtx_code,
|
||||
extern int shift_operator (rtx, enum machine_mode);
|
||||
extern const char * xstormy16_output_shift (enum machine_mode, enum rtx_code,
|
||||
rtx, rtx, rtx);
|
||||
extern int xstormy16_below100_symbol (rtx, enum machine_mode);
|
||||
extern int xstormy16_below100_operand (rtx, enum machine_mode);
|
||||
extern int xstormy16_splittable_below100_operand (rtx, enum machine_mode);
|
||||
extern int xstormy16_below100_or_register (rtx, enum machine_mode);
|
||||
extern int xstormy16_splittable_below100_or_register (rtx, enum machine_mode);
|
||||
extern int xstormy16_onebit_set_operand (rtx, enum machine_mode);
|
||||
extern int xstormy16_onebit_clr_operand (rtx, enum machine_mode);
|
||||
#endif
|
||||
|
||||
|
@ -549,6 +549,194 @@ xstormy16_preferred_reload_class (rtx x, enum reg_class class)
|
||||
return class;
|
||||
}
|
||||
|
||||
/* Predicate for symbols and addresses that reflect special 8-bit
|
||||
addressing. */
|
||||
int
|
||||
xstormy16_below100_symbol (rtx x,
|
||||
enum machine_mode mode ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (GET_CODE (x) == CONST)
|
||||
x = XEXP (x, 0);
|
||||
if (GET_CODE (x) == PLUS
|
||||
&& GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
x = XEXP (x, 0);
|
||||
if (GET_CODE (x) == SYMBOL_REF)
|
||||
{
|
||||
const char *n = XSTR (x, 0);
|
||||
if (n[0] == '@' && n[1] == 'b' && n[2] == '.')
|
||||
return 1;
|
||||
}
|
||||
if (GET_CODE (x) == CONST_INT)
|
||||
{
|
||||
HOST_WIDE_INT i = INTVAL (x);
|
||||
if ((i >= 0x0000 && i <= 0x00ff)
|
||||
|| (i >= 0x7f00 && i <= 0x7fff))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Predicate for MEMs that can use special 8-bit addressing. */
|
||||
int
|
||||
xstormy16_below100_operand (rtx x, enum machine_mode mode)
|
||||
{
|
||||
if (GET_MODE (x) != mode)
|
||||
return 0;
|
||||
if (GET_CODE (x) == MEM)
|
||||
x = XEXP (x, 0);
|
||||
else if (GET_CODE (x) == SUBREG
|
||||
&& GET_CODE (XEXP (x, 0)) == MEM
|
||||
&& !MEM_VOLATILE_P (XEXP (x, 0)))
|
||||
x = XEXP (XEXP (x, 0), 0);
|
||||
else
|
||||
return 0;
|
||||
if (GET_CODE (x) == CONST_INT)
|
||||
{
|
||||
HOST_WIDE_INT i = INTVAL (x);
|
||||
return (i >= 0x7f00 && i < 0x7fff);
|
||||
}
|
||||
return xstormy16_below100_symbol (x, HImode);
|
||||
}
|
||||
|
||||
/* Likewise, but only for non-volatile MEMs, for patterns where the
|
||||
MEM will get split into smaller sized accesses. */
|
||||
int
|
||||
xstormy16_splittable_below100_operand (rtx x, enum machine_mode mode)
|
||||
{
|
||||
if (GET_CODE (x) == MEM && MEM_VOLATILE_P (x))
|
||||
return 0;
|
||||
return xstormy16_below100_operand (x, mode);
|
||||
}
|
||||
|
||||
int
|
||||
xstormy16_below100_or_register (rtx x, enum machine_mode mode)
|
||||
{
|
||||
return (xstormy16_below100_operand (x, mode)
|
||||
|| register_operand (x, mode));
|
||||
}
|
||||
|
||||
int
|
||||
xstormy16_splittable_below100_or_register (rtx x, enum machine_mode mode)
|
||||
{
|
||||
if (GET_CODE (x) == MEM && MEM_VOLATILE_P (x))
|
||||
return 0;
|
||||
return (xstormy16_below100_operand (x, mode)
|
||||
|| register_operand (x, mode));
|
||||
}
|
||||
|
||||
/* Predicate for constants with exactly one bit set. */
|
||||
int
|
||||
xstormy16_onebit_set_operand (rtx x, enum machine_mode mode)
|
||||
{
|
||||
HOST_WIDE_INT i;
|
||||
if (GET_CODE (x) != CONST_INT)
|
||||
return 0;
|
||||
i = INTVAL (x);
|
||||
if (mode == QImode)
|
||||
i &= 0xff;
|
||||
if (mode == HImode)
|
||||
i &= 0xffff;
|
||||
return exact_log2 (i) != -1;
|
||||
}
|
||||
|
||||
/* Predicate for constants with exactly one bit not set. */
|
||||
int
|
||||
xstormy16_onebit_clr_operand (rtx x, enum machine_mode mode)
|
||||
{
|
||||
HOST_WIDE_INT i;
|
||||
if (GET_CODE (x) != CONST_INT)
|
||||
return 0;
|
||||
i = ~ INTVAL (x);
|
||||
if (mode == QImode)
|
||||
i &= 0xff;
|
||||
if (mode == HImode)
|
||||
i &= 0xffff;
|
||||
return exact_log2 (i) != -1;
|
||||
}
|
||||
|
||||
/* Expand an 8-bit IOR. This either detects the one case we can
|
||||
actually do, or uses a 16-bit IOR. */
|
||||
void
|
||||
xstormy16_expand_iorqi3 (rtx *operands)
|
||||
{
|
||||
rtx in, out, outsub, val;
|
||||
|
||||
out = operands[0];
|
||||
in = operands[1];
|
||||
val = operands[2];
|
||||
|
||||
if (xstormy16_onebit_set_operand (val, QImode))
|
||||
{
|
||||
if (!xstormy16_below100_or_register (in, QImode))
|
||||
in = copy_to_mode_reg (QImode, in);
|
||||
if (!xstormy16_below100_or_register (out, QImode))
|
||||
out = gen_reg_rtx (QImode);
|
||||
emit_insn (gen_iorqi3_internal (out, in, val));
|
||||
if (out != operands[0])
|
||||
emit_move_insn (operands[0], out);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GET_CODE (in) != REG)
|
||||
in = copy_to_mode_reg (QImode, in);
|
||||
if (GET_CODE (val) != REG
|
||||
&& GET_CODE (val) != CONST_INT)
|
||||
val = copy_to_mode_reg (QImode, val);
|
||||
if (GET_CODE (out) != REG)
|
||||
out = gen_reg_rtx (QImode);
|
||||
|
||||
in = simplify_gen_subreg (HImode, in, QImode, 0);
|
||||
outsub = simplify_gen_subreg (HImode, out, QImode, 0);
|
||||
if (GET_CODE (val) != CONST_INT)
|
||||
val = simplify_gen_subreg (HImode, val, QImode, 0);
|
||||
|
||||
emit_insn (gen_iorhi3 (outsub, in, val));
|
||||
|
||||
if (out != operands[0])
|
||||
emit_move_insn (operands[0], out);
|
||||
}
|
||||
|
||||
/* Likewise, for AND. */
|
||||
void
|
||||
xstormy16_expand_andqi3 (rtx *operands)
|
||||
{
|
||||
rtx in, out, outsub, val;
|
||||
|
||||
out = operands[0];
|
||||
in = operands[1];
|
||||
val = operands[2];
|
||||
|
||||
if (xstormy16_onebit_clr_operand (val, QImode))
|
||||
{
|
||||
if (!xstormy16_below100_or_register (in, QImode))
|
||||
in = copy_to_mode_reg (QImode, in);
|
||||
if (!xstormy16_below100_or_register (out, QImode))
|
||||
out = gen_reg_rtx (QImode);
|
||||
emit_insn (gen_andqi3_internal (out, in, val));
|
||||
if (out != operands[0])
|
||||
emit_move_insn (operands[0], out);
|
||||
return;
|
||||
}
|
||||
|
||||
if (GET_CODE (in) != REG)
|
||||
in = copy_to_mode_reg (QImode, in);
|
||||
if (GET_CODE (val) != REG
|
||||
&& GET_CODE (val) != CONST_INT)
|
||||
val = copy_to_mode_reg (QImode, val);
|
||||
if (GET_CODE (out) != REG)
|
||||
out = gen_reg_rtx (QImode);
|
||||
|
||||
in = simplify_gen_subreg (HImode, in, QImode, 0);
|
||||
outsub = simplify_gen_subreg (HImode, out, QImode, 0);
|
||||
if (GET_CODE (val) != CONST_INT)
|
||||
val = simplify_gen_subreg (HImode, val, QImode, 0);
|
||||
|
||||
emit_insn (gen_andhi3 (outsub, in, val));
|
||||
|
||||
if (out != operands[0])
|
||||
emit_move_insn (operands[0], out);
|
||||
}
|
||||
|
||||
#define LEGITIMATE_ADDRESS_INTEGER_P(X, OFFSET) \
|
||||
(GET_CODE (X) == CONST_INT \
|
||||
&& (unsigned HOST_WIDE_INT) (INTVAL (X) + (OFFSET) + 2048) < 4096)
|
||||
@ -579,6 +767,9 @@ xstormy16_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
|
||||
if (GET_CODE (x) == REG && REGNO_OK_FOR_BASE_P (REGNO (x))
|
||||
&& (! strict || REGNO (x) < FIRST_PSEUDO_REGISTER))
|
||||
return 1;
|
||||
|
||||
if (xstormy16_below100_symbol(x, mode))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -668,6 +859,9 @@ xstormy16_extra_constraint_p (rtx x, int c)
|
||||
return (GET_CODE (x) == CONST_INT
|
||||
&& (INTVAL (x) == 0));
|
||||
|
||||
case 'W':
|
||||
return xstormy16_below100_operand(x, GET_MODE(x));
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -868,6 +1062,7 @@ xstormy16_expand_move (enum machine_mode mode, rtx dest, rtx src)
|
||||
&& GET_CODE (dest) == MEM
|
||||
&& (GET_CODE (XEXP (dest, 0)) != CONST_INT
|
||||
|| ! xstormy16_legitimate_address_p (mode, XEXP (dest, 0), 0))
|
||||
&& ! xstormy16_below100_operand (dest, mode)
|
||||
&& GET_CODE (src) != REG
|
||||
&& GET_CODE (src) != SUBREG)
|
||||
src = copy_to_mode_reg (mode, src);
|
||||
@ -1489,6 +1684,119 @@ xstormy16_asm_output_mi_thunk (FILE *file,
|
||||
putc ('\n', file);
|
||||
}
|
||||
|
||||
/* The purpose of this function is to override the default behavior of
|
||||
BSS objects. Normally, they go into .bss or .sbss via ".common"
|
||||
directives, but we need to override that and put them in
|
||||
.bss_below100. We can't just use a section override (like we do
|
||||
for .data_below100), because that makes them initialized rather
|
||||
than uninitialized. */
|
||||
void
|
||||
xstormy16_asm_output_aligned_common (FILE *stream,
|
||||
tree decl ATTRIBUTE_UNUSED,
|
||||
const char *name,
|
||||
int size,
|
||||
int align,
|
||||
int global)
|
||||
{
|
||||
if (name[0] == '@' && name[2] == '.')
|
||||
{
|
||||
const char *op = 0;
|
||||
switch (name[1])
|
||||
{
|
||||
case 'b':
|
||||
bss100_section();
|
||||
op = "space";
|
||||
break;
|
||||
}
|
||||
if (op)
|
||||
{
|
||||
const char *name2;
|
||||
int p2align = 0;
|
||||
|
||||
while (align > 8)
|
||||
{
|
||||
align /= 2;
|
||||
p2align ++;
|
||||
}
|
||||
name2 = xstormy16_strip_name_encoding (name);
|
||||
if (global)
|
||||
fprintf (stream, "\t.globl\t%s\n", name2);
|
||||
if (p2align)
|
||||
fprintf (stream, "\t.p2align %d\n", p2align);
|
||||
fprintf (stream, "\t.type\t%s, @object\n", name2);
|
||||
fprintf (stream, "\t.size\t%s, %d\n", name2, size);
|
||||
fprintf (stream, "%s:\n\t.%s\t%d\n", name2, op, size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!global)
|
||||
{
|
||||
fprintf (stream, "\t.local\t");
|
||||
assemble_name (stream, name);
|
||||
fprintf (stream, "\n");
|
||||
}
|
||||
fprintf (stream, "\t.comm\t");
|
||||
assemble_name (stream, name);
|
||||
fprintf (stream, ",%u,%u\n", size, align);
|
||||
}
|
||||
|
||||
/* Mark symbols with the "below100" attribute so that we can use the
|
||||
special addressing modes for them. */
|
||||
|
||||
static void
|
||||
xstormy16_encode_section_info (tree decl,
|
||||
rtx r,
|
||||
int first ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (TREE_CODE (decl) == VAR_DECL
|
||||
&& (lookup_attribute ("below100", DECL_ATTRIBUTES (decl))
|
||||
|| lookup_attribute ("BELOW100", DECL_ATTRIBUTES (decl))))
|
||||
{
|
||||
const char *newsection = 0;
|
||||
char *newname;
|
||||
tree idp;
|
||||
rtx rtlname, rtl;
|
||||
const char *oldname;
|
||||
|
||||
rtl = r;
|
||||
rtlname = XEXP (rtl, 0);
|
||||
if (GET_CODE (rtlname) == SYMBOL_REF)
|
||||
oldname = XSTR (rtlname, 0);
|
||||
else if (GET_CODE (rtlname) == MEM
|
||||
&& GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
|
||||
oldname = XSTR (XEXP (rtlname, 0), 0);
|
||||
else
|
||||
abort ();
|
||||
|
||||
if (DECL_INITIAL (decl))
|
||||
{
|
||||
newsection = ".data_below100";
|
||||
DECL_SECTION_NAME (decl) = build_string (strlen (newsection), newsection);
|
||||
}
|
||||
|
||||
newname = alloca (strlen (oldname) + 4);
|
||||
sprintf (newname, "@b.%s", oldname);
|
||||
idp = get_identifier (newname);
|
||||
XEXP (rtl, 0) =
|
||||
gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
xstormy16_strip_name_encoding (const char *name)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (name[0] == '@' && name[2] == '.')
|
||||
name += 3;
|
||||
else if (name[0] == '*')
|
||||
name ++;
|
||||
else
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/* Output constructors and destructors. Just like
|
||||
default_named_section_asm_out_* but don't set the sections writable. */
|
||||
#undef TARGET_ASM_CONSTRUCTOR
|
||||
@ -1603,6 +1911,7 @@ xstormy16_print_operand (FILE *file, rtx x, int code)
|
||||
/* There is either one bit set, or one bit clear, in X.
|
||||
Print it preceded by '#'. */
|
||||
{
|
||||
static int bits_set[8] = { 0, 1, 1, 2, 1, 2, 2, 3 };
|
||||
HOST_WIDE_INT xx = 1;
|
||||
HOST_WIDE_INT l;
|
||||
|
||||
@ -1611,9 +1920,30 @@ xstormy16_print_operand (FILE *file, rtx x, int code)
|
||||
else
|
||||
output_operand_lossage ("`B' operand is not constant");
|
||||
|
||||
l = exact_log2 (xx);
|
||||
if (l == -1)
|
||||
l = exact_log2 (~xx);
|
||||
/* GCC sign-extends masks with the MSB set, so we have to
|
||||
detect all the cases that differ only in sign extension
|
||||
beyond the bits we care about. Normally, the predicates
|
||||
and constraints ensure that we have the right values. This
|
||||
works correctly for valid masks. */
|
||||
if (bits_set[xx & 7] <= 1)
|
||||
{
|
||||
/* Remove sign extension bits. */
|
||||
if ((~xx & ~(HOST_WIDE_INT)0xff) == 0)
|
||||
xx &= 0xff;
|
||||
else if ((~xx & ~(HOST_WIDE_INT)0xffff) == 0)
|
||||
xx &= 0xffff;
|
||||
l = exact_log2 (xx);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add sign extension bits. */
|
||||
if ((xx & ~(HOST_WIDE_INT)0xff) == 0)
|
||||
xx |= ~(HOST_WIDE_INT)0xff;
|
||||
else if ((xx & ~(HOST_WIDE_INT)0xffff) == 0)
|
||||
xx |= ~(HOST_WIDE_INT)0xffff;
|
||||
l = exact_log2 (~xx);
|
||||
}
|
||||
|
||||
if (l == -1)
|
||||
output_operand_lossage ("`B' operand has multiple bits set");
|
||||
|
||||
@ -1650,6 +1980,24 @@ xstormy16_print_operand (FILE *file, rtx x, int code)
|
||||
return;
|
||||
}
|
||||
|
||||
case 'b':
|
||||
/* Print the shift mask for bp/bn. */
|
||||
{
|
||||
HOST_WIDE_INT xx = 1;
|
||||
HOST_WIDE_INT l;
|
||||
|
||||
if (GET_CODE (x) == CONST_INT)
|
||||
xx = INTVAL (x);
|
||||
else
|
||||
output_operand_lossage ("`B' operand is not constant");
|
||||
|
||||
l = 7 - xx;
|
||||
|
||||
fputs (IMMEDIATE_PREFIX, file);
|
||||
fprintf (file, HOST_WIDE_INT_PRINT_DEC, l);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0:
|
||||
/* Handled below. */
|
||||
break;
|
||||
@ -2040,11 +2388,15 @@ xstormy16_interrupt_function_p (void)
|
||||
#define TARGET_ATTRIBUTE_TABLE xstormy16_attribute_table
|
||||
static tree xstormy16_handle_interrupt_attribute
|
||||
(tree *, tree, tree, int, bool *);
|
||||
static tree xstormy16_handle_below100_attribute
|
||||
(tree *, tree, tree, int, bool *);
|
||||
|
||||
static const struct attribute_spec xstormy16_attribute_table[] =
|
||||
{
|
||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||
{ "interrupt", 0, 0, false, true, true, xstormy16_handle_interrupt_attribute },
|
||||
{ "BELOW100", 0, 0, false, false, false, xstormy16_handle_below100_attribute },
|
||||
{ "below100", 0, 0, false, false, false, xstormy16_handle_below100_attribute },
|
||||
{ NULL, 0, 0, false, false, false, NULL }
|
||||
};
|
||||
|
||||
@ -2065,6 +2417,34 @@ xstormy16_handle_interrupt_attribute (tree *node, tree name,
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Handle an "below" attribute;
|
||||
arguments as in struct attribute_spec.handler. */
|
||||
static tree
|
||||
xstormy16_handle_below100_attribute (tree *node,
|
||||
tree name ATTRIBUTE_UNUSED,
|
||||
tree args ATTRIBUTE_UNUSED,
|
||||
int flags ATTRIBUTE_UNUSED,
|
||||
bool *no_add_attrs)
|
||||
{
|
||||
if (TREE_CODE (*node) != VAR_DECL
|
||||
&& TREE_CODE (*node) != POINTER_TYPE
|
||||
&& TREE_CODE (*node) != TYPE_DECL)
|
||||
{
|
||||
warning ("`__BELOW100__' attribute only applies to variables");
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
else if (args == NULL_TREE && TREE_CODE (*node) == VAR_DECL)
|
||||
{
|
||||
if (! (TREE_PUBLIC (*node) || TREE_STATIC (*node)))
|
||||
{
|
||||
warning ("__BELOW100__ attribute not allowed with auto storage class.");
|
||||
*no_add_attrs = true;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
#undef TARGET_INIT_BUILTINS
|
||||
#define TARGET_INIT_BUILTINS xstormy16_init_builtins
|
||||
@ -2182,6 +2562,174 @@ xstormy16_expand_builtin(tree exp, rtx target,
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/* Look for combinations of insns that can be converted to BN or BP
|
||||
opcodes. This is, unfortunately, too complex to do with MD
|
||||
patterns. */
|
||||
static void
|
||||
combine_bnp (rtx insn)
|
||||
{
|
||||
int insn_code, regno, need_extend, mask;
|
||||
rtx cond, reg, and, load, qireg, mem;
|
||||
enum machine_mode load_mode = QImode;
|
||||
|
||||
insn_code = recog_memoized (insn);
|
||||
if (insn_code != CODE_FOR_cbranchhi
|
||||
&& insn_code != CODE_FOR_cbranchhi_neg)
|
||||
return;
|
||||
|
||||
cond = XVECEXP (PATTERN (insn), 0, 0); /* set */
|
||||
cond = XEXP (cond, 1); /* if */
|
||||
cond = XEXP (cond, 0); /* cond */
|
||||
switch (GET_CODE (cond))
|
||||
{
|
||||
case NE:
|
||||
case EQ:
|
||||
need_extend = 0;
|
||||
break;
|
||||
case LT:
|
||||
case GE:
|
||||
need_extend = 1;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
reg = XEXP (cond, 0);
|
||||
if (GET_CODE (reg) != REG)
|
||||
return;
|
||||
regno = REGNO (reg);
|
||||
if (XEXP (cond, 1) != const0_rtx)
|
||||
return;
|
||||
if (! find_regno_note (insn, REG_DEAD, regno))
|
||||
return;
|
||||
qireg = gen_rtx_REG (QImode, regno);
|
||||
|
||||
if (need_extend)
|
||||
{
|
||||
/* LT and GE conditionals should have an sign extend before
|
||||
them. */
|
||||
for (and = prev_real_insn (insn); and; and = prev_real_insn (and))
|
||||
{
|
||||
int and_code = recog_memoized (and);
|
||||
if (and_code == CODE_FOR_extendqihi2
|
||||
&& rtx_equal_p (XEXP (PATTERN (and), 0), reg)
|
||||
&& rtx_equal_p (XEXP (XEXP (PATTERN (and), 1), 0), qireg))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (and_code == CODE_FOR_movhi_internal
|
||||
&& rtx_equal_p (XEXP (PATTERN (and), 0), reg))
|
||||
{
|
||||
/* This is for testing bit 15. */
|
||||
and = insn;
|
||||
break;
|
||||
}
|
||||
|
||||
if (reg_mentioned_p (reg, and))
|
||||
return;
|
||||
if (GET_CODE (and) != NOTE
|
||||
&& GET_CODE (and) != INSN)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* EQ and NE conditionals have an AND before them. */
|
||||
for (and = prev_real_insn (insn); and; and = prev_real_insn (and))
|
||||
{
|
||||
if (recog_memoized (and) == CODE_FOR_andhi3
|
||||
&& rtx_equal_p (XEXP (PATTERN (and), 0), reg)
|
||||
&& rtx_equal_p (XEXP (XEXP (PATTERN (and), 1), 0), reg))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (reg_mentioned_p (reg, and))
|
||||
return;
|
||||
if (GET_CODE (and) != NOTE
|
||||
&& GET_CODE (and) != INSN)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!and)
|
||||
return;
|
||||
|
||||
for (load = prev_real_insn (and); load; load = prev_real_insn (load))
|
||||
{
|
||||
int load_code = recog_memoized (load);
|
||||
if (load_code == CODE_FOR_movhi_internal
|
||||
&& rtx_equal_p (XEXP (PATTERN (load), 0), reg)
|
||||
&& xstormy16_below100_operand (XEXP (PATTERN (load), 1), HImode)
|
||||
&& ! MEM_VOLATILE_P (XEXP (PATTERN (load), 1)))
|
||||
{
|
||||
load_mode = HImode;
|
||||
break;
|
||||
}
|
||||
|
||||
if (load_code == CODE_FOR_movqi_internal
|
||||
&& rtx_equal_p (XEXP (PATTERN (load), 0), qireg)
|
||||
&& xstormy16_below100_operand (XEXP (PATTERN (load), 1), QImode))
|
||||
{
|
||||
load_mode = QImode;
|
||||
break;
|
||||
}
|
||||
|
||||
if (reg_mentioned_p (reg, load))
|
||||
return;
|
||||
if (GET_CODE (load) != NOTE
|
||||
&& GET_CODE (load) != INSN)
|
||||
return;
|
||||
}
|
||||
if (!load)
|
||||
return;
|
||||
|
||||
if (!need_extend)
|
||||
{
|
||||
if (!xstormy16_onebit_set_operand (XEXP (XEXP (PATTERN (and), 1), 1), load_mode))
|
||||
return;
|
||||
mask = (int) INTVAL (XEXP (XEXP (PATTERN (and), 1), 1));
|
||||
}
|
||||
else
|
||||
mask = (load_mode == HImode) ? 0x8000 : 0x80;
|
||||
|
||||
mem = XEXP (PATTERN (load), 1);
|
||||
if (load_mode == HImode)
|
||||
{
|
||||
rtx addr = XEXP (mem, 0);
|
||||
if (! (mask & 0xff))
|
||||
{
|
||||
addr = plus_constant (addr, 1);
|
||||
mask >>= 8;
|
||||
}
|
||||
mem = gen_rtx_MEM (QImode, addr);
|
||||
}
|
||||
|
||||
if (need_extend)
|
||||
XEXP (cond, 0) = gen_rtx_SIGN_EXTEND (HImode, mem);
|
||||
else
|
||||
XEXP (cond, 0) = gen_rtx_AND (QImode, mem, GEN_INT (mask));
|
||||
INSN_CODE (insn) = -1;
|
||||
delete_insn (load);
|
||||
if (and != insn)
|
||||
delete_insn (and);
|
||||
}
|
||||
|
||||
static void
|
||||
xstormy16_reorg (void)
|
||||
{
|
||||
rtx insn;
|
||||
|
||||
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
|
||||
{
|
||||
if (! JUMP_P (insn))
|
||||
continue;
|
||||
combine_bnp (insn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Worker function for TARGET_RETURN_IN_MEMORY. */
|
||||
|
||||
@ -2196,6 +2744,10 @@ xstormy16_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
|
||||
#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
|
||||
#undef TARGET_ASM_ALIGNED_SI_OP
|
||||
#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
|
||||
#undef TARGET_ENCODE_SECTION_INFO
|
||||
#define TARGET_ENCODE_SECTION_INFO xstormy16_encode_section_info
|
||||
#undef TARGET_STRIP_NAME_ENCODING
|
||||
#define TARGET_STRIP_NAME_ENCODING xstormy16_strip_name_encoding
|
||||
|
||||
#undef TARGET_ASM_OUTPUT_MI_THUNK
|
||||
#define TARGET_ASM_OUTPUT_MI_THUNK xstormy16_asm_output_mi_thunk
|
||||
@ -2222,4 +2774,7 @@ xstormy16_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
|
||||
#undef TARGET_RETURN_IN_MEMORY
|
||||
#define TARGET_RETURN_IN_MEMORY xstormy16_return_in_memory
|
||||
|
||||
#undef TARGET_MACHINE_DEPENDENT_REORG
|
||||
#define TARGET_MACHINE_DEPENDENT_REORG xstormy16_reorg
|
||||
|
||||
struct gcc_target targetm = TARGET_INITIALIZER;
|
||||
|
@ -626,6 +626,26 @@ do { \
|
||||
#undef DTORS_SECTION_ASM_OP
|
||||
#define CTORS_SECTION_ASM_OP "\t.section\t.ctors,\"a\""
|
||||
#define DTORS_SECTION_ASM_OP "\t.section\t.dtors,\"a\""
|
||||
#define EXTRA_SECTIONS in_bss100
|
||||
|
||||
/* We define the function body in a separate macro so that if we ever
|
||||
add another section, we can just add an entry to
|
||||
EXTRA_SECTION_FUNCTIONS without making it difficult to read. It is
|
||||
not used anywhere else. */
|
||||
#define XSTORMY16_SECTION_FUNCTION(name, in, string, bits) \
|
||||
void \
|
||||
name () \
|
||||
{ \
|
||||
if (in_section != in) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.section %s,\"aw\",@%sbits\n", string, bits); \
|
||||
in_section = in; \
|
||||
} \
|
||||
}
|
||||
|
||||
#undef EXTRA_SECTION_FUNCTIONS
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
XSTORMY16_SECTION_FUNCTION (bss100_section, in_bss100, ".bss_below100", "no")
|
||||
|
||||
#define JUMP_TABLES_IN_TEXT_SECTION 1
|
||||
|
||||
@ -642,15 +662,23 @@ do { \
|
||||
|
||||
#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == '|')
|
||||
|
||||
#define ASM_OUTPUT_ALIGNED_DECL_COMMON(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
|
||||
xstormy16_asm_output_aligned_common(STREAM, DECL, NAME, SIZE, ALIGNMENT, 1)
|
||||
#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
|
||||
xstormy16_asm_output_aligned_common(STREAM, DECL, NAME, SIZE, ALIGNMENT, 0)
|
||||
|
||||
|
||||
/* Output and Generation of Labels. */
|
||||
|
||||
#define ASM_OUTPUT_SYMBOL_REF(STREAM, SYMBOL) \
|
||||
do { \
|
||||
const char *rn = XSTR (SYMBOL, 0); \
|
||||
if (rn[0] == '@' && rn[2] == '.') \
|
||||
rn += 3; \
|
||||
if (SYMBOL_REF_FUNCTION_P (SYMBOL)) \
|
||||
ASM_OUTPUT_LABEL_REF ((STREAM), XSTR (SYMBOL, 0)); \
|
||||
ASM_OUTPUT_LABEL_REF ((STREAM), rn); \
|
||||
else \
|
||||
assemble_name (STREAM, XSTR (SYMBOL, 0)); \
|
||||
assemble_name (STREAM, rn); \
|
||||
} while (0)
|
||||
|
||||
#define ASM_OUTPUT_LABEL_REF(STREAM, NAME) \
|
||||
@ -660,6 +688,9 @@ do { \
|
||||
fputc (')', STREAM); \
|
||||
} while (0)
|
||||
|
||||
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
|
||||
asm_fprintf ((STREAM), "%U%s", xstormy16_strip_name_encoding (NAME));
|
||||
|
||||
/* Globalizing directive for a label. */
|
||||
#define GLOBAL_ASM_OP "\t.globl "
|
||||
|
||||
@ -785,6 +816,11 @@ do { \
|
||||
{"equality_operator", {EQ, NE }}, \
|
||||
{"inequality_operator", {GE, GT, LE, LT, GEU, GTU, LEU, LTU }}, \
|
||||
{"xstormy16_ineqsi_operator", {LT, GE, LTU, GEU }}, \
|
||||
{"xstormy16_below100_operand", {MEM }}, \
|
||||
{"xstormy16_below100_or_register", {MEM, REG }}, \
|
||||
{"xstormy16_splittable_below100_or_register", {MEM, REG }}, \
|
||||
{"xstormy16_onebit_clr_operand", {CONST_INT }}, \
|
||||
{"xstormy16_onebit_set_operand", {CONST_INT }}, \
|
||||
{"nonimmediate_nonstack_operand", {REG, MEM}},
|
||||
|
||||
#define CASE_VECTOR_MODE SImode
|
||||
|
@ -130,9 +130,9 @@
|
||||
""
|
||||
"{ xstormy16_expand_move (QImode, operands[0], operands[1]); DONE; }")
|
||||
|
||||
(define_insn "*movqi_internal"
|
||||
[(set (match_operand:QI 0 "nonimmediate_nonstack_operand" "=r,m,e,e,T,r,S")
|
||||
(match_operand:QI 1 "general_operand" "r,e,m,i,i,i,i"))]
|
||||
(define_insn "movqi_internal"
|
||||
[(set (match_operand:QI 0 "nonimmediate_nonstack_operand" "=r,m,e,e,T,r,S,W,r")
|
||||
(match_operand:QI 1 "general_operand" "r,e,m,i,i,i,i,ir,W"))]
|
||||
""
|
||||
"@
|
||||
mov %0,%1
|
||||
@ -141,6 +141,8 @@
|
||||
mov %0,%1
|
||||
mov Rx,%1
|
||||
mov %0,%1
|
||||
mov.b %0,%1
|
||||
mov.b %0,%1
|
||||
mov.b %0,%1"
|
||||
[(set_attr_alternative "length"
|
||||
[(const_int 2)
|
||||
@ -153,8 +155,10 @@
|
||||
(const_int 2)
|
||||
(const_int 2)
|
||||
(const_int 4)
|
||||
(const_int 4)])
|
||||
(set_attr "psw_operand" "0,0,0,0,nop,0,nop")])
|
||||
(const_int 4)
|
||||
(const_int 2)
|
||||
(const_int 2)])
|
||||
(set_attr "psw_operand" "0,0,0,0,nop,0,nop,0,0")])
|
||||
|
||||
(define_insn "pushhi"
|
||||
[(set (mem:HI (post_inc (reg:HI 15)))
|
||||
@ -178,9 +182,9 @@
|
||||
""
|
||||
"{ xstormy16_expand_move (HImode, operands[0], operands[1]); DONE; }")
|
||||
|
||||
(define_insn "*movhi_internal"
|
||||
[(set (match_operand:HI 0 "nonimmediate_nonstack_operand" "=r,m,e,e,T,r,S")
|
||||
(match_operand:HI 1 "xs_hi_general_operand" "r,e,m,L,L,i,i"))]
|
||||
(define_insn "movhi_internal"
|
||||
[(set (match_operand:HI 0 "nonimmediate_nonstack_operand" "=r,m,e,e,T,r,S,W,r")
|
||||
(match_operand:HI 1 "xs_hi_general_operand" "r,e,m,L,L,i,i,ir,W"))]
|
||||
""
|
||||
"@
|
||||
mov %0,%1
|
||||
@ -189,6 +193,8 @@
|
||||
mov.w %0,%1
|
||||
mov.w Rx,%1
|
||||
mov.w %0,%1
|
||||
mov.w %0,%1
|
||||
mov.w %0,%1
|
||||
mov.w %0,%1"
|
||||
[(set_attr_alternative "length"
|
||||
[(const_int 2)
|
||||
@ -201,8 +207,10 @@
|
||||
(const_int 2)
|
||||
(const_int 2)
|
||||
(const_int 4)
|
||||
(const_int 4)
|
||||
(const_int 4)
|
||||
(const_int 4)])
|
||||
(set_attr "psw_operand" "0,0,0,0,nop,0,nop")])
|
||||
(set_attr "psw_operand" "0,0,0,0,nop,0,nop,0,0")])
|
||||
|
||||
(define_expand "movsi"
|
||||
[(set (match_operand:SI 0 "nonimmediate_operand" "")
|
||||
@ -552,29 +560,63 @@
|
||||
|
||||
;; Logical AND, 16 bit integers
|
||||
(define_insn "andhi3"
|
||||
[(set (match_operand:HI 0 "register_operand" "=T,r,r,r")
|
||||
(and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
|
||||
(match_operand:HI 2 "nonmemory_operand" "L,r,K,i")))]
|
||||
[(set (match_operand:HI 0 "xstormy16_splittable_below100_or_register" "=T,r,r,r,W")
|
||||
(and:HI (match_operand:HI 1 "xstormy16_below100_or_register" "%0,0,0,0,0")
|
||||
(match_operand:HI 2 "nonmemory_operand" "L,r,K,i,K")))]
|
||||
""
|
||||
"@
|
||||
and Rx,%2
|
||||
and %0,%2
|
||||
clr1 %0,%B2
|
||||
and %0,%2"
|
||||
[(set_attr "length" "2,2,2,4")])
|
||||
and %0,%2
|
||||
#"
|
||||
[(set_attr "length" "2,2,2,4,2")])
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:HI 0 "xstormy16_below100_operand" "")
|
||||
(and:HI (match_operand:HI 1 "xstormy16_below100_operand" "")
|
||||
(match_operand:HI 2 "xstormy16_onebit_clr_operand" "")))]
|
||||
""
|
||||
[(set (match_dup 3)
|
||||
(and:QI (match_dup 4)
|
||||
(match_dup 5)))]
|
||||
"{ int s = ((INTVAL (operands[2]) & 0xff) == 0xff) ? 1 : 0;
|
||||
operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, s);
|
||||
operands[4] = simplify_gen_subreg (QImode, operands[1], HImode, s);
|
||||
operands[5] = simplify_gen_subreg (QImode, operands[2], HImode, s);
|
||||
operands[5] = GEN_INT (INTVAL (operands[5]) | ~(HOST_WIDE_INT)0xff);
|
||||
}
|
||||
")
|
||||
|
||||
;; Inclusive OR, 16 bit integers
|
||||
(define_insn "iorhi3"
|
||||
[(set (match_operand:HI 0 "register_operand" "=T,r,r,r")
|
||||
(ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
|
||||
(match_operand:HI 2 "nonmemory_operand" "L,r,J,i")))]
|
||||
[(set (match_operand:HI 0 "xstormy16_splittable_below100_or_register" "=T,r,r,r,W")
|
||||
(ior:HI (match_operand:HI 1 "xstormy16_below100_or_register" "%0,0,0,0,0")
|
||||
(match_operand:HI 2 "nonmemory_operand" "L,r,J,i,J")))]
|
||||
""
|
||||
"@
|
||||
or Rx,%2
|
||||
or %0,%2
|
||||
set1 %0,%B2
|
||||
or %0,%2"
|
||||
[(set_attr "length" "2,2,2,4")])
|
||||
or %0,%2
|
||||
#"
|
||||
[(set_attr "length" "2,2,2,4,2")])
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:HI 0 "xstormy16_below100_operand" "")
|
||||
(ior:HI (match_operand:HI 1 "xstormy16_below100_operand" "")
|
||||
(match_operand:HI 2 "xstormy16_onebit_set_operand" "")))]
|
||||
""
|
||||
[(set (match_dup 3)
|
||||
(ior:QI (match_dup 4)
|
||||
(match_dup 5)))]
|
||||
"{ int s = ((INTVAL (operands[2]) & 0xff) == 0x00) ? 1 : 0;
|
||||
operands[3] = simplify_gen_subreg (QImode, operands[0], HImode, s);
|
||||
operands[4] = simplify_gen_subreg (QImode, operands[1], HImode, s);
|
||||
operands[5] = simplify_gen_subreg (QImode, operands[2], HImode, s);
|
||||
operands[5] = GEN_INT (INTVAL (operands[5]) & 0xff);
|
||||
}
|
||||
")
|
||||
|
||||
;; Exclusive OR, 16 bit integers
|
||||
(define_insn "xorhi3"
|
||||
@ -796,7 +838,7 @@
|
||||
"{ xstormy16_emit_cbranch (LTU, operands[0]); DONE; }")
|
||||
|
||||
|
||||
(define_insn "*cbranchhi"
|
||||
(define_insn "cbranchhi"
|
||||
[(set (pc)
|
||||
(if_then_else (match_operator:HI 1 "comparison_operator"
|
||||
[(match_operand:HI 2 "nonmemory_operand"
|
||||
@ -814,7 +856,7 @@
|
||||
[(set_attr "branch_class" "bcc12")
|
||||
(set_attr "psw_operand" "0,0,1")])
|
||||
|
||||
(define_insn "*cbranchhi_neg"
|
||||
(define_insn "cbranchhi_neg"
|
||||
[(set (pc)
|
||||
(if_then_else (match_operator:HI 1 "comparison_operator"
|
||||
[(match_operand:HI 2 "nonmemory_operand"
|
||||
@ -1095,3 +1137,208 @@
|
||||
""
|
||||
[(set_attr "length" "0")
|
||||
(set_attr "psw_operand" "nop")])
|
||||
|
||||
;;---------------------------------------------------------------------------
|
||||
|
||||
(define_expand "iorqi3"
|
||||
[(match_operand:QI 0 "xstormy16_below100_or_register" "")
|
||||
(match_operand:QI 1 "xstormy16_below100_or_register" "")
|
||||
(match_operand:QI 2 "nonmemory_operand" "")]
|
||||
""
|
||||
"
|
||||
{
|
||||
xstormy16_expand_iorqi3 (operands);
|
||||
DONE;
|
||||
}")
|
||||
|
||||
(define_insn "iorqi3_internal"
|
||||
[(set (match_operand:QI 0 "xstormy16_below100_or_register" "=Wr")
|
||||
(ior:QI (match_operand:QI 1 "xstormy16_below100_or_register" "0")
|
||||
(match_operand:QI 2 "xstormy16_onebit_set_operand" "i")))]
|
||||
""
|
||||
"set1 %0,%B2"
|
||||
[(set_attr "length" "2")
|
||||
(set_attr "psw_operand" "0")])
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand:QI 0 "register_operand" "")
|
||||
(match_operand:QI 1 "xstormy16_below100_operand" ""))
|
||||
(set (match_operand:HI 2 "register_operand" "")
|
||||
(ior:HI (match_operand:HI 3 "register_operand" "")
|
||||
(match_operand:QI 4 "xstormy16_onebit_set_operand" "")))
|
||||
(set (match_operand:QI 5 "xstormy16_below100_operand" "")
|
||||
(match_operand:QI 6 "register_operand" ""))
|
||||
]
|
||||
"REGNO (operands[0]) == REGNO (operands[2])
|
||||
&& REGNO (operands[0]) == REGNO (operands[3])
|
||||
&& REGNO (operands[0]) == REGNO (operands[6])
|
||||
&& rtx_equal_p (operands[1], operands[5])"
|
||||
[(set (match_dup 1)
|
||||
(ior:QI (match_dup 1)
|
||||
(match_dup 4)))
|
||||
]
|
||||
"")
|
||||
|
||||
|
||||
(define_expand "andqi3"
|
||||
[(match_operand:QI 0 "xstormy16_below100_or_register" "")
|
||||
(match_operand:QI 1 "xstormy16_below100_or_register" "")
|
||||
(match_operand:QI 2 "nonmemory_operand" "")]
|
||||
""
|
||||
"
|
||||
{
|
||||
xstormy16_expand_andqi3 (operands);
|
||||
DONE;
|
||||
}")
|
||||
|
||||
(define_insn "andqi3_internal"
|
||||
[(set (match_operand:QI 0 "xstormy16_below100_or_register" "=Wr")
|
||||
(and:QI (match_operand:QI 1 "xstormy16_below100_or_register" "0")
|
||||
(match_operand:QI 2 "xstormy16_onebit_clr_operand" "i")))]
|
||||
""
|
||||
"clr1 %0,%B2"
|
||||
[(set_attr "length" "2")
|
||||
(set_attr "psw_operand" "0")])
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand:HI 0 "register_operand" "")
|
||||
(and:HI (match_operand:HI 1 "register_operand" "")
|
||||
(match_operand 2 "immediate_operand" "")))
|
||||
(set (match_operand:HI 3 "register_operand" "")
|
||||
(zero_extend:HI (match_operand:QI 4 "register_operand" "")));
|
||||
]
|
||||
"REGNO (operands[0]) == REGNO (operands[1])
|
||||
&& REGNO (operands[0]) == REGNO (operands[3])
|
||||
&& REGNO (operands[0]) == REGNO (operands[4])"
|
||||
[(set (match_dup 0)
|
||||
(and:HI (match_dup 1)
|
||||
(match_dup 5)))
|
||||
]
|
||||
"operands[5] = GEN_INT (INTVAL (operands[2]) & 0xff);")
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand:QI 0 "register_operand" "")
|
||||
(match_operand:QI 1 "xstormy16_below100_operand" ""))
|
||||
(set (match_operand:HI 2 "register_operand" "")
|
||||
(and:HI (match_operand:HI 3 "register_operand" "")
|
||||
(match_operand:QI 4 "xstormy16_onebit_clr_operand" "")))
|
||||
(set (match_operand:QI 5 "xstormy16_below100_operand" "")
|
||||
(match_operand:QI 6 "register_operand" ""))
|
||||
]
|
||||
"REGNO (operands[0]) == REGNO (operands[2])
|
||||
&& REGNO (operands[0]) == REGNO (operands[3])
|
||||
&& REGNO (operands[0]) == REGNO (operands[6])
|
||||
&& rtx_equal_p (operands[1], operands[5])"
|
||||
[(set (match_dup 1)
|
||||
(and:QI (match_dup 1)
|
||||
(match_dup 4)))
|
||||
]
|
||||
"")
|
||||
|
||||
;; GCC uses different techniques to optimize MSB and LSB accesses, so
|
||||
;; we have to code those separately.
|
||||
|
||||
(define_insn "*bclrx"
|
||||
[(set (pc)
|
||||
(if_then_else (eq:HI (and:QI (match_operand:QI 1 "xstormy16_below100_operand" "W")
|
||||
(match_operand:HI 2 "immediate_operand" "i"))
|
||||
(const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))
|
||||
(clobber (match_operand:BI 3 "" "=y"))]
|
||||
""
|
||||
"bn %1,%B2,%l0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "psw_operand" "nop")])
|
||||
|
||||
(define_insn "*bclrx2"
|
||||
[(set (pc)
|
||||
(if_then_else (zero_extract:HI
|
||||
(xor:HI (subreg:HI
|
||||
(match_operand:QI 1 "xstormy16_below100_operand" "W") 0)
|
||||
(match_operand:HI 2 "xstormy16_onebit_set_operand" "J"))
|
||||
(const_int 1)
|
||||
(match_operand:HI 3 "immediate_operand" "i"))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))
|
||||
(clobber (match_operand:BI 4 "" "=y"))]
|
||||
""
|
||||
"bn %1,%B2,%l0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "psw_operand" "nop")])
|
||||
|
||||
(define_insn "*bclr7"
|
||||
[(set (pc)
|
||||
(if_then_else (xor:HI (lshiftrt:HI (subreg:HI
|
||||
(match_operand:QI 1 "xstormy16_below100_operand" "W") 0)
|
||||
(const_int 7))
|
||||
(const_int 1))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))
|
||||
(clobber (match_operand:BI 2 "" "=y"))]
|
||||
""
|
||||
"bn %1,#7,%l0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "psw_operand" "nop")])
|
||||
|
||||
(define_insn "*bclr15"
|
||||
[(set (pc)
|
||||
(if_then_else (ge:HI (sign_extend:HI (match_operand:QI 1 "xstormy16_below100_operand" "W"))
|
||||
(const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))
|
||||
(clobber (match_operand:BI 2 "" "=y"))]
|
||||
""
|
||||
"bn %1,#7,%l0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "psw_operand" "nop")])
|
||||
|
||||
(define_insn "*bsetx"
|
||||
[(set (pc)
|
||||
(if_then_else (ne:HI (and:QI (match_operand:QI 1 "xstormy16_below100_operand" "W")
|
||||
(match_operand:HI 2 "immediate_operand" "i"))
|
||||
(const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))
|
||||
(clobber (match_operand:BI 3 "" "=y"))]
|
||||
""
|
||||
"bp %1,%B2,%l0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "psw_operand" "nop")])
|
||||
|
||||
(define_insn "*bsetx2"
|
||||
[(set (pc)
|
||||
(if_then_else (zero_extract:HI (match_operand:QI 1 "xstormy16_below100_operand" "W")
|
||||
(const_int 1)
|
||||
(match_operand:HI 2 "immediate_operand" "i"))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))
|
||||
(clobber (match_operand:BI 3 "" "=y"))]
|
||||
""
|
||||
"bp %1,%b2,%l0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "psw_operand" "nop")])
|
||||
|
||||
(define_insn "*bset7"
|
||||
[(set (pc)
|
||||
(if_then_else (lshiftrt:HI (subreg:HI (match_operand:QI 1 "xstormy16_below100_operand" "W") 0)
|
||||
(const_int 7))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))
|
||||
(clobber (match_operand:BI 2 "" "=y"))]
|
||||
""
|
||||
"bp %1,#7,%l0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "psw_operand" "nop")])
|
||||
|
||||
(define_insn "*bset15"
|
||||
[(set (pc)
|
||||
(if_then_else (lt:HI (sign_extend:HI (match_operand:QI 1 "xstormy16_below100_operand" "W"))
|
||||
(const_int 0))
|
||||
(label_ref (match_operand 0 "" ""))
|
||||
(pc)))
|
||||
(clobber (match_operand:BI 2 "" "=y"))]
|
||||
""
|
||||
"bp %1,#7,%l0"
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "psw_operand" "nop")])
|
||||
|
@ -2977,6 +2977,23 @@ Currently @option{-m[no-]ms-bitfields} is provided for the Microsoft Windows X86
|
||||
compilers to match the native Microsoft compiler.
|
||||
@end table
|
||||
|
||||
@subsection Xstormy16 Variable Attributes
|
||||
|
||||
One attribute is currently defined for xstormy16 configurations:
|
||||
@code{below100}
|
||||
|
||||
@table @code
|
||||
@item below100
|
||||
@cindex @code{below100} attribute
|
||||
|
||||
If a variable has the @code{below100} attribute (@code{BELOW100} is
|
||||
allowed also), GCC will place the variable in the first 0x100 bytes of
|
||||
memory and use special opcodes to access it. Such variables will be
|
||||
placed in either the @code{.bss_below100} section or the
|
||||
@code{.data_below100} section.
|
||||
|
||||
@end table
|
||||
|
||||
@node Type Attributes
|
||||
@section Specifying Attributes of Types
|
||||
@cindex attribute of types
|
||||
|
Loading…
Reference in New Issue
Block a user