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:
Jim Wilson 1997-10-18 05:46:19 +00:00 committed by Jeff Law
parent 13c2de98de
commit 1933ec7e4e
4 changed files with 233 additions and 133 deletions

View File

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

View File

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

View File

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

View File

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