Commit 82348675 by Sandra Loosemore Committed by Sandra Loosemore

nios2-protos.h (nios2_large_constant_p): Declare.

2017-10-23  Sandra Loosemore  <sandra@codesourcery.com>

	gcc/
	* config/nios2/nios2-protos.h (nios2_large_constant_p): Declare.
	(nios2_symbolic_memory_operand_p): Declare.
	(nios2_split_large_constant): Declare.
	(nios2_split_symbolic_memory_operand): Declare.
	* config/nios2/nios2.c: Adjust includes.
	(nios2_symbolic_constant_allowed): New.
	(nios2_symbolic_constant_p): New.
	(nios2_plus_symbolic_constant_p): New.
	(nios2_valid_addr_expr_p): Recognize addresses involving 
	symbolic constants.
	(nios2_legitimate_address_p): Likewise, also LO_SUM.
	(nios2_symbolic_memory_operand_p): New.
	(nios2_large_constant_p): New.
	(nios2_split_large_constant): New.
	(nios2_split_plus_large_constant): New.
	(nios2_split_symbolic_memory_operand): New.
	(nios2_legitimize_address): Code refactoring.  Handle addresses
	involving symbolic constants.
	(nios2_emit_move_sequence): Likewise.
	(nios2_print_operand): Improve error output.
	(nios2_print_operand_address): Handle LO_SUM.
	(nios2_cdx_narrow_form_p): Likewise.
	* config/nios2/nios2.md (movqi_internal): Add splitter for memory
	operands involving symbolic constants.
	(movhi_internal, movsi_internal): Likewise.
	(zero_extendhisi2, zero_extendqi<mode>2): Likewise.
	(extendhisi2, extendqi<mode>2): Likewise.

From-SVN: r254033
parent 6642bfb2
2017-10-23 Sandra Loosemore <sandra@codesourcery.com> 2017-10-23 Sandra Loosemore <sandra@codesourcery.com>
* config/nios2/nios2-protos.h (nios2_large_constant_p): Declare.
(nios2_symbolic_memory_operand_p): Declare.
(nios2_split_large_constant): Declare.
(nios2_split_symbolic_memory_operand): Declare.
* config/nios2/nios2.c: Adjust includes.
(nios2_symbolic_constant_allowed): New.
(nios2_symbolic_constant_p): New.
(nios2_plus_symbolic_constant_p): New.
(nios2_valid_addr_expr_p): Recognize addresses involving
symbolic constants.
(nios2_legitimate_address_p): Likewise, also LO_SUM.
(nios2_symbolic_memory_operand_p): New.
(nios2_large_constant_p): New.
(nios2_split_large_constant): New.
(nios2_split_plus_large_constant): New.
(nios2_split_symbolic_memory_operand): New.
(nios2_legitimize_address): Code refactoring. Handle addresses
involving symbolic constants.
(nios2_emit_move_sequence): Likewise.
(nios2_print_operand): Improve error output.
(nios2_print_operand_address): Handle LO_SUM.
(nios2_cdx_narrow_form_p): Likewise.
* config/nios2/nios2.md (movqi_internal): Add splitter for memory
operands involving symbolic constants.
(movhi_internal, movsi_internal): Likewise.
(zero_extendhisi2, zero_extendqi<mode>2): Likewise.
(extendhisi2, extendqi<mode>2): Likewise.
2017-10-23 Sandra Loosemore <sandra@codesourcery.com>
* tree-pass.h (PROP_rtl_split_insns): Define. * tree-pass.h (PROP_rtl_split_insns): Define.
* recog.c (pass_data_split_all_insns): Provide PROP_rtl_split_insns. * recog.c (pass_data_split_all_insns): Provide PROP_rtl_split_insns.
...@@ -30,6 +30,11 @@ extern bool nios2_expand_return (void); ...@@ -30,6 +30,11 @@ extern bool nios2_expand_return (void);
extern void nios2_function_profiler (FILE *, int); extern void nios2_function_profiler (FILE *, int);
#ifdef RTX_CODE #ifdef RTX_CODE
extern bool nios2_large_constant_p (rtx);
extern bool nios2_symbolic_memory_operand_p (rtx);
extern rtx nios2_split_large_constant (rtx, rtx);
extern rtx nios2_split_symbolic_memory_operand (rtx);
extern bool nios2_emit_move_sequence (rtx *, machine_mode); extern bool nios2_emit_move_sequence (rtx *, machine_mode);
extern void nios2_emit_expensive_div (rtx *, machine_mode); extern void nios2_emit_expensive_div (rtx *, machine_mode);
extern void nios2_adjust_call_address (rtx *, rtx); extern void nios2_adjust_call_address (rtx *, rtx);
......
...@@ -48,11 +48,13 @@ ...@@ -48,11 +48,13 @@
#include "langhooks.h" #include "langhooks.h"
#include "stor-layout.h" #include "stor-layout.h"
#include "builtins.h" #include "builtins.h"
#include "tree-pass.h"
/* This file should be included last. */ /* This file should be included last. */
#include "target-def.h" #include "target-def.h"
/* Forward function declarations. */ /* Forward function declarations. */
static bool nios2_symbolic_constant_p (rtx);
static bool prologue_saved_reg_p (unsigned); static bool prologue_saved_reg_p (unsigned);
static void nios2_load_pic_register (void); static void nios2_load_pic_register (void);
static void nios2_register_custom_code (unsigned int, enum nios2_ccs_code, int); static void nios2_register_custom_code (unsigned int, enum nios2_ccs_code, int);
...@@ -1902,7 +1904,52 @@ nios2_validate_compare (machine_mode mode, rtx *cmp, rtx *op1, rtx *op2) ...@@ -1902,7 +1904,52 @@ nios2_validate_compare (machine_mode mode, rtx *cmp, rtx *op1, rtx *op2)
} }
/* Addressing Modes. */ /* Addressing modes and constants. */
/* Symbolic constants are split into high/lo_sum pairs during the
split1 pass. After that, they are not considered legitimate addresses.
This function returns true if in a pre-split context where these
constants are allowed. */
static bool
nios2_symbolic_constant_allowed (void)
{
/* The reload_completed check is for the benefit of
nios2_asm_output_mi_thunk and perhaps other places that try to
emulate a post-reload pass. */
return !(cfun->curr_properties & PROP_rtl_split_insns) && !reload_completed;
}
/* Return true if X is constant expression with a reference to an
"ordinary" symbol; not GOT-relative, not GP-relative, not TLS. */
static bool
nios2_symbolic_constant_p (rtx x)
{
rtx base, offset;
if (flag_pic)
return false;
if (GET_CODE (x) == LABEL_REF)
return true;
else if (CONSTANT_P (x))
{
split_const (x, &base, &offset);
return (SYMBOL_REF_P (base)
&& !SYMBOL_REF_TLS_MODEL (base)
&& !gprel_constant_p (base)
&& SMALL_INT (INTVAL (offset)));
}
return false;
}
/* Return true if X is an expression of the form
(PLUS reg symbolic_constant). */
static bool
nios2_plus_symbolic_constant_p (rtx x)
{
return (GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0))
&& nios2_symbolic_constant_p (XEXP (x, 1)));
}
/* Implement TARGET_LEGITIMATE_CONSTANT_P. */ /* Implement TARGET_LEGITIMATE_CONSTANT_P. */
static bool static bool
...@@ -1971,6 +2018,8 @@ nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p) ...@@ -1971,6 +2018,8 @@ nios2_valid_addr_expr_p (rtx base, rtx offset, bool strict_p)
&& nios2_regno_ok_for_base_p (REGNO (base), strict_p) && nios2_regno_ok_for_base_p (REGNO (base), strict_p)
&& (offset == NULL_RTX && (offset == NULL_RTX
|| nios2_valid_addr_offset_p (offset) || nios2_valid_addr_offset_p (offset)
|| (nios2_symbolic_constant_allowed ()
&& nios2_symbolic_constant_p (offset))
|| nios2_unspec_reloc_p (offset))); || nios2_unspec_reloc_p (offset)));
} }
...@@ -1993,6 +2042,11 @@ nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, ...@@ -1993,6 +2042,11 @@ nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
/* Else, fall through. */ /* Else, fall through. */
case LABEL_REF: case LABEL_REF:
if (nios2_symbolic_constant_allowed ()
&& nios2_symbolic_constant_p (operand))
return true;
/* Else, fall through. */
case CONST_INT: case CONST_INT:
case CONST_DOUBLE: case CONST_DOUBLE:
return false; return false;
...@@ -2007,8 +2061,27 @@ nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, ...@@ -2007,8 +2061,27 @@ nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
rtx op0 = XEXP (operand, 0); rtx op0 = XEXP (operand, 0);
rtx op1 = XEXP (operand, 1); rtx op1 = XEXP (operand, 1);
return (nios2_valid_addr_expr_p (op0, op1, strict_p) if (nios2_valid_addr_expr_p (op0, op1, strict_p)
|| nios2_valid_addr_expr_p (op1, op0, strict_p)); || nios2_valid_addr_expr_p (op1, op0, strict_p))
return true;
}
break;
/* %lo(constant)(reg)
This requires a 16-bit relocation and isn't valid with R2
io-variant load/stores. */
case LO_SUM:
if (TARGET_ARCH_R2
&& (TARGET_BYPASS_CACHE || TARGET_BYPASS_CACHE_VOLATILE))
return false;
else
{
rtx op0 = XEXP (operand, 0);
rtx op1 = XEXP (operand, 1);
return (REG_P (op0)
&& nios2_regno_ok_for_base_p (REGNO (op0), strict_p)
&& nios2_large_constant_p (op1));
} }
default: default:
...@@ -2017,6 +2090,75 @@ nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED, ...@@ -2017,6 +2090,75 @@ nios2_legitimate_address_p (machine_mode mode ATTRIBUTE_UNUSED,
return false; return false;
} }
/* Return true if X is a MEM whose address expression involves a symbolic
constant. */
bool
nios2_symbolic_memory_operand_p (rtx x)
{
rtx addr;
if (GET_CODE (x) != MEM)
return false;
addr = XEXP (x, 0);
return (nios2_symbolic_constant_p (addr)
|| nios2_plus_symbolic_constant_p (addr));
}
/* Return true if X is something that needs to be split into a
high/lo_sum pair. */
bool
nios2_large_constant_p (rtx x)
{
return (nios2_symbolic_constant_p (x)
|| nios2_large_unspec_reloc_p (x));
}
/* Given an RTX X that satisfies nios2_large_constant_p, split it into
high and lo_sum parts using TEMP as a scratch register. Emit the high
instruction and return the lo_sum expression. */
rtx
nios2_split_large_constant (rtx x, rtx temp)
{
emit_insn (gen_rtx_SET (temp, gen_rtx_HIGH (Pmode, copy_rtx (x))));
return gen_rtx_LO_SUM (Pmode, temp, copy_rtx (x));
}
/* Split an RTX of the form
(plus op0 op1)
where op1 is a large constant into
(set temp (high op1))
(set temp (plus op0 temp))
(lo_sum temp op1)
returning the lo_sum expression as the value. */
static rtx
nios2_split_plus_large_constant (rtx op0, rtx op1)
{
rtx temp = gen_reg_rtx (Pmode);
op0 = force_reg (Pmode, op0);
emit_insn (gen_rtx_SET (temp, gen_rtx_HIGH (Pmode, copy_rtx (op1))));
emit_insn (gen_rtx_SET (temp, gen_rtx_PLUS (Pmode, op0, temp)));
return gen_rtx_LO_SUM (Pmode, temp, copy_rtx (op1));
}
/* Given a MEM OP with an address that includes a splittable symbol,
emit some instructions to do the split and return a new MEM. */
rtx
nios2_split_symbolic_memory_operand (rtx op)
{
rtx addr = XEXP (op, 0);
if (nios2_symbolic_constant_p (addr))
addr = nios2_split_large_constant (addr, gen_reg_rtx (Pmode));
else if (nios2_plus_symbolic_constant_p (addr))
addr = nios2_split_plus_large_constant (XEXP (addr, 0), XEXP (addr, 1));
else
gcc_unreachable ();
return replace_equiv_address (op, addr, false);
}
/* Return true if SECTION is a small section name. */ /* Return true if SECTION is a small section name. */
static bool static bool
nios2_small_section_name_p (const char *section) nios2_small_section_name_p (const char *section)
...@@ -2219,6 +2361,9 @@ nios2_legitimize_constant_address (rtx addr) ...@@ -2219,6 +2361,9 @@ nios2_legitimize_constant_address (rtx addr)
base = nios2_legitimize_tls_address (base); base = nios2_legitimize_tls_address (base);
else if (flag_pic) else if (flag_pic)
base = nios2_load_pic_address (base, UNSPEC_PIC_SYM, NULL_RTX); base = nios2_load_pic_address (base, UNSPEC_PIC_SYM, NULL_RTX);
else if (!nios2_symbolic_constant_allowed ()
&& nios2_symbolic_constant_p (addr))
return nios2_split_large_constant (addr, gen_reg_rtx (Pmode));
else else
return addr; return addr;
...@@ -2239,9 +2384,27 @@ static rtx ...@@ -2239,9 +2384,27 @@ static rtx
nios2_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, nios2_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
machine_mode mode ATTRIBUTE_UNUSED) machine_mode mode ATTRIBUTE_UNUSED)
{ {
rtx op0, op1;
if (CONSTANT_P (x)) if (CONSTANT_P (x))
return nios2_legitimize_constant_address (x); return nios2_legitimize_constant_address (x);
/* Remaining cases all involve something + a constant. */
if (GET_CODE (x) != PLUS)
return x;
op0 = XEXP (x, 0);
op1 = XEXP (x, 1);
/* We may need to split symbolic constants now. */
if (nios2_symbolic_constant_p (op1))
{
if (nios2_symbolic_constant_allowed ())
return gen_rtx_PLUS (Pmode, force_reg (Pmode, op0), copy_rtx (op1));
else
return nios2_split_plus_large_constant (op0, op1);
}
/* For the TLS LE (Local Exec) model, the compiler may try to /* For the TLS LE (Local Exec) model, the compiler may try to
combine constant offsets with unspec relocs, creating address RTXs combine constant offsets with unspec relocs, creating address RTXs
looking like this: looking like this:
...@@ -2264,20 +2427,19 @@ nios2_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, ...@@ -2264,20 +2427,19 @@ nios2_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
(const_int 48 [0x30])))] UNSPEC_ADD_TLS_LE))) (const_int 48 [0x30])))] UNSPEC_ADD_TLS_LE)))
Which will be output as '%tls_le(var+48)(r23)' in assembly. */ Which will be output as '%tls_le(var+48)(r23)' in assembly. */
if (GET_CODE (x) == PLUS else if (GET_CODE (op1) == CONST)
&& GET_CODE (XEXP (x, 1)) == CONST)
{ {
rtx unspec, offset; rtx unspec, offset;
split_const (XEXP (x, 1), &unspec, &offset); split_const (op1, &unspec, &offset);
if (GET_CODE (unspec) == UNSPEC if (GET_CODE (unspec) == UNSPEC
&& !nios2_large_offset_p (XINT (unspec, 1)) && !nios2_large_offset_p (XINT (unspec, 1))
&& offset != const0_rtx) && offset != const0_rtx)
{ {
rtx reg = force_reg (Pmode, XEXP (x, 0)); rtx reg = force_reg (Pmode, op0);
unspec = copy_rtx (unspec); unspec = copy_rtx (unspec);
XVECEXP (unspec, 0, 0) XVECEXP (unspec, 0, 0)
= plus_constant (Pmode, XVECEXP (unspec, 0, 0), INTVAL (offset)); = plus_constant (Pmode, XVECEXP (unspec, 0, 0), INTVAL (offset));
x = gen_rtx_PLUS (Pmode, reg, gen_rtx_CONST (Pmode, unspec)); return gen_rtx_PLUS (Pmode, reg, gen_rtx_CONST (Pmode, unspec));
} }
} }
...@@ -2338,9 +2500,27 @@ nios2_emit_move_sequence (rtx *operands, machine_mode mode) ...@@ -2338,9 +2500,27 @@ nios2_emit_move_sequence (rtx *operands, machine_mode mode)
return true; return true;
} }
} }
else if (!gprel_constant_p (from)) else if (gprel_constant_p (from))
/* Handled directly by movsi_internal as gp + offset. */
;
else if (nios2_large_constant_p (from))
/* This case covers either a regular symbol reference or an UNSPEC
representing a 32-bit offset. We split the former
only conditionally and the latter always. */
{
if (!nios2_symbolic_constant_allowed ()
|| nios2_large_unspec_reloc_p (from))
{
rtx lo = nios2_split_large_constant (from, to);
emit_insn (gen_rtx_SET (to, lo));
set_unique_reg_note (get_last_insn (), REG_EQUAL,
copy_rtx (operands[1]));
return true;
}
}
else
/* This is a TLS or PIC symbol. */
{ {
if (!nios2_large_unspec_reloc_p (from))
from = nios2_legitimize_constant_address (from); from = nios2_legitimize_constant_address (from);
if (CONSTANT_P (from)) if (CONSTANT_P (from))
{ {
...@@ -2652,6 +2832,7 @@ nios2_print_operand (FILE *file, rtx op, int letter) ...@@ -2652,6 +2832,7 @@ nios2_print_operand (FILE *file, rtx op, int letter)
break; break;
} }
debug_rtx (op);
output_operand_lossage ("Unsupported operand for code '%c'", letter); output_operand_lossage ("Unsupported operand for code '%c'", letter);
gcc_unreachable (); gcc_unreachable ();
} }
...@@ -2757,6 +2938,20 @@ nios2_print_operand_address (FILE *file, machine_mode mode, rtx op) ...@@ -2757,6 +2938,20 @@ nios2_print_operand_address (FILE *file, machine_mode mode, rtx op)
} }
break; break;
case LO_SUM:
{
rtx op0 = XEXP (op, 0);
rtx op1 = XEXP (op, 1);
if (REG_P (op0) && CONSTANT_P (op1))
{
nios2_print_operand (file, op1, 'L');
fprintf (file, "(%s)", reg_names[REGNO (op0)]);
return;
}
}
break;
case REG: case REG:
fprintf (file, "0(%s)", reg_names[REGNO (op)]); fprintf (file, "0(%s)", reg_names[REGNO (op)]);
return; return;
...@@ -4329,6 +4524,9 @@ nios2_cdx_narrow_form_p (rtx_insn *insn) ...@@ -4329,6 +4524,9 @@ nios2_cdx_narrow_form_p (rtx_insn *insn)
/* GP-based references are never narrow. */ /* GP-based references are never narrow. */
if (gprel_constant_p (addr)) if (gprel_constant_p (addr))
return false; return false;
/* %lo requires a 16-bit relocation and is never narrow. */
if (GET_CODE (addr) == LO_SUM)
return false;
ret = split_mem_address (addr, &rhs1, &rhs2); ret = split_mem_address (addr, &rhs1, &rhs2);
gcc_assert (ret); gcc_assert (ret);
} }
...@@ -4373,6 +4571,9 @@ nios2_cdx_narrow_form_p (rtx_insn *insn) ...@@ -4373,6 +4571,9 @@ nios2_cdx_narrow_form_p (rtx_insn *insn)
/* GP-based references are never narrow. */ /* GP-based references are never narrow. */
if (gprel_constant_p (addr)) if (gprel_constant_p (addr))
return false; return false;
/* %lo requires a 16-bit relocation and is never narrow. */
if (GET_CODE (addr) == LO_SUM)
return false;
ret = split_mem_address (addr, &rhs1, &rhs2); ret = split_mem_address (addr, &rhs1, &rhs2);
gcc_assert (ret); gcc_assert (ret);
offset = INTVAL (rhs2); offset = INTVAL (rhs2);
......
...@@ -201,7 +201,7 @@ ...@@ -201,7 +201,7 @@
"addi\\t%0, %1, %L2" "addi\\t%0, %1, %L2"
[(set_attr "type" "alu")]) [(set_attr "type" "alu")])
(define_insn "movqi_internal" (define_insn_and_split "movqi_internal"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r") [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r")
(match_operand:QI 1 "general_operand" "rM,m,rI"))] (match_operand:QI 1 "general_operand" "rM,m,rI"))]
"(register_operand (operands[0], QImode) "(register_operand (operands[0], QImode)
...@@ -224,20 +224,47 @@ ...@@ -224,20 +224,47 @@
gcc_unreachable (); gcc_unreachable ();
} }
} }
"(nios2_symbolic_memory_operand_p (operands[0])
|| nios2_symbolic_memory_operand_p (operands[1]))"
[(set (match_dup 0) (match_dup 1))]
{
if (nios2_symbolic_memory_operand_p (operands[0]))
operands[0] = nios2_split_symbolic_memory_operand (operands[0]);
else
operands[1] = nios2_split_symbolic_memory_operand (operands[1]);
}
[(set_attr "type" "st,ld,mov")]) [(set_attr "type" "st,ld,mov")])
(define_insn "movhi_internal" (define_insn_and_split "movhi_internal"
[(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r") [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r")
(match_operand:HI 1 "general_operand" "rM,m,rI"))] (match_operand:HI 1 "general_operand" "rM,m,rI"))]
"(register_operand (operands[0], HImode) "(register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode))" || reg_or_0_operand (operands[1], HImode))"
"@ {
sth%o0%.\\t%z1, %0 switch (which_alternative)
ldhu%o1%.\\t%0, %1 {
mov%i1%.\\t%0, %z1" case 0:
return "sth%o0%.\\t%z1, %0";
case 1:
return "ldhu%o1%.\\t%0, %1";
case 2:
return "mov%i1%.\\t%0, %z1";
default:
gcc_unreachable ();
}
}
"(nios2_symbolic_memory_operand_p (operands[0])
|| nios2_symbolic_memory_operand_p (operands[1]))"
[(set (match_dup 0) (match_dup 1))]
{
if (nios2_symbolic_memory_operand_p (operands[0]))
operands[0] = nios2_split_symbolic_memory_operand (operands[0]);
else
operands[1] = nios2_split_symbolic_memory_operand (operands[1]);
}
[(set_attr "type" "st,ld,mov")]) [(set_attr "type" "st,ld,mov")])
(define_insn "movsi_internal" (define_insn_and_split "movsi_internal"
[(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r") [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r")
(match_operand:SI 1 "general_operand" "rM,m,rIJK,S"))] (match_operand:SI 1 "general_operand" "rM,m,rIJK,S"))]
"(register_operand (operands[0], SImode) "(register_operand (operands[0], SImode)
...@@ -269,6 +296,18 @@ ...@@ -269,6 +296,18 @@
gcc_unreachable (); gcc_unreachable ();
} }
} }
"(nios2_symbolic_memory_operand_p (operands[0])
|| nios2_symbolic_memory_operand_p (operands[1])
|| nios2_large_constant_p (operands[1]))"
[(set (match_dup 0) (match_dup 1))]
{
if (nios2_symbolic_memory_operand_p (operands[0]))
operands[0] = nios2_split_symbolic_memory_operand (operands[0]);
else if (nios2_symbolic_memory_operand_p (operands[1]))
operands[1] = nios2_split_symbolic_memory_operand (operands[1]);
else
operands[1] = nios2_split_large_constant (operands[1], operands[0]);
}
[(set_attr "type" "st,ld,mov,alu")]) [(set_attr "type" "st,ld,mov,alu")])
(define_mode_iterator BH [QI HI]) (define_mode_iterator BH [QI HI])
...@@ -318,42 +357,62 @@ ...@@ -318,42 +357,62 @@
(define_mode_iterator QX [HI SI]) (define_mode_iterator QX [HI SI])
;; Zero extension patterns ;; Zero extension patterns
(define_insn "zero_extendhisi2" (define_insn_and_split "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r") [(set (match_operand:SI 0 "register_operand" "=r,r")
(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
"" ""
"@ "@
andi%.\\t%0, %1, 0xffff andi%.\\t%0, %1, 0xffff
ldhu%o1%.\\t%0, %1" ldhu%o1%.\\t%0, %1"
"nios2_symbolic_memory_operand_p (operands[1])"
[(set (match_dup 0) (zero_extend:SI (match_dup 1)))]
{
operands[1] = nios2_split_symbolic_memory_operand (operands[1]);
}
[(set_attr "type" "and,ld")]) [(set_attr "type" "and,ld")])
(define_insn "zero_extendqi<mode>2" (define_insn_and_split "zero_extendqi<mode>2"
[(set (match_operand:QX 0 "register_operand" "=r,r") [(set (match_operand:QX 0 "register_operand" "=r,r")
(zero_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))] (zero_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
"" ""
"@ "@
andi%.\\t%0, %1, 0xff andi%.\\t%0, %1, 0xff
ldbu%o1%.\\t%0, %1" ldbu%o1%.\\t%0, %1"
"nios2_symbolic_memory_operand_p (operands[1])"
[(set (match_dup 0) (zero_extend:QX (match_dup 1)))]
{
operands[1] = nios2_split_symbolic_memory_operand (operands[1]);
}
[(set_attr "type" "and,ld")]) [(set_attr "type" "and,ld")])
;; Sign extension patterns ;; Sign extension patterns
(define_insn "extendhisi2" (define_insn_and_split "extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r,r") [(set (match_operand:SI 0 "register_operand" "=r,r")
(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
"" ""
"@ "@
# #
ldh%o1%.\\t%0, %1" ldh%o1%.\\t%0, %1"
"nios2_symbolic_memory_operand_p (operands[1])"
[(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
{
operands[1] = nios2_split_symbolic_memory_operand (operands[1]);
}
[(set_attr "type" "alu,ld")]) [(set_attr "type" "alu,ld")])
(define_insn "extendqi<mode>2" (define_insn_and_split "extendqi<mode>2"
[(set (match_operand:QX 0 "register_operand" "=r,r") [(set (match_operand:QX 0 "register_operand" "=r,r")
(sign_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))] (sign_extend:QX (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
"" ""
"@ "@
# #
ldb%o1%.\\t%0, %1" ldb%o1%.\\t%0, %1"
"nios2_symbolic_memory_operand_p (operands[1])"
[(set (match_dup 0) (sign_extend:QX (match_dup 1)))]
{
operands[1] = nios2_split_symbolic_memory_operand (operands[1]);
}
[(set_attr "type" "alu,ld")]) [(set_attr "type" "alu,ld")])
;; Split patterns for register alternative cases. ;; Split patterns for register alternative cases.
......
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