Commit 3bbbe009 by Sandra Loosemore Committed by Sandra Loosemore

nios2.h (LABEL_ALIGN): Define.

2015-07-14  Sandra Loosemore  <sandra@codesourcery.com>
	    Cesar Philippidis  <cesar@codesourcery.com>
	    Chung-Lin Tang  <cltang@codesourcery.com>

	gcc/
	* config/nios2/nios2.h (LABEL_ALIGN): Define.
	(REG_ALLOC_ORDER): Define.
	(ADJUST_REG_ALLOC_ORDER): Define.
	(HONOR_REG_ALLOC_ORDER): Define.
	(CDX_REG_P): Define.
	(ANDCLEAR_INT): Define.
	* config/nios2/nios2-protos.h (nios2_add_insn_asm): Declare.
	(nios2_label_align): Declare.
	(nios2_cdx_narrow_form_p): Declare.
	(nios2_adjust_reg_alloc_order): Declare.
	* config/nios2/nios2.c (nios2_rtx_costs): Adjust for BMX zero-extract
	operation.
	(nios2_large_unspec_reloc_p): New function, split from...
	(nios2_legitimate_pic_operand_p): ...here.
	(nios2_emit_move_sequence): Add *high/*lo_sum constant expand code.
	(nios2_print_operand_punct_valid_p): New.
	(nios2_print_operand): Add %., %!, %x, %y, %A.  Remove %U.
	(split_mem_address): New.
	(split_alu_insn): New.
	(cdxreg): New.
	(cdx_add_immed, cdx_and_immed, cdx_mov_immed, cdx_shift_immed): New.
	(enum nios2_add_insn_kind): New.
	(nios2_add_insn_names, nios2_add_insn_narrow): New.
	(nios2_add_insn_classify): New.
	(nios2_add_insn_asm): New.
	(nios2_cdx_narrow_form_p): New.
	(label_align, min_labelno, max_labelno): New.
	(nios2_reorg): New.
	(nios2_label_align): New.
	(nios2_adjust_reg_alloc_order): New.
	(TARGET_PRINT_OPERAND_PUNCT_VALID_P): Define.
	(TARGET_MACHINE_DEPENDENT_REORG): Define.
	* config/nios2/constraints.md (P): New constraint.
	* config/nios2/predicates.md (const_and_operand): New.
	(and_operand): New.
	(stack_memory_operand): New.
	* config/nios2/nios2.md (SP_REGNO): Define stack pointer regno.
	(length): Update to use nios2_cdx_narrow_form_p().
	(type): Add new insn type values.
	(control, alu, st, ld, shift): Update insn reservations with
	new insn type values.
	(*high, *lo_sum): Define new insn patterns for constant generation.
	(movqi_internal, movhi_internal, movsi_internal): Reduce
	alternatives, update asm template to handle CDX variants, update
	type attributes.
	(zero_extendhisi2, zero_extendqi<mode>2): Add CDX variants to asm
	template, update type attributes.
	(extendhisi2, extendqi<mode>2): Likewise.
	(addsi3): Change to use function for asm string.
	(subsi3): Add CDX notation to asm template, update type attributes.
	(negsi3, one_cmplsi3): Likewise.
	(andsi3): New pattern, specialized from logical patterns.
	(<code>si3): Remove and case, combine alternatives, update asm
	template.
	(<shift_op>si3): Add CDX notation, update type attributes.
	(rotrsi3): Update type attribute.
	(*merge, extzv, insv): New insn patterns.
	(return): Change to define_expand.
	(simple_return): Add CDX notation, update type attributes.
	(indirect_jump): Add CDX notation.
	(jump): Update asm cases, update length attribute expression.
	(*call, *call_value, *sibcall, *sibcall_value): Add CDX variant.
	(nios2_cbranch): Update asm cases and length attribute expression
	to handle CDX variants.
	(nios2_cmp<code>): Update asm template.
	(nop): Add CDX notation, update type attributes.
	(trap): Add CDX notation.
	(ctrapsi4): Update asm cases and length attribute expression to
	handle CDX variant.
	* doc/md.texi (Machine Constraints): Document P constraint.

	gcc/testsuite/
	* gcc.target/nios2/andci.c: New.
	* gcc.target/nios2/bmx.c: New.
	* gcc.target/nios2/cdx-add.c: New.
	* gcc.target/nios2/cdx-branch.c: New.
	* gcc.target/nios2/cdx-callret.c: New.
	* gcc.target/nios2/cdx-loadstore.c: New.
	* gcc.target/nios2/cdx-logical.c: New.
	* gcc.target/nios2/cdx-mov.c: New.
	* gcc.target/nios2/cdx-shift.c: New.
	* gcc.target/nios2/cdx-sub.c: New.
	* gcc.target/nios2/nios2-trap-insn.c: Adjust pattern.

Co-Authored-By: Cesar Philippidis <cesar@codesourcery.com>
Co-Authored-By: Chung-Lin Tang <cltang@codesourcery.com>

From-SVN: r225796
parent a03c6ae3
......@@ -2,6 +2,81 @@
Cesar Philippidis <cesar@codesourcery.com>
Chung-Lin Tang <cltang@codesourcery.com>
* config/nios2/nios2.h (LABEL_ALIGN): Define.
(REG_ALLOC_ORDER): Define.
(ADJUST_REG_ALLOC_ORDER): Define.
(HONOR_REG_ALLOC_ORDER): Define.
(CDX_REG_P): Define.
(ANDCLEAR_INT): Define.
* config/nios2/nios2-protos.h (nios2_add_insn_asm): Declare.
(nios2_label_align): Declare.
(nios2_cdx_narrow_form_p): Declare.
(nios2_adjust_reg_alloc_order): Declare.
* config/nios2/nios2.c (nios2_rtx_costs): Adjust for BMX zero-extract
operation.
(nios2_large_unspec_reloc_p): New function, split from...
(nios2_legitimate_pic_operand_p): ...here.
(nios2_emit_move_sequence): Add *high/*lo_sum constant expand code.
(nios2_print_operand_punct_valid_p): New.
(nios2_print_operand): Add %., %!, %x, %y, %A. Remove %U.
(split_mem_address): New.
(split_alu_insn): New.
(cdxreg): New.
(cdx_add_immed, cdx_and_immed, cdx_mov_immed, cdx_shift_immed): New.
(enum nios2_add_insn_kind): New.
(nios2_add_insn_names, nios2_add_insn_narrow): New.
(nios2_add_insn_classify): New.
(nios2_add_insn_asm): New.
(nios2_cdx_narrow_form_p): New.
(label_align, min_labelno, max_labelno): New.
(nios2_reorg): New.
(nios2_label_align): New.
(nios2_adjust_reg_alloc_order): New.
(TARGET_PRINT_OPERAND_PUNCT_VALID_P): Define.
(TARGET_MACHINE_DEPENDENT_REORG): Define.
* config/nios2/constraints.md (P): New constraint.
* config/nios2/predicates.md (const_and_operand): New.
(and_operand): New.
(stack_memory_operand): New.
* config/nios2/nios2.md (SP_REGNO): Define stack pointer regno.
(length): Update to use nios2_cdx_narrow_form_p().
(type): Add new insn type values.
(control, alu, st, ld, shift): Update insn reservations with
new insn type values.
(*high, *lo_sum): Define new insn patterns for constant generation.
(movqi_internal, movhi_internal, movsi_internal): Reduce
alternatives, update asm template to handle CDX variants, update
type attributes.
(zero_extendhisi2, zero_extendqi<mode>2): Add CDX variants to asm
template, update type attributes.
(extendhisi2, extendqi<mode>2): Likewise.
(addsi3): Change to use function for asm string.
(subsi3): Add CDX notation to asm template, update type attributes.
(negsi3, one_cmplsi3): Likewise.
(andsi3): New pattern, specialized from logical patterns.
(<code>si3): Remove and case, combine alternatives, update asm
template.
(<shift_op>si3): Add CDX notation, update type attributes.
(rotrsi3): Update type attribute.
(*merge, extzv, insv): New insn patterns.
(return): Change to define_expand.
(simple_return): Add CDX notation, update type attributes.
(indirect_jump): Add CDX notation.
(jump): Update asm cases, update length attribute expression.
(*call, *call_value, *sibcall, *sibcall_value): Add CDX variant.
(nios2_cbranch): Update asm cases and length attribute expression
to handle CDX variants.
(nios2_cmp<code>): Update asm template.
(nop): Add CDX notation, update type attributes.
(trap): Add CDX notation.
(ctrapsi4): Update asm cases and length attribute expression to
handle CDX variant.
* doc/md.texi (Machine Constraints): Document P constraint.
2015-07-14 Sandra Loosemore <sandra@codesourcery.com>
Cesar Philippidis <cesar@codesourcery.com>
Chung-Lin Tang <cltang@codesourcery.com>
* config/nios2/nios2.h (SMALL_INT12): New macro.
* config/nios2/nios2.c (nios2_valid_addr_offset_p): New function.
(nios2_valid_addr_expr_p): Use it.
......
......@@ -20,9 +20,10 @@
;; We use the following constraint letters for constants
;;
;; I: -32768 to -32767
;; I: -32768 to 32767
;; J: 0 to 65535
;; K: $nnnn0000 for some nnnn
;; P: Under R2, $nnnnffff or $ffffnnnn for some nnnn
;; L: 0 to 31 (for shift counts)
;; M: 0
;; N: 0 to 255 (for custom instruction numbers)
......@@ -86,6 +87,11 @@
(and (match_code "const_int")
(match_test "ival >= 0 && ival <= 31")))
(define_constraint "P"
"An immediate operand for R2 andchi/andci instructions."
(and (match_code "const_int")
(match_test "TARGET_ARCH_R2 && ANDCLEAR_INT (ival)")))
(define_constraint "S"
"An immediate stored in small data, accessible by GP."
(match_test "gprel_constant_p (op)"))
......
......@@ -42,12 +42,18 @@ extern bool nios2_validate_fpu_compare (machine_mode, rtx *, rtx *, rtx *,
extern bool nios2_fpu_insn_enabled (enum n2fpu_code);
extern const char * nios2_fpu_insn_asm (enum n2fpu_code);
extern const char * nios2_add_insn_asm (rtx_insn *, rtx *);
extern bool nios2_legitimate_pic_operand_p (rtx);
extern bool gprel_constant_p (rtx);
extern bool nios2_regno_ok_for_base_p (int, bool);
extern bool nios2_unspec_reloc_p (rtx);
extern int nios2_label_align (rtx);
extern bool nios2_cdx_narrow_form_p (rtx_insn *);
extern void nios2_adjust_reg_alloc_order (void);
#ifdef TREE_CODE
#ifdef ARGS_SIZE_RTX
/* expr.h defines both ARGS_SIZE_RTX and `enum direction' */
......
......@@ -96,6 +96,8 @@
((TREE_CODE (EXP) == STRING_CST) \
&& (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
#define LABEL_ALIGN(LABEL) nios2_label_align (LABEL)
/* Layout of source language data types. */
#define INT_TYPE_SIZE 32
......@@ -175,6 +177,20 @@
#define HARD_REGNO_NREGS(REGNO, MODE) \
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* Order in which to allocate registers. Each register must be
listed once. This is the default ordering for R1 and non-CDX R2
code. For CDX, we overwrite this in ADJUST_REG_ALLOC_ORDER. */
#define REG_ALLOC_ORDER \
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, \
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, \
37, 38, 39 }
#define ADJUST_REG_ALLOC_ORDER nios2_adjust_reg_alloc_order ()
/* Caller-save costs can be less emphasized under R2 CDX, where we can
use push.n/pop.n. */
#define HONOR_REG_ALLOC_ORDER (TARGET_HAS_CDX)
/* Register Classes. */
enum reg_class
......@@ -213,6 +229,9 @@ enum reg_class
#define CLASS_MAX_NREGS(CLASS, MODE) \
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
#define CDX_REG_P(REGNO) \
((REGNO) == 16 || (REGNO) == 17 || (2 <= (REGNO) && (REGNO) <= 7))
/* Tests for various kinds of constants used in the Nios II port. */
#define SMALL_INT(X) ((unsigned HOST_WIDE_INT)(X) + 0x8000 < 0x10000)
......@@ -222,6 +241,8 @@ enum reg_class
#define SHIFT_INT(X) ((X) >= 0 && (X) <= 31)
#define RDWRCTL_INT(X) ((X) >= 0 && (X) <= 31)
#define CUSTOM_INSN_OPCODE(X) ((X) >= 0 && (X) <= 255)
#define ANDCLEAR_INT(X) \
(((X) & 0xffff) == 0xffff || (((X) >> 16) & 0xffff) == 0xffff)
/* Say that the epilogue uses the return address register. Note that
in the case of sibcalls, the values "used by the epilogue" are
......
......@@ -55,6 +55,16 @@
(ior (match_operand 0 "const_logical_operand")
(match_operand 0 "register_operand")))
(define_predicate "const_and_operand"
(and (match_code "const_int")
(match_test "SMALL_INT_UNSIGNED (INTVAL (op))
|| UPPER16_INT (INTVAL (op))
|| (TARGET_ARCH_R2 && ANDCLEAR_INT (INTVAL (op)))")))
(define_predicate "and_operand"
(ior (match_operand 0 "const_and_operand")
(match_operand 0 "register_operand")))
(define_predicate "const_shift_operand"
(and (match_code "const_int")
(match_test "SHIFT_INT (INTVAL (op))")))
......@@ -84,6 +94,16 @@
false));
})
(define_predicate "stack_memory_operand"
(match_code "mem")
{
rtx addr = XEXP (op, 0);
return ((REG_P (addr) && REGNO (addr) == SP_REGNO)
|| (GET_CODE (addr) == PLUS
&& REG_P (XEXP (addr, 0)) && REGNO (XEXP (addr, 0)) == SP_REGNO
&& CONST_INT_P (XEXP (addr, 1))));
})
(define_predicate "ldstio_memory_operand"
(match_code "mem")
{
......
......@@ -2991,6 +2991,9 @@ instead of @code{0} in the assembly output.
Integer that is valid as an immediate operand for
a custom instruction opcode. Range 0 to 255.
@item P
An immediate operand for R2 andchi/andci instructions.
@item S
Matches immediates which are addresses in the small
data section and therefore can be added to @code{gp}
......
2015-07-14 Sandra Loosemore <sandra@codesourcery.com>
Cesar Philippidis <cesar@codesourcery.com>
Chung-Lin Tang <cltang@codesourcery.com>
* gcc.target/nios2/andci.c: New.
* gcc.target/nios2/bmx.c: New.
* gcc.target/nios2/cdx-add.c: New.
* gcc.target/nios2/cdx-branch.c: New.
* gcc.target/nios2/cdx-callret.c: New.
* gcc.target/nios2/cdx-loadstore.c: New.
* gcc.target/nios2/cdx-logical.c: New.
* gcc.target/nios2/cdx-mov.c: New.
* gcc.target/nios2/cdx-shift.c: New.
* gcc.target/nios2/cdx-sub.c: New.
* gcc.target/nios2/nios2-trap-insn.c: Adjust pattern.
2015-07-14 Andrea Azzarone <azzaronea@gmail.com>
PR c++/65071
......
/* { dg-do compile } */
/* { dg-options "-O2 -march=r2" } */
/* Test generation of Nios II R2 "andci" and "andchi" instructions. */
unsigned int f (unsigned int a)
{
return a & 0xfffffff0;
}
unsigned int g (unsigned int b)
{
return b & 0xfff0ffff;
}
/* { dg-final { scan-assembler "\tandci\t.*" } } */
/* { dg-final { scan-assembler "\tandchi\t.*" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -march=r2 -mbmx" } */
/* Test generation of Nios II R2 BMX instructions. */
struct s {
unsigned int pad1 : 3;
unsigned int bitfield : 20;
unsigned int intfield;
};
void f (struct s *a, struct s *b)
{
a->bitfield = b->bitfield;
}
void g (struct s *a, struct s *b)
{
a->bitfield = b->intfield;
}
void h (struct s *a, struct s *b)
{
a->intfield = b->bitfield;
}
/* { dg-final { scan-assembler "\tmerge\t.*, 22, 3" } } */
/* { dg-final { scan-assembler "\tinsert\t.*, 22, 3" } } */
/* { dg-final { scan-assembler "\textract\t.*, 22, 3" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -march=r2 -mcdx" } */
/* Check generation of R2 CDX add.n and addi.n instructions. */
int f (int a, int b)
{
return a + b;
}
int g (int a)
{
return a + 32;
}
int h (int a)
{
return a + 33;
}
/* { dg-final { scan-assembler "\tadd\\.n\t.*" } } */
/* { dg-final { scan-assembler "\taddi\\.n\t.*, 32" } } */
/* { dg-final { scan-assembler "\taddi\t.*, 33" } } */
/* { dg-do compile } */
/* { dg-options "-Os -march=r2 -mcdx" } */
/* Check generation of R2 CDX br.n, beqz.n, bnez.n instructions. */
int f (int a, int b, int c)
{
if (a == 0)
return b;
else
return c;
}
int g (int a, int b, int c)
{
if (a != 0)
return b;
else
return c;
}
extern int i (int);
extern int j (int);
extern int k (int);
int h (int a)
{
int x;
/* As well as the conditional branch for the "if", there has to be
an unconditional branch from one branch of the "if" to
the return statement. We compile this testcase with -Os to
avoid insertion of a duplicate epilogue in place of the branch. */
if (a == 1)
x = i (37);
else
x = j (42);
return x + a + k (x);
}
/* { dg-final { scan-assembler "\tbeqz\\.n\t.*" } } */
/* { dg-final { scan-assembler "\tbnez\\.n\t.*" } } */
/* { dg-final { scan-assembler "\tbeq\t|\tbne\t" } } */
/* { dg-final { scan-assembler "\tbr\\.n\t.*" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -march=r2 -mcdx" } */
/* Check generation of R2 CDX callr.n, jmpr.n, ret.n instructions. */
typedef int (*F) (void);
int x (F f)
{
f ();
/* Note that the compiler might generate a return via pop.n or ldwm;
the test below is to make sure that it doesn't generate a 32-bit
return instruction. */
return 3;
}
int y (F f)
{
return f ();
}
/* { dg-final { scan-assembler "\tcallr\\.n\t.*" } } */
/* { dg-final { scan-assembler-not "\tret$" } } */
/* { dg-final { scan-assembler "\tjmpr\\.n\t.*" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -march=r2 -mcdx" } */
/* Check generation of R2 CDX load/store instructions. */
unsigned char ldb (unsigned char *p)
{
return p[7];
}
unsigned short ldh (unsigned short *p)
{
return p[7];
}
unsigned int ldw (unsigned int *p)
{
return p[7];
}
void stb (unsigned char *p, unsigned char x)
{
p[15] = x;
}
void sth (unsigned short *p, unsigned short x)
{
p[15] = x;
}
void stw (unsigned int *p, unsigned int x)
{
p[15] = x;
}
void no_cdx_stb (unsigned char *p, unsigned char x)
{
p[16] = x;
}
void no_cdx_sth (unsigned short *p, unsigned short x)
{
p[16] = x;
}
void no_cdx_stw (unsigned int *p, unsigned int x)
{
p[16] = x;
}
/* { dg-final { scan-assembler "\tldbu\\.n\t.*, 7\\(.*\\)" } } */
/* { dg-final { scan-assembler "\tldhu\\.n\t.*, 14\\(.*\\)" } } */
/* { dg-final { scan-assembler "\tldw\\.n\t.*, 28\\(.*\\)" } } */
/* { dg-final { scan-assembler "\tstb\\.n\t.*, 15\\(.*\\)" } } */
/* { dg-final { scan-assembler "\tsth\\.n\t.*, 30\\(.*\\)" } } */
/* { dg-final { scan-assembler "\tstw\\.n\t.*, 60\\(.*\\)" } } */
/* { dg-final { scan-assembler "\tstb\t.*, 16\\(.*\\)" } } */
/* { dg-final { scan-assembler "\tsth\t.*, 32\\(.*\\)" } } */
/* { dg-final { scan-assembler "\tstw\t.*, 64\\(.*\\)" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -march=r2 -mcdx" } */
/* Check generation of R2 CDX and.n, andi.n, or.n, xor.n, and not.n
instructions.
and.n, or.n, and x.n require one of the input registers to be the same
as the output register. Since the tests below want to put the result
in the return value register, they use this function to make sure that
one of the input operands is also already in the return register. */
extern unsigned int x (unsigned int a);
unsigned int f (unsigned int a, unsigned int b)
{
return x (a) & b;
}
unsigned int g (unsigned int a)
{
return a & 31;
}
unsigned int h (unsigned int a, unsigned int b)
{
return x (a) | b;
}
unsigned int i (unsigned int a, unsigned int b)
{
return x (a) ^ b;
}
unsigned int j (unsigned int a)
{
return ~a;
}
/* { dg-final { scan-assembler "\tand\\.n\t.*" } } */
/* { dg-final { scan-assembler "\tandi\\.n\t.*, 31" } } */
/* { dg-final { scan-assembler "\tor\\.n\t.*" } } */
/* { dg-final { scan-assembler "\txor\\.n\t.*" } } */
/* { dg-final { scan-assembler "\tnot\\.n\t.*" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -march=r2 -mcdx" } */
/* Check generation of R2 CDX mov.n and movi.n instructions. */
extern void f (int a, int b, int c, int d);
int g (int x, int y, int z)
{
f (100, x, y, z);
return -1;
}
/* We should always get mov.n and never mov when compiling with -mcdx. */
/* { dg-final { scan-assembler "\tmov\\.n\t.*" } } */
/* { dg-final { scan-assembler-not "\tmov\t.*" } } */
/* Both of the constant loads are expressible with movi.n. */
/* { dg-final { scan-assembler "\tmovi\\.n\t.*, 100" } } */
/* { dg-final { scan-assembler "\tmovi\\.n\t.*, -1" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -march=r2 -mcdx" } */
/* Check generation of R2 CDX and.n, andi.n, or.n, xor.n, and not.n
instructions. */
extern unsigned int x (unsigned int a);
unsigned int f (unsigned int a, unsigned int b)
{
return x (a) << b;
}
unsigned int g (unsigned int a)
{
return x (a) << 24;
}
unsigned int h (unsigned int a, unsigned int b)
{
return x (a) >> b;
}
unsigned int i (unsigned int a, unsigned int b)
{
return x (a) >> 24;
}
/* { dg-final { scan-assembler "\tsll\\.n\t.*" } } */
/* { dg-final { scan-assembler "\tslli\\.n\t.*, 24" } } */
/* { dg-final { scan-assembler "\tsrl\\.n\t.*" } } */
/* { dg-final { scan-assembler "\tsrli\\.n\t.*, 24" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -march=r2 -mcdx" } */
/* Check generation of R2 CDX sub.n, subi.n, and neg.n instructions. */
int f (int a, int b)
{
return a - b;
}
int g (int a)
{
return a - 32;
}
int h (int a)
{
return -a;
}
/* { dg-final { scan-assembler "\tsub\\.n\t.*" } } */
/* { dg-final { scan-assembler "\tsubi\\.n\t.*, 32" } } */
/* { dg-final { scan-assembler "\tneg\\.n\t.*" } } */
/* { dg-do compile } */
/* { dg-final { scan-assembler "trap\\t3" } } */
/* { dg-final { scan-assembler "trap\\t3|trap.n\\t3" } } */
/* Test the nios2 trap instruction */
void foo(void){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment