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:
DJ Delorie 2004-08-17 18:51:28 -04:00 committed by DJ Delorie
parent c3f84f61e3
commit 54e9a19d9d
6 changed files with 956 additions and 26 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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")])

View File

@ -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