v850.c (ep_memory_offset): New function.
* v850.c (ep_memory_offset): New function. (ep_memory_operand, substitute_ep_register, v850_reorg): Call it. * v850.h (CONST_OK_FOR_*): Add and correct comments. (CONSTANT_ADDRESS_P): Add comment. (EXTRA_CONSTRAINT): Define 'U'. * v850.md: Add comments on bit field instructions. (addsi3): Delete &r/r/r alternative. Add r/r/U alternative. (lshrsi3): Use N not J constraint. * v850.md (v850_tst1+1): New define_split for tst1 instruction. * v850.c (reg_or_0_operand): Call register_operand. (reg_or_int5_operand): Likewise. * v850.h (MASK_BIG_SWITCH, TARGET_BIG_SWITCH): New macros. (TARGET_SWITCHES): Add "big-switch". (ASM_OUTPUT_ADDR_VEC_ELT, ASM_OUTPUT_ADDR_DIFF_ELT, CASE_VECTOR_MODE, ASM_OUTPUT_BEFORE_BASE_LABEL): Add support for TARGET_BIG_SWITCH. (CASE_DROPS_THROUGH): Comment out. (CASE_VECTOR_PC_RELATIVE, JUMP_TABLES_IN_TEXT_SECTION): Define. * v850.md (cmpsi): Delete compare mode. (casesi): New pattern. * v850.h (CONST_OK_FOR_N): Delete redundant compare against zero. * v850.md (ashlsi3): Use SImode not QImode for shift count. (lshrsi3): Likewise. * v850.c (print_operand): Add 'c', 'C', and 'z' support. Delete unreachable switch statement after 'b' support. Remove "b" from strings for 'b' support. * v850.md (branch_normal, branch_invert): Change %b to b%b. v850 patches from Jim. From-SVN: r15992
This commit is contained in:
parent
13c2de98de
commit
1933ec7e4e
@ -1,3 +1,37 @@
|
||||
Fri Oct 17 23:48:52 1997 Jim Wilson (wilson@cygnus.com)
|
||||
|
||||
* v850.c (ep_memory_offset): New function.
|
||||
(ep_memory_operand, substitute_ep_register, v850_reorg): Call it.
|
||||
|
||||
* v850.h (CONST_OK_FOR_*): Add and correct comments.
|
||||
(CONSTANT_ADDRESS_P): Add comment.
|
||||
(EXTRA_CONSTRAINT): Define 'U'.
|
||||
* v850.md: Add comments on bit field instructions.
|
||||
(addsi3): Delete &r/r/r alternative. Add r/r/U alternative.
|
||||
(lshrsi3): Use N not J constraint.
|
||||
|
||||
* v850.md (v850_tst1+1): New define_split for tst1 instruction.
|
||||
|
||||
* v850.c (reg_or_0_operand): Call register_operand.
|
||||
(reg_or_int5_operand): Likewise.
|
||||
* v850.h (MASK_BIG_SWITCH, TARGET_BIG_SWITCH): New macros.
|
||||
(TARGET_SWITCHES): Add "big-switch".
|
||||
(ASM_OUTPUT_ADDR_VEC_ELT, ASM_OUTPUT_ADDR_DIFF_ELT, CASE_VECTOR_MODE,
|
||||
ASM_OUTPUT_BEFORE_BASE_LABEL): Add support for TARGET_BIG_SWITCH.
|
||||
(CASE_DROPS_THROUGH): Comment out.
|
||||
(CASE_VECTOR_PC_RELATIVE, JUMP_TABLES_IN_TEXT_SECTION): Define.
|
||||
* v850.md (cmpsi): Delete compare mode.
|
||||
(casesi): New pattern.
|
||||
|
||||
* v850.h (CONST_OK_FOR_N): Delete redundant compare against zero.
|
||||
* v850.md (ashlsi3): Use SImode not QImode for shift count.
|
||||
(lshrsi3): Likewise.
|
||||
|
||||
* v850.c (print_operand): Add 'c', 'C', and 'z' support. Delete
|
||||
unreachable switch statement after 'b' support. Remove "b" from
|
||||
strings for 'b' support.
|
||||
* v850.md (branch_normal, branch_invert): Change %b to b%b.
|
||||
|
||||
Fri Oct 17 23:33:20 1997 Jeffrey A Law (law@cygnus.com)
|
||||
|
||||
* Makefile.in (LIBGCC2_CFLAGS): Avoid a backslash then an
|
||||
|
@ -307,73 +307,46 @@ print_operand (file, x, code)
|
||||
{
|
||||
case 'b':
|
||||
case 'B':
|
||||
switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
|
||||
case 'c':
|
||||
case 'C':
|
||||
switch ((code == 'B' || code == 'C')
|
||||
? reverse_condition (GET_CODE (x)) : GET_CODE (x))
|
||||
{
|
||||
case NE:
|
||||
fprintf (file, "bne");
|
||||
if (code == 'c' || code == 'C')
|
||||
fprintf (file, "nz");
|
||||
else
|
||||
fprintf (file, "ne");
|
||||
break;
|
||||
case EQ:
|
||||
fprintf (file, "be");
|
||||
if (code == 'c' || code == 'C')
|
||||
fprintf (file, "z");
|
||||
else
|
||||
fprintf (file, "e");
|
||||
break;
|
||||
case GE:
|
||||
fprintf (file, "bge");
|
||||
fprintf (file, "ge");
|
||||
break;
|
||||
case GT:
|
||||
fprintf (file, "bgt");
|
||||
fprintf (file, "gt");
|
||||
break;
|
||||
case LE:
|
||||
fprintf (file, "ble");
|
||||
fprintf (file, "le");
|
||||
break;
|
||||
case LT:
|
||||
fprintf (file, "blt");
|
||||
fprintf (file, "lt");
|
||||
break;
|
||||
case GEU:
|
||||
fprintf (file, "bnl");
|
||||
fprintf (file, "nl");
|
||||
break;
|
||||
case GTU:
|
||||
fprintf (file, "bh");
|
||||
fprintf (file, "h");
|
||||
break;
|
||||
case LEU:
|
||||
fprintf (file, "bnh");
|
||||
fprintf (file, "nh");
|
||||
break;
|
||||
case LTU:
|
||||
fprintf (file, "bl");
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
break;
|
||||
switch (GET_CODE (x))
|
||||
{
|
||||
case NE:
|
||||
fprintf (file, "be");
|
||||
break;
|
||||
case EQ:
|
||||
fprintf (file, "bne");
|
||||
break;
|
||||
case GE:
|
||||
fprintf (file, "blt");
|
||||
break;
|
||||
case GT:
|
||||
fprintf (file, "bgt");
|
||||
break;
|
||||
case LE:
|
||||
fprintf (file, "ble");
|
||||
break;
|
||||
case LT:
|
||||
fprintf (file, "blt");
|
||||
break;
|
||||
case GEU:
|
||||
fprintf (file, "bnl");
|
||||
break;
|
||||
case GTU:
|
||||
fprintf (file, "bh");
|
||||
break;
|
||||
case LEU:
|
||||
fprintf (file, "bnh");
|
||||
break;
|
||||
case LTU:
|
||||
fprintf (file, "bl");
|
||||
fprintf (file, "l");
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
@ -504,6 +477,14 @@ print_operand (file, x, code)
|
||||
case '.': /* register r0 */
|
||||
fputs (reg_names[0], file);
|
||||
break;
|
||||
case 'z': /* reg or zero */
|
||||
if (x == const0_rtx)
|
||||
fputs (reg_names[0], file);
|
||||
else if (GET_CODE (x) == REG)
|
||||
fputs (reg_names[REGNO (x)], file);
|
||||
else
|
||||
abort ();
|
||||
break;
|
||||
default:
|
||||
switch (GET_CODE (x))
|
||||
{
|
||||
@ -821,6 +802,35 @@ output_move_double (operands)
|
||||
}
|
||||
|
||||
|
||||
/* Return maximum offset supported for a short EP memory reference of mode
|
||||
MODE and signedness UNSIGNEDP. */
|
||||
|
||||
int
|
||||
ep_memory_offset (mode, unsignedp)
|
||||
enum machine_mode mode;
|
||||
int unsignedp;
|
||||
{
|
||||
int max_offset = 0;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case QImode:
|
||||
max_offset = (1 << 7);
|
||||
break;
|
||||
|
||||
case HImode:
|
||||
max_offset = (1 << 8);
|
||||
break;
|
||||
|
||||
case SImode:
|
||||
case SFmode:
|
||||
max_offset = (1 << 8);
|
||||
break;
|
||||
}
|
||||
|
||||
return max_offset;
|
||||
}
|
||||
|
||||
/* Return true if OP is a valid short EP memory reference */
|
||||
|
||||
int
|
||||
@ -836,27 +846,9 @@ ep_memory_operand (op, mode, unsigned_load)
|
||||
if (GET_CODE (op) != MEM)
|
||||
return FALSE;
|
||||
|
||||
switch (GET_MODE (op))
|
||||
{
|
||||
default:
|
||||
return FALSE;
|
||||
max_offset = ep_memory_offset (mode, unsigned_load);
|
||||
|
||||
case QImode:
|
||||
max_offset = (1 << 7);
|
||||
mask = 0;
|
||||
break;
|
||||
|
||||
case HImode:
|
||||
max_offset = (1 << 8);
|
||||
mask = 1;
|
||||
break;
|
||||
|
||||
case SImode:
|
||||
case SFmode:
|
||||
max_offset = (1 << 8);
|
||||
mask = 3;
|
||||
break;
|
||||
}
|
||||
mask = GET_MODE_SIZE (mode) - 1;
|
||||
|
||||
addr = XEXP (op, 0);
|
||||
if (GET_CODE (addr) == CONST)
|
||||
@ -905,23 +897,8 @@ reg_or_0_operand (op, mode)
|
||||
else if (GET_CODE (op) == CONST_DOUBLE)
|
||||
return CONST_DOUBLE_OK_FOR_G (op);
|
||||
|
||||
else if (GET_CODE (op) == REG)
|
||||
return TRUE;
|
||||
|
||||
else if (GET_CODE (op) == SUBREG)
|
||||
{
|
||||
do {
|
||||
op = SUBREG_REG (op);
|
||||
} while (GET_CODE (op) == SUBREG);
|
||||
|
||||
if (GET_CODE (op) == MEM && !reload_completed)
|
||||
return TRUE;
|
||||
|
||||
else if (GET_CODE (op) == REG)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
else
|
||||
return register_operand (op, mode);
|
||||
}
|
||||
|
||||
/* Return true if OP is either a register or a signed five bit integer */
|
||||
@ -934,23 +911,8 @@ reg_or_int5_operand (op, mode)
|
||||
if (GET_CODE (op) == CONST_INT)
|
||||
return CONST_OK_FOR_J (INTVAL (op));
|
||||
|
||||
else if (GET_CODE (op) == REG)
|
||||
return TRUE;
|
||||
|
||||
else if (GET_CODE (op) == SUBREG)
|
||||
{
|
||||
do {
|
||||
op = SUBREG_REG (op);
|
||||
} while (GET_CODE (op) == SUBREG);
|
||||
|
||||
if (GET_CODE (op) == MEM && !reload_completed)
|
||||
return TRUE;
|
||||
|
||||
else if (GET_CODE (op) == REG)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
else
|
||||
return register_operand (op, mode);
|
||||
}
|
||||
|
||||
/* Return true if OP is a valid call operand. */
|
||||
@ -1083,6 +1045,8 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
|
||||
if (pattern)
|
||||
{
|
||||
rtx *p_mem;
|
||||
/* Memory operands are signed by default. */
|
||||
int unsignedp = FALSE;
|
||||
|
||||
if (GET_CODE (SET_DEST (pattern)) == MEM
|
||||
&& GET_CODE (SET_SRC (pattern)) == MEM)
|
||||
@ -1108,9 +1072,9 @@ substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
|
||||
&& GET_CODE (XEXP (addr, 0)) == REG
|
||||
&& REGNO (XEXP (addr, 0)) == regno
|
||||
&& GET_CODE (XEXP (addr, 1)) == CONST_INT
|
||||
&& ((unsigned)INTVAL (XEXP (addr, 1))) < 256
|
||||
&& (GET_MODE (*p_mem) != QImode
|
||||
|| ((unsigned)INTVAL (XEXP (addr, 1))) < 128))
|
||||
&& (((unsigned)INTVAL (XEXP (addr, 1)))
|
||||
< ep_memory_offset (GET_MODE (*p_mem),
|
||||
unsignedp)))
|
||||
*p_mem = change_address (*p_mem, VOIDmode,
|
||||
gen_rtx (PLUS, Pmode,
|
||||
*p_ep, XEXP (addr, 1)));
|
||||
@ -1216,6 +1180,8 @@ void v850_reorg (start_insn)
|
||||
rtx src = SET_SRC (pattern);
|
||||
rtx dest = SET_DEST (pattern);
|
||||
rtx mem;
|
||||
/* Memory operands are signed by default. */
|
||||
int unsignedp = FALSE;
|
||||
|
||||
if (GET_CODE (dest) == MEM && GET_CODE (src) == MEM)
|
||||
mem = NULL_RTX;
|
||||
@ -1229,7 +1195,7 @@ void v850_reorg (start_insn)
|
||||
else
|
||||
mem = NULL_RTX;
|
||||
|
||||
if (mem && ep_memory_operand (mem, GET_MODE (mem), FALSE))
|
||||
if (mem && ep_memory_operand (mem, GET_MODE (mem), unsignedp))
|
||||
use_ep = TRUE;
|
||||
|
||||
else if (!use_ep && mem
|
||||
@ -1248,9 +1214,8 @@ void v850_reorg (start_insn)
|
||||
else if (GET_CODE (addr) == PLUS
|
||||
&& GET_CODE (XEXP (addr, 0)) == REG
|
||||
&& GET_CODE (XEXP (addr, 1)) == CONST_INT
|
||||
&& ((unsigned)INTVAL (XEXP (addr, 1))) < 256
|
||||
&& (GET_MODE (mem) != QImode
|
||||
|| ((unsigned)INTVAL (XEXP (addr, 1))) < 128))
|
||||
&& (((unsigned)INTVAL (XEXP (addr, 1)))
|
||||
< ep_memory_offset (GET_MODE (mem), unsignedp)))
|
||||
{
|
||||
short_p = TRUE;
|
||||
regno = REGNO (XEXP (addr, 0));
|
||||
|
@ -58,6 +58,8 @@ extern int target_flags;
|
||||
#define MASK_CPU 0x00000030
|
||||
#define MASK_V850 0x00000010
|
||||
|
||||
#define MASK_BIG_SWITCH 0x00000100
|
||||
|
||||
#ifndef MASK_DEFAULT
|
||||
#define MASK_DEFAULT MASK_V850
|
||||
#endif
|
||||
@ -97,6 +99,9 @@ extern int target_flags;
|
||||
/* Whether to call out-of-line functions to save registers or not. */
|
||||
#define TARGET_PROLOG_FUNCTION (target_flags & MASK_PROLOG_FUNCTION)
|
||||
|
||||
/* Whether to emit 2 byte per entry or 4 byte per entry switch tables. */
|
||||
#define TARGET_BIG_SWITCH (target_flags & MASK_BIG_SWITCH)
|
||||
|
||||
/* General debug flag */
|
||||
#define TARGET_DEBUG (target_flags & MASK_DEBUG)
|
||||
|
||||
@ -119,6 +124,7 @@ extern int target_flags;
|
||||
{ "debug", MASK_DEBUG }, \
|
||||
{ "v850", MASK_V850 }, \
|
||||
{ "v850", -(MASK_V850 ^ MASK_CPU) }, \
|
||||
{ "big-switch", MASK_BIG_SWITCH }, \
|
||||
EXTRA_SWITCHES \
|
||||
{ "", TARGET_DEFAULT}}
|
||||
|
||||
@ -468,19 +474,21 @@ enum reg_class {
|
||||
|
||||
#define INT_7_BITS(VALUE) ((unsigned) (VALUE) + 0x40 < 0x80)
|
||||
#define INT_8_BITS(VALUE) ((unsigned) (VALUE) + 0x80 < 0x100)
|
||||
/* 0 bits */
|
||||
/* zero */
|
||||
#define CONST_OK_FOR_I(VALUE) ((VALUE) == 0)
|
||||
/* 4 bits */
|
||||
/* 5 bit signed immediate */
|
||||
#define CONST_OK_FOR_J(VALUE) ((unsigned) (VALUE) + 0x10 < 0x20)
|
||||
/* 15 bits */
|
||||
/* 16 bit signed immediate */
|
||||
#define CONST_OK_FOR_K(VALUE) ((unsigned) (VALUE) + 0x8000 < 0x10000)
|
||||
/* valid constant for movhi instruction. */
|
||||
#define CONST_OK_FOR_L(VALUE) \
|
||||
(((unsigned) ((int) (VALUE) >> 16) + 0x8000 < 0x10000) \
|
||||
&& CONST_OK_FOR_I ((VALUE & 0xffff)))
|
||||
/* 16 bits */
|
||||
#define CONST_OK_FOR_M(VALUE) ((unsigned)(VALUE) < 0x10000
|
||||
/* 16 bit unsigned immediate */
|
||||
#define CONST_OK_FOR_M(VALUE) ((unsigned)(VALUE) < 0x10000)
|
||||
/* 5 bit unsigned immediate in shift instructions */
|
||||
#define CONST_OK_FOR_N(VALUE) ((unsigned) (VALUE) <= 31)
|
||||
|
||||
#define CONST_OK_FOR_N(VALUE) ((unsigned) VALUE >= 0 && (unsigned) VALUE <= 31) /* 5 bit signed immediate in shift instructions */
|
||||
#define CONST_OK_FOR_O(VALUE) 0
|
||||
#define CONST_OK_FOR_P(VALUE) 0
|
||||
|
||||
@ -799,6 +807,9 @@ extern int current_function_anonymous_args;
|
||||
|
||||
/* 1 if X is an rtx for a constant that is a valid address. */
|
||||
|
||||
/* ??? This seems too exclusive. May get better code by accepting more
|
||||
possibilities here, in particular, should accept ZDA_NAME SYMBOL_REFs. */
|
||||
|
||||
#define CONSTANT_ADDRESS_P(X) \
|
||||
(GET_CODE (X) == CONST_INT \
|
||||
&& CONST_OK_FOR_K (INTVAL (X)))
|
||||
@ -864,7 +875,11 @@ extern int current_function_anonymous_args;
|
||||
: (C) == 'R' ? special_symbolref_operand (OP, VOIDmode) \
|
||||
: (C) == 'S' ? (GET_CODE (OP) == SYMBOL_REF && ! ZDA_NAME_P (XSTR (OP, 0))) \
|
||||
: (C) == 'T' ? 0 \
|
||||
: (C) == 'U' ? 0 \
|
||||
: (C) == 'U' ? ((GET_CODE (OP) == SYMBOL_REF && ZDA_NAME_P (XSTR (OP, 0))) \
|
||||
|| (GET_CODE (OP) == CONST \
|
||||
&& GET_CODE (XEXP (OP, 0)) == PLUS \
|
||||
&& GET_CODE (XEXP (XEXP (OP, 0), 0)) == SYMBOL_REF \
|
||||
&& ZDA_NAME_P (XSTR (XEXP (XEXP (OP, 0), 0), 0)))) \
|
||||
: 0)
|
||||
|
||||
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
|
||||
@ -1266,12 +1281,15 @@ do { char dstr[30]; \
|
||||
/* This is how to output an element of a case-vector that is absolute. */
|
||||
|
||||
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
|
||||
asm_fprintf (FILE, "\t%s .L%d\n", ".long", VALUE)
|
||||
asm_fprintf (FILE, "\t%s .L%d\n", \
|
||||
(TARGET_BIG_SWITCH ? ".long" : ".short"), VALUE)
|
||||
|
||||
/* This is how to output an element of a case-vector that is relative. */
|
||||
|
||||
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
|
||||
fprintf (FILE, "\t%s .L%d-.L%d\n", ".long", VALUE, REL)
|
||||
fprintf (FILE, "\t%s .L%d-.L%d\n", \
|
||||
(TARGET_BIG_SWITCH ? ".long" : ".short"), \
|
||||
VALUE, REL)
|
||||
|
||||
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
|
||||
if ((LOG) != 0) \
|
||||
@ -1292,12 +1310,26 @@ do { char dstr[30]; \
|
||||
|
||||
/* Specify the machine mode that this machine uses
|
||||
for the index in the tablejump instruction. */
|
||||
#define CASE_VECTOR_MODE Pmode
|
||||
#define CASE_VECTOR_MODE (TARGET_BIG_SWITCH ? SImode : HImode)
|
||||
|
||||
/* Define this if the case instruction drops through after the table
|
||||
when the index is out of range. Don't define it if the case insn
|
||||
jumps to the default label instead. */
|
||||
#define CASE_DROPS_THROUGH
|
||||
/* #define CASE_DROPS_THROUGH */
|
||||
|
||||
/* We must use a PC relative entry for small tables. It would be more
|
||||
efficient to use an absolute entry for big tables, but this is not
|
||||
a runtime choice yet. */
|
||||
#define CASE_VECTOR_PC_RELATIVE
|
||||
|
||||
/* The switch instruction requires that the jump table immediately follow
|
||||
it. */
|
||||
#define JUMP_TABLES_IN_TEXT_SECTION
|
||||
|
||||
/* svr4.h defines this assuming that 4 byte alignment is required. */
|
||||
#undef ASM_OUTPUT_BEFORE_CASE_LABEL
|
||||
#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
|
||||
ASM_OUTPUT_ALIGN ((FILE), (TARGET_BIG_SWITCH ? 2 : 1));
|
||||
|
||||
#define WORD_REGISTER_OPERATIONS
|
||||
|
||||
|
@ -263,6 +263,22 @@
|
||||
[(set_attr "length" "4")
|
||||
(set_attr "cc" "clobber")])
|
||||
|
||||
;; This replaces ld.b;sar;andi with tst1;setf nz.
|
||||
|
||||
;; ??? The zero_extract sets the Z bit to the opposite of what one would
|
||||
;; expect. This perhaps should be wrapped in a (eq: X (const_int 0)).
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:SI 0 "register_operand" "")
|
||||
(zero_extract:SI (match_operand:QI 1 "memory_operand" "")
|
||||
(const_int 1)
|
||||
(match_operand 2 "const_int_operand" "")))]
|
||||
""
|
||||
[(set (cc0) (zero_extract:SI (match_dup 1)
|
||||
(const_int 1)
|
||||
(match_dup 2)))
|
||||
(set (match_dup 0) (ne:SI (cc0) (const_int 0)))])
|
||||
|
||||
(define_insn "tstsi"
|
||||
[(set (cc0) (match_operand:SI 0 "register_operand" "r"))]
|
||||
""
|
||||
@ -272,8 +288,8 @@
|
||||
|
||||
(define_insn "cmpsi"
|
||||
[(set (cc0)
|
||||
(compare:SI (match_operand:SI 0 "register_operand" "r,r")
|
||||
(match_operand:SI 1 "reg_or_int5_operand" "r,J")))]
|
||||
(compare (match_operand:SI 0 "register_operand" "r,r")
|
||||
(match_operand:SI 1 "reg_or_int5_operand" "r,J")))]
|
||||
""
|
||||
"@
|
||||
cmp %1,%0
|
||||
@ -286,16 +302,16 @@
|
||||
;; ----------------------------------------------------------------------
|
||||
|
||||
(define_insn "addsi3"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r,&r")
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
|
||||
(plus:SI (match_operand:SI 1 "register_operand" "%0,r,r")
|
||||
(match_operand:SI 2 "nonmemory_operand" "rJ,K,r")))]
|
||||
(match_operand:SI 2 "nonmemory_operand" "rJ,K,U")))]
|
||||
""
|
||||
"@
|
||||
add %2,%0
|
||||
addi %2,%1,%0
|
||||
mov %1,%0\;add %2,%0"
|
||||
[(set_attr "length" "2,4,6")
|
||||
(set_attr "cc" "set_zn")])
|
||||
addi %O2(%P2),%1,%0"
|
||||
[(set_attr "length" "2,4,4")
|
||||
(set_attr "cc" "set_zn,set_zn,set_zn")])
|
||||
|
||||
;; ----------------------------------------------------------------------
|
||||
;; SUBTRACT INSTRUCTIONS
|
||||
@ -592,7 +608,16 @@
|
||||
;; -----------------------------------------------------------------
|
||||
;; BIT FIELDS
|
||||
;; -----------------------------------------------------------------
|
||||
;; Is it worth defining insv and extv for the V850 series?!?
|
||||
|
||||
;; ??? Is it worth defining insv and extv for the V850 series?!?
|
||||
|
||||
;; An insv pattern would be useful, but does not get used because
|
||||
;; store_bit_field never calls insv when storing a constant value into a
|
||||
;; single-bit bitfield.
|
||||
|
||||
;; extv/extzv patterns would be useful, but do not get used because
|
||||
;; optimize_bitfield_compare in fold-const usually converts single
|
||||
;; bit extracts into an AND with a mask.
|
||||
|
||||
;; -----------------------------------------------------------------
|
||||
;; Scc INSTRUCTIONS
|
||||
@ -816,9 +841,9 @@
|
||||
return 0;
|
||||
|
||||
if (get_attr_length (insn) == 2)
|
||||
return \"%b1 %l0\";
|
||||
return \"b%b1 %l0\";
|
||||
else
|
||||
return \"%B1 .+6\;jr %l0\";
|
||||
return \"b%B1 .+6\;jr %l0\";
|
||||
}"
|
||||
[(set (attr "length")
|
||||
(if_then_else (lt (abs (minus (match_dup 0) (pc)))
|
||||
@ -843,9 +868,9 @@
|
||||
|| GET_CODE (operands[1]) == LT))
|
||||
return 0;
|
||||
if (get_attr_length (insn) == 2)
|
||||
return \"%B1 %l0\";
|
||||
return \"b%B1 %l0\";
|
||||
else
|
||||
return \"%b1 .+6\;jr %l0\";
|
||||
return \"b%b1 .+6\;jr %l0\";
|
||||
}"
|
||||
[(set (attr "length")
|
||||
(if_then_else (lt (abs (minus (match_dup 0) (pc)))
|
||||
@ -889,6 +914,50 @@
|
||||
[(set_attr "length" "2")
|
||||
(set_attr "cc" "none")])
|
||||
|
||||
(define_expand "casesi"
|
||||
[(match_operand:SI 0 "register_operand" "")
|
||||
(match_operand:SI 1 "register_operand" "")
|
||||
(match_operand:SI 2 "register_operand" "")
|
||||
(match_operand 3 "" "") (match_operand 4 "" "")]
|
||||
""
|
||||
"
|
||||
{
|
||||
rtx reg = gen_reg_rtx (SImode);
|
||||
rtx tableaddress = gen_reg_rtx (SImode);
|
||||
rtx mem;
|
||||
|
||||
/* Subtract the lower bound from the index. */
|
||||
emit_insn (gen_subsi3 (reg, operands[0], operands[1]));
|
||||
/* Compare the result against the number of table entries. */
|
||||
emit_insn (gen_cmpsi (reg, operands[2]));
|
||||
/* Branch to the default label if out of range of the table. */
|
||||
emit_jump_insn (gen_bgtu (operands[4]));
|
||||
|
||||
/* Shift index for the table array access. */
|
||||
emit_insn (gen_ashlsi3 (reg, reg, GEN_INT (TARGET_BIG_SWITCH ? 2 : 1)));
|
||||
/* Load the table address into a psuedo. */
|
||||
emit_insn (gen_movsi (tableaddress,
|
||||
gen_rtx (LABEL_REF, VOIDmode, operands[3])));
|
||||
/* Add the table address to the index. */
|
||||
emit_insn (gen_addsi3 (reg, reg, tableaddress));
|
||||
/* Load the table entry. */
|
||||
mem = gen_rtx (MEM, CASE_VECTOR_MODE, reg);
|
||||
RTX_UNCHANGING_P (mem);
|
||||
if (! TARGET_BIG_SWITCH)
|
||||
{
|
||||
rtx reg2 = gen_reg_rtx (HImode);
|
||||
emit_insn (gen_movhi (reg2, mem));
|
||||
emit_insn (gen_extendhisi2 (reg, reg2));
|
||||
}
|
||||
else
|
||||
emit_insn (gen_movsi (reg, mem));
|
||||
/* Add the table address. */
|
||||
emit_insn (gen_addsi3 (reg, reg, tableaddress));
|
||||
/* Branch to the switch label. */
|
||||
emit_jump_insn (gen_tablejump (reg, operands[3]));
|
||||
DONE;
|
||||
}")
|
||||
|
||||
;; Call subroutine with no return value.
|
||||
|
||||
(define_expand "call"
|
||||
@ -1021,7 +1090,7 @@
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
(ashift:SI
|
||||
(match_operand:SI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "r,N")))]
|
||||
(match_operand:SI 2 "nonmemory_operand" "r,N")))]
|
||||
""
|
||||
"@
|
||||
shl %2,%0
|
||||
@ -1033,7 +1102,7 @@
|
||||
[(set (match_operand:SI 0 "register_operand" "=r,r")
|
||||
(lshiftrt:SI
|
||||
(match_operand:SI 1 "register_operand" "0,0")
|
||||
(match_operand:QI 2 "nonmemory_operand" "r,J")))]
|
||||
(match_operand:SI 2 "nonmemory_operand" "r,N")))]
|
||||
""
|
||||
"@
|
||||
shr %2,%0
|
||||
|
Loading…
Reference in New Issue
Block a user