This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Add support for v850e processor
- From: Nick Clifton <nickc at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: 27 Aug 2002 21:00:56 +0100
- Subject: Add support for v850e processor
Hi Guys,
I am going to apply the attached patch to add support to GCC to
generate code for the NEC V850E processor. This is a variant of the
V850 processor with some extra instructions. The port was developed
by Red Hat and we now have permission from NEC to contribute it.
Cheers
Nick
2002-08-27 Nick Clifton <nickc@redhat.com>
Catherine Moore <clm@redhat.com>
Jim Wilson <wilson@cygnus.com>
* config.gcc: Add v850e-*-* target.
Add --with-cpu= support for v850.
* config/v850/lib1funcs.asm: Add v850e callt functions.
* config/v850/v850.h: Add support for v850e target.
* config/v850/v850.c: Add functions to support v850e target.
* config/v850/v850-protos.h: Add prototypes for new functions in v850.c.
* config/v850/v850.md: Add patterns for v850e instructions.
* doc/invoke.texi: Document new v850e command line switches.
Index: gcc/config.gcc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.gcc,v
retrieving revision 1.240
diff -c -3 -p -w -r1.240 config.gcc
*** gcc/config.gcc 20 Aug 2002 21:53:27 -0000 1.240
--- gcc/config.gcc 27 Aug 2002 19:56:37 -0000
*************** v850-*-rtems*)
*** 2643,2648 ****
--- 2643,2663 ----
c_target_objs="v850-c.o"
cxx_target_objs="v850-c.o"
;;
+ v850e-*-*)
+ target_cpu_default="TARGET_CPU_v850e"
+ tm_file="dbxelf.h elfos.h svr4.h v850/v850.h"
+ tm_p_file=v850/v850-protos.h
+ tmake_file=v850/t-v850
+ md_file=v850/v850.md
+ out_file=v850/v850.c
+ if test x$stabs = xyes
+ then
+ tm_file="${tm_file} dbx.h"
+ fi
+ use_collect2=no
+ c_target_objs="v850-c.o"
+ cxx_target_objs="v850-c.o"
+ ;;
v850-*-*)
target_cpu_default="TARGET_CPU_generic"
tm_file="dbxelf.h elfos.h svr4.h ${tm_file}"
*************** sparc*-*-*)
*** 2941,2946 ****
--- 2956,2977 ----
target_cpu_default2=TARGET_CPU_"`echo $machine | sed 's/-.*$//'`"
;;
.supersparc | .hypersparc | .ultrasparc | .v7 | .v8 | .v9)
+ target_cpu_default2="TARGET_CPU_$with_cpu"
+ ;;
+ *)
+ if test x$pass2done = xyes
+ then
+ echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2
+ exit 1
+ fi
+ ;;
+ esac
+ ;;
+ v850*-*-*)
+ case "x$with_cpu" in
+ x)
+ ;;
+ v850e)
target_cpu_default2="TARGET_CPU_$with_cpu"
;;
*)
Index: gcc/config/v850/lib1funcs.asm
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/v850/lib1funcs.asm,v
retrieving revision 1.12
diff -c -3 -p -w -r1.12 lib1funcs.asm
*** gcc/config/v850/lib1funcs.asm 17 May 2001 03:16:14 -0000 1.12
--- gcc/config/v850/lib1funcs.asm 27 Aug 2002 19:56:38 -0000
***************
*** 1,5 ****
/* libgcc routines for NEC V850.
! Copyright (C) 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
--- 1,5 ----
/* libgcc routines for NEC V850.
! Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
*************** __return_r29_r31:
*** 1114,1120 ****
.type __save_r31,@function
/* Allocate space and save register 31 on the stack */
/* Also allocate space for the argument save area */
! /* Called via: jalr __save_r29_r31,r10 */
__save_r31:
addi -20,sp,sp
st.w r31,16[sp]
--- 1114,1120 ----
.type __save_r31,@function
/* Allocate space and save register 31 on the stack */
/* Also allocate space for the argument save area */
! /* Called via: jalr __save_r31,r10 */
__save_r31:
addi -20,sp,sp
st.w r31,16[sp]
*************** __return_r31:
*** 1130,1136 ****
ld.w 16[sp],r31
addi 20,sp,sp
jmp [r31]
! .size __return_r29_r31,.-__return_r29_r31
#endif /* L_save_31c */
#ifdef L_save_varargs
--- 1130,1136 ----
ld.w 16[sp],r31
addi 20,sp,sp
jmp [r31]
! .size __return_r31,.-__return_r31
#endif /* L_save_31c */
#ifdef L_save_varargs
*************** __restore_all_interrupt:
*** 1267,1269 ****
--- 1267,1644 ----
jmp [r10]
.size __restore_all_interrupt,.-__restore_all_interrupt
#endif /* L_save_all_interrupt */
+
+
+ #if defined __v850e__
+ #ifdef L_callt_save_r2_r29
+ /* Put these functions into the call table area. */
+ .call_table_text
+
+ /* Allocate space and save registers 2, 20 .. 29 on the stack. */
+ /* Called via: callt ctoff(__callt_save_r2_r29). */
+ .align 2
+ .L_save_r2_r29:
+ add -4, sp
+ st.w r2, 0[sp]
+ prepare {r20 - r29}, 0
+ ctret
+
+ /* Restore saved registers, deallocate stack and return to the user. */
+ /* Called via: callt ctoff(__callt_return_r2_r29). */
+ .align 2
+ .L_return_r2_r29:
+ dispose 0, {r20-r29}
+ ld.w 0[sp], r2
+ add 4, sp
+ jmp [r31]
+
+ /* Place the offsets of the start of these routines into the call table. */
+ .call_table_data
+
+ .global __callt_save_r2_r29
+ .type __callt_save_r2_r29,@function
+ __callt_save_r2_r29: .short ctoff(.L_save_r2_r29)
+
+ .global __callt_return_r2_r29
+ .type __callt_return_r2_r29,@function
+ __callt_return_r2_r29: .short ctoff(.L_return_r2_r29)
+
+ #endif /* L_callt_save_r2_r29 */
+
+ #ifdef L_callt_save_r2_r31
+ /* Put these functions into the call table area. */
+ .call_table_text
+
+ /* Allocate space and save registers 2 and 20 .. 29, 31 on the stack. */
+ /* Also allocate space for the argument save area. */
+ /* Called via: callt ctoff(__callt_save_r2_r31). */
+ .align 2
+ .L_save_r2_r31:
+ add -4, sp
+ st.w r2, 0[sp]
+ prepare {r20 - r29, r31}, 4
+ ctret
+
+ /* Restore saved registers, deallocate stack and return to the user. */
+ /* Called via: callt ctoff(__callt_return_r2_r31). */
+ .align 2
+ .L_return_r2_r31:
+ dispose 4, {r20 - r29, r31}
+ ld.w 0[sp], r2
+ addi 4, sp, sp
+ jmp [r31]
+
+ /* Place the offsets of the start of these routines into the call table. */
+ .call_table_data
+
+ .global __callt_save_r2_r31
+ .type __callt_save_r2_r31,@function
+ __callt_save_r2_r31: .short ctoff(.L_save_r2_r31)
+
+ .global __callt_return_r2_r31
+ .type __callt_return_r2_r31,@function
+ __callt_return_r2_r31: .short ctoff(.L_return_r2_r31)
+
+ #endif /* L_callt_save_r2_r31 */
+
+
+ #ifdef L_callt_save_r6_r9
+ /* Put these functions into the call table area. */
+ .call_table_text
+
+ /* Save registers r6 - r9 onto the stack in the space reserved for them.
+ Use by variable argument functions.
+ Called via: callt ctoff(__callt_save_r6_r9). */
+ .align 2
+ .L_save_r6_r9:
+ mov ep,r1
+ mov sp,ep
+ sst.w r6,0[ep]
+ sst.w r7,4[ep]
+ sst.w r8,8[ep]
+ sst.w r9,12[ep]
+ mov r1,ep
+ ctret
+
+ /* Place the offsets of the start of this routines into the call table. */
+ .call_table_data
+
+ .global __callt_save_r6_r9
+ .type __callt_save_r6_r9,@function
+ __callt_save_r6_r9: .short ctoff(.L_save_r6_r9)
+ #endif /* L_callt_save_r6_r9 */
+
+
+ #ifdef L_callt_save_interrupt
+ /* Put this functions into the call table area */
+ .call_table_text
+
+ /* Save registers r1, ep, gp, r10 on stack and load up with expected values. */
+ /* Called via: callt ctoff(__callt_save_interrupt). */
+ .align 2
+ .L_save_interrupt:
+ /* SP has already been moved before callt ctoff(_save_interrupt). */
+ /* addi -24, sp, sp */
+ st.w ep, 0[sp]
+ st.w gp, 4[sp]
+ st.w r1, 8[sp]
+ /* R10 has alread been saved bofore callt ctoff(_save_interrupt). */
+ /* st.w r10, 12[sp] */
+ mov hilo(__ep),ep
+ mov hilo(__gp),gp
+ ctret
+
+ /* Place the offsets of the start of the routine into the call table. */
+ .call_table_data
+ .global __callt_save_interrupt
+ .type __callt_save_interrupt,@function
+ __callt_save_interrupt: .short ctoff(.L_save_interrupt)
+
+ .call_table_text
+
+ /* Restore saved registers, deallocate stack and return from the interrupt. */
+ /* Called via: callt ctoff(__callt_restore_itnerrupt). */
+ .text
+ .align 2
+ .globl __return_interrupt
+ .type __return_interrupt,@function
+ .L_return_interrupt:
+ ld.w 20[sp], r1
+ ldsr r1, ctpsw
+ ld.w 16[sp], r1
+ ldsr r1, ctpc
+ ld.w 12[sp], r10
+ ld.w 8[sp], r1
+ ld.w 4[sp], gp
+ ld.w 0[sp], ep
+ addi 24, sp, sp
+ reti
+
+ /* Place the offsets of the start of the routine into the call table. */
+ .call_table_data
+
+ .global __callt_return_interrupt
+ .type __callt_return_interrupt,@function
+ __callt_return_interrupt: .short ctoff(.L_return_interrupt)
+
+ #endif /* L_callt_save_interrupt */
+
+ #ifdef L_callt_save_all_interrupt
+ /* Put this functions into the call table area. */
+ .call_table_text
+
+ /* Save all registers except for those saved in __save_interrupt. */
+ /* Allocate enough stack for all of the registers & 16 bytes of space. */
+ /* Called via: callt ctoff(__callt_save_all_interrupt). */
+ .align 2
+ .L_save_all_interrupt:
+ addi -60, sp, sp
+ mov ep, r1
+ mov sp, ep
+ sst.w r2, 56[ep]
+ sst.w r5, 52[ep]
+ sst.w r6, 48[ep]
+ sst.w r7, 44[ep]
+ sst.w r8, 40[ep]
+ sst.w r9, 36[ep]
+ sst.w r11, 32[ep]
+ sst.w r12, 28[ep]
+ sst.w r13, 24[ep]
+ sst.w r14, 20[ep]
+ sst.w r15, 16[ep]
+ sst.w r16, 12[ep]
+ sst.w r17, 8[ep]
+ sst.w r18, 4[ep]
+ sst.w r19, 0[ep]
+ mov r1, ep
+
+ prepare {r20 - r29, r31}, 4
+ ctret
+
+ /* Restore all registers saved in __save_all_interrupt. */
+ /* & deallocate the stack space. */
+ /* Called via: callt ctoff(__callt_restore_all_interrupt). */
+ .align 2
+ .L_restore_all_interrupt:
+ dispose 4, {r20 - r29, r31}
+
+ mov ep, r1
+ mov sp, ep
+ sld.w 0 [ep], r19
+ sld.w 4 [ep], r18
+ sld.w 8 [ep], r17
+ sld.w 12[ep], r16
+ sld.w 16[ep], r15
+ sld.w 20[ep], r14
+ sld.w 24[ep], r13
+ sld.w 28[ep], r12
+ sld.w 32[ep], r11
+ sld.w 36[ep], r9
+ sld.w 40[ep], r8
+ sld.w 44[ep], r7
+ sld.w 48[ep], r6
+ sld.w 52[ep], r5
+ sld.w 56[ep], r2
+ mov r1, ep
+ addi 60, sp, sp
+ ctret
+
+ /* Place the offsets of the start of these routines into the call table. */
+ .call_table_data
+
+ .global __callt_save_all_interrupt
+ .type __callt_save_all_interrupt,@function
+ __callt_save_all_interrupt: .short ctoff(.L_save_all_interrupt)
+
+ .global __callt_restore_all_interrupt
+ .type __callt_restore_all_interrupt,@function
+ __callt_restore_all_interrupt: .short ctoff(.L_restore_all_interrupt)
+
+ #endif /* L_callt_save_all_interrupt */
+
+
+ #define MAKE_CALLT_FUNCS( START ) \
+ .call_table_text ;\
+ .align 2 ;\
+ /* Allocate space and save registers START .. r29 on the stack. */ ;\
+ /* Called via: callt ctoff(__callt_save_START_r29). */ ;\
+ .L_save_##START##_r29: ;\
+ prepare { START - r29 }, 0 ;\
+ ctret ;\
+ ;\
+ /* Restore saved registers, deallocate stack and return. */ ;\
+ /* Called via: callt ctoff(__return_START_r29) */ ;\
+ .align 2 ;\
+ .L_return_##START##_r29: ;\
+ dispose 0, { START - r29 }, r31 ;\
+ ;\
+ /* Place the offsets of the start of these funcs into the call table. */;\
+ .call_table_data ;\
+ ;\
+ .global __callt_save_##START##_r29 ;\
+ .type __callt_save_##START##_r29,@function ;\
+ __callt_save_##START##_r29: .short ctoff(.L_save_##START##_r29 ) ;\
+ ;\
+ .global __callt_return_##START##_r29 ;\
+ .type __callt_return_##START##_r29,@function ;\
+ __callt_return_##START##_r29: .short ctoff(.L_return_##START##_r29 )
+
+
+ #define MAKE_CALLT_CFUNCS( START ) \
+ .call_table_text ;\
+ .align 2 ;\
+ /* Allocate space and save registers START .. r31 on the stack. */ ;\
+ /* Called via: callt ctoff(__callt_save_START_r31c). */ ;\
+ .L_save_##START##_r31c: ;\
+ prepare { START - r29, r31}, 4 ;\
+ ctret ;\
+ ;\
+ /* Restore saved registers, deallocate stack and return. */ ;\
+ /* Called via: callt ctoff(__return_START_r31c). */ ;\
+ .align 2 ;\
+ .L_return_##START##_r31c: ;\
+ dispose 4, { START - r29, r31}, r31 ;\
+ ;\
+ /* Place the offsets of the start of these funcs into the call table. */;\
+ .call_table_data ;\
+ ;\
+ .global __callt_save_##START##_r31c ;\
+ .type __callt_save_##START##_r31c,@function ;\
+ __callt_save_##START##_r31c: .short ctoff(.L_save_##START##_r31c ) ;\
+ ;\
+ .global __callt_return_##START##_r31c ;\
+ .type __callt_return_##START##_r31c,@function ;\
+ __callt_return_##START##_r31c: .short ctoff(.L_return_##START##_r31c )
+
+
+ #ifdef L_callt_save_20
+ MAKE_CALLT_FUNCS (r20)
+ #endif
+ #ifdef L_callt_save_21
+ MAKE_CALLT_FUNCS (r21)
+ #endif
+ #ifdef L_callt_save_22
+ MAKE_CALLT_FUNCS (r22)
+ #endif
+ #ifdef L_callt_save_23
+ MAKE_CALLT_FUNCS (r23)
+ #endif
+ #ifdef L_callt_save_24
+ MAKE_CALLT_FUNCS (r24)
+ #endif
+ #ifdef L_callt_save_25
+ MAKE_CALLT_FUNCS (r25)
+ #endif
+ #ifdef L_callt_save_26
+ MAKE_CALLT_FUNCS (r26)
+ #endif
+ #ifdef L_callt_save_27
+ MAKE_CALLT_FUNCS (r27)
+ #endif
+ #ifdef L_callt_save_28
+ MAKE_CALLT_FUNCS (r28)
+ #endif
+ #ifdef L_callt_save_29
+ MAKE_CALLT_FUNCS (r29)
+ #endif
+
+ #ifdef L_callt_save_20c
+ MAKE_CALLT_CFUNCS (r20)
+ #endif
+ #ifdef L_callt_save_21c
+ MAKE_CALLT_CFUNCS (r21)
+ #endif
+ #ifdef L_callt_save_22c
+ MAKE_CALLT_CFUNCS (r22)
+ #endif
+ #ifdef L_callt_save_23c
+ MAKE_CALLT_CFUNCS (r23)
+ #endif
+ #ifdef L_callt_save_24c
+ MAKE_CALLT_CFUNCS (r24)
+ #endif
+ #ifdef L_callt_save_25c
+ MAKE_CALLT_CFUNCS (r25)
+ #endif
+ #ifdef L_callt_save_26c
+ MAKE_CALLT_CFUNCS (r26)
+ #endif
+ #ifdef L_callt_save_27c
+ MAKE_CALLT_CFUNCS (r27)
+ #endif
+ #ifdef L_callt_save_28c
+ MAKE_CALLT_CFUNCS (r28)
+ #endif
+ #ifdef L_callt_save_29c
+ MAKE_CALLT_CFUNCS (r29)
+ #endif
+
+
+ #ifdef L_callt_save_31c
+ .call_table_text
+ .align 2
+ /* Allocate space and save register r31 on the stack. */
+ /* Called via: callt ctoff(__callt_save_r31c). */
+ .L_callt_save_r31c:
+ prepare {r31}, 4
+ ctret
+
+ /* Restore saved registers, deallocate stack and return. */
+ /* Called via: callt ctoff(__return_r31c). */
+ .align 2
+ .L_callt_return_r31c:
+ dispose 4, {r31}, r31
+
+ /* Place the offsets of the start of these funcs into the call table. */
+ .call_table_data
+
+ .global __callt_save_r31c
+ .type __callt_save_r31c,@function
+ __callt_save_r31c: .short ctoff(.L_callt_save_r31c)
+
+ .global __callt_return_r31c
+ .type __callt_return_r31c,@function
+ __callt_return_r31c: .short ctoff(.L_callt_return_r31c)
+ #endif
+
+ #endif /* __v850e__ */
Index: gcc/config/v850/t-v850
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/v850/t-v850,v
retrieving revision 1.8
diff -c -3 -p -w -r1.8 t-v850
*** gcc/config/v850/t-v850 4 Jul 2001 14:11:55 -0000 1.8
--- gcc/config/v850/t-v850 27 Aug 2002 19:56:38 -0000
*************** LIB1ASMFUNCS = _mulsi3 \
*** 29,35 ****
_save_31c \
_save_varargs \
_save_interrupt \
! _save_all_interrupt
# We want fine grained libraries, so use the new code to build the
# floating point emulation libraries.
--- 29,62 ----
_save_31c \
_save_varargs \
_save_interrupt \
! _save_all_interrupt \
! _callt_save_20 \
! _callt_save_21 \
! _callt_save_22 \
! _callt_save_23 \
! _callt_save_24 \
! _callt_save_25 \
! _callt_save_26 \
! _callt_save_27 \
! _callt_save_28 \
! _callt_save_29 \
! _callt_save_20c \
! _callt_save_21c \
! _callt_save_22c \
! _callt_save_23c \
! _callt_save_24c \
! _callt_save_25c \
! _callt_save_26c \
! _callt_save_27c \
! _callt_save_28c \
! _callt_save_29c \
! _callt_save_31c \
! _callt_save_varargs \
! _callt_save_interrupt \
! _callt_save_all_interrupt \
! _callt_save_r2_r29 \
! _callt_save_r2_r31 \
! _callt_save_r6_r9
# We want fine grained libraries, so use the new code to build the
# floating point emulation libraries.
*************** fp-bit.c: $(srcdir)/config/fp-bit.c
*** 50,55 ****
--- 77,84 ----
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
TCFLAGS = -Wa,-mwarn-signed-overflow -Wa,-mwarn-unsigned-overflow
+ # Create non-target specific versions of the libraries
+ TCFLAGS += -mno-app-regs -msmall-sld -mv850 -D__v850e__ -Wa,-mv850any
v850-c.o: $(srcdir)/config/v850/v850-c.c $(RTL_H) $(TREE_H) $(CONFIG_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
Index: gcc/config/v850/v850-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/v850/v850-protos.h,v
retrieving revision 1.12
diff -c -3 -p -w -r1.12 v850-protos.h
*** gcc/config/v850/v850-protos.h 19 May 2002 05:23:25 -0000 1.12
--- gcc/config/v850/v850-protos.h 27 Aug 2002 19:56:38 -0000
*************** extern void notice_update_cc
*** 53,58 ****
--- 53,62 ----
extern char * construct_save_jarl PARAMS ((rtx));
extern char * construct_restore_jr PARAMS ((rtx));
#ifdef HAVE_MACHINE_MODES
+ extern char * construct_dispose_instruction PARAMS ((rtx));
+ extern char * construct_prepare_instruction PARAMS ((rtx));
+ extern int pattern_is_ok_for_prepare PARAMS ((rtx, Mmode));
+ extern int pattern_is_ok_for_dispose PARAMS ((rtx, Mmode));
extern int ep_memory_operand PARAMS ((rtx, Mmode, int));
extern int reg_or_0_operand PARAMS ((rtx, Mmode));
extern int reg_or_int5_operand PARAMS ((rtx, Mmode));
Index: gcc/config/v850/v850.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/v850/v850.c,v
retrieving revision 1.62
diff -c -3 -p -w -r1.62 v850.c
*** gcc/config/v850/v850.c 21 Aug 2002 02:41:51 -0000 1.62
--- gcc/config/v850/v850.c 27 Aug 2002 19:56:38 -0000
*************** override_options ()
*** 142,147 ****
--- 142,154 ----
}
}
}
+
+ /* Make sure that the US_BIT_SET mask has been correctly initialised. */
+ if ((target_flags & MASK_US_MASK_SET) == 0)
+ {
+ target_flags |= MASK_US_MASK_SET;
+ target_flags &= ~MASK_US_BIT_SET;
+ }
}
*************** function_arg (cum, mode, type, named)
*** 176,181 ****
--- 183,191 ----
else
size = GET_MODE_SIZE (mode);
+ if (size < 1)
+ return 0;
+
if (type)
align = TYPE_ALIGN (type) / BITS_PER_UNIT;
else
*************** print_operand_address (file, addr)
*** 696,701 ****
--- 706,743 ----
}
}
+ /* When assemble_integer is used to emit the offsets for a switch
+ table it can encounter (TRUNCATE:HI (MINUS:SI (LABEL_REF:SI) (LABEL_REF:SI))).
+ output_addr_const will normally barf at this, but it is OK to omit
+ the truncate and just emit the difference of the two labels. The
+ .hword directive will automatically handle the truncation for us.
+
+ Returns 1 if rtx was handled, 0 otherwise. */
+
+ int
+ v850_output_addr_const_extra (file, x)
+ FILE * file;
+ rtx x;
+ {
+ if (GET_CODE (x) != TRUNCATE)
+ return 0;
+
+ x = XEXP (x, 0);
+
+ /* We must also handle the case where the switch table was passed a
+ constant value and so has been collapsed. In this case the first
+ label will have been deleted. In such a case it is OK to emit
+ nothing, since the table will not be used.
+ (cf gcc.c-torture/compile/990801-1.c). */
+ if (GET_CODE (x) == MINUS
+ && GET_CODE (XEXP (x, 0)) == LABEL_REF
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == CODE_LABEL
+ && INSN_DELETED_P (XEXP (XEXP (x, 0), 0)))
+ return 1;
+
+ output_addr_const (file, x);
+ return 1;
+ }
/* Return appropriate code to load up a 1, 2, or 4 integer/floating
point value. */
*************** output_move_single (operands)
*** 716,731 ****
{
HOST_WIDE_INT value = INTVAL (src);
! if (CONST_OK_FOR_J (value)) /* signed 5 bit immediate */
return "mov %1,%0";
! else if (CONST_OK_FOR_K (value)) /* signed 16 bit immediate */
return "movea lo(%1),%.,%0";
! else if (CONST_OK_FOR_L (value)) /* upper 16 bits were set */
return "movhi hi(%1),%.,%0";
! else /* random constant */
return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
}
--- 758,776 ----
{
HOST_WIDE_INT value = INTVAL (src);
! if (CONST_OK_FOR_J (value)) /* Signed 5 bit immediate. */
return "mov %1,%0";
! else if (CONST_OK_FOR_K (value)) /* Signed 16 bit immediate. */
return "movea lo(%1),%.,%0";
! else if (CONST_OK_FOR_L (value)) /* Upper 16 bits were set. */
return "movhi hi(%1),%.,%0";
! /* A random constant. */
! else if (TARGET_V850E)
! return "mov %1,%0";
! else
return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
}
*************** output_move_single (operands)
*** 734,749 ****
HOST_WIDE_INT high, low;
const_double_split (src, &high, &low);
! if (CONST_OK_FOR_J (high)) /* signed 5 bit immediate */
return "mov %F1,%0";
! else if (CONST_OK_FOR_K (high)) /* signed 16 bit immediate */
return "movea lo(%F1),%.,%0";
! else if (CONST_OK_FOR_L (high)) /* upper 16 bits were set */
return "movhi hi(%F1),%.,%0";
! else /* random constant */
return "movhi hi(%F1),%.,%0\n\tmovea lo(%F1),%0,%0";
}
--- 779,799 ----
HOST_WIDE_INT high, low;
const_double_split (src, &high, &low);
!
! if (CONST_OK_FOR_J (high)) /* Signed 5 bit immediate. */
return "mov %F1,%0";
! else if (CONST_OK_FOR_K (high)) /* Signed 16 bit immediate. */
return "movea lo(%F1),%.,%0";
! else if (CONST_OK_FOR_L (high)) /* Upper 16 bits were set. */
return "movhi hi(%F1),%.,%0";
! /* A random constant. */
! else if (TARGET_V850E)
! return "mov %F1,%0";
!
! else
return "movhi hi(%F1),%.,%0\n\tmovea lo(%F1),%0,%0";
}
*************** output_move_single (operands)
*** 757,762 ****
--- 807,815 ----
|| GET_CODE (src) == SYMBOL_REF
|| GET_CODE (src) == CONST)
{
+ if (TARGET_V850E)
+ return "mov hilo(%1),%0";
+ else
return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
}
*************** ep_memory_offset (mode, unsignedp)
*** 881,890 ****
--- 934,957 ----
switch (mode)
{
case QImode:
+ if (TARGET_SMALL_SLD)
+ max_offset = (1 << 4);
+ else if (TARGET_V850E
+ && ( ( unsignedp && ! TARGET_US_BIT_SET)
+ || (! unsignedp && TARGET_US_BIT_SET)))
+ max_offset = (1 << 4);
+ else
max_offset = (1 << 7);
break;
case HImode:
+ if (TARGET_SMALL_SLD)
+ max_offset = (1 << 5);
+ else if (TARGET_V850E
+ && ( ( unsignedp && ! TARGET_US_BIT_SET)
+ || (! unsignedp && TARGET_US_BIT_SET)))
+ max_offset = (1 << 5);
+ else
max_offset = (1 << 8);
break;
*************** reg_or_int5_operand (op, mode)
*** 985,990 ****
--- 1052,1083 ----
return register_operand (op, mode);
}
+ /* Return true if OP is either a register or a signed nine bit integer. */
+
+ int
+ reg_or_int9_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+ {
+ if (GET_CODE (op) == CONST_INT)
+ return CONST_OK_FOR_O (INTVAL (op));
+
+ return register_operand (op, mode);
+ }
+
+ /* Return true if OP is either a register or a const integer. */
+
+ int
+ reg_or_const_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+ {
+ if (GET_CODE (op) == CONST_INT)
+ return TRUE;
+
+ return register_operand (op, mode);
+ }
+
/* Return true if OP is a valid call operand. */
int
*************** Saved %d bytes (%d uses of register %s)
*** 1129,1134 ****
--- 1222,1237 ----
else if (GET_CODE (SET_SRC (pattern)) == MEM)
p_mem = &SET_SRC (pattern);
+ else if (GET_CODE (SET_SRC (pattern)) == SIGN_EXTEND
+ && GET_CODE (XEXP (SET_SRC (pattern), 0)) == MEM)
+ p_mem = &XEXP (SET_SRC (pattern), 0);
+
+ else if (GET_CODE (SET_SRC (pattern)) == ZERO_EXTEND
+ && GET_CODE (XEXP (SET_SRC (pattern), 0)) == MEM)
+ {
+ p_mem = &XEXP (SET_SRC (pattern), 0);
+ unsignedp = TRUE;
+ }
else
p_mem = (rtx *)0;
*************** void v850_reorg (start_insn)
*** 1278,1283 ****
--- 1381,1396 ----
else if (GET_CODE (src) == MEM)
mem = src;
+ else if (GET_CODE (src) == SIGN_EXTEND
+ && GET_CODE (XEXP (src, 0)) == MEM)
+ mem = XEXP (src, 0);
+
+ else if (GET_CODE (src) == ZERO_EXTEND
+ && GET_CODE (XEXP (src, 0)) == MEM)
+ {
+ mem = XEXP (src, 0);
+ unsignedp = TRUE;
+ }
else
mem = NULL_RTX;
*************** expand_prologue ()
*** 1531,1536 ****
--- 1644,1652 ----
/* Save/setup global registers for interrupt functions right now. */
if (interrupt_handler)
{
+ if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
+ emit_insn (gen_callt_save_interrupt ());
+ else
emit_insn (gen_save_interrupt ());
actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE;
*************** expand_prologue ()
*** 1544,1549 ****
--- 1660,1668 ----
{
if (TARGET_PROLOG_FUNCTION)
{
+ if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
+ emit_insn (gen_save_r6_r9_v850e ());
+ else
emit_insn (gen_save_r6_r9 ());
}
else
*************** Saved %d bytes via prologue function (%d
*** 1656,1661 ****
--- 1775,1783 ----
/* Special case interrupt functions that save all registers for a call. */
if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
{
+ if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
+ emit_insn (gen_callt_save_all_interrupt ());
+ else
emit_insn (gen_save_all_interrupt ());
}
else
*************** Saved %d bytes via epilogue function (%d
*** 1888,1893 ****
--- 2010,2018 ----
for a call. */
if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0)
{
+ if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
+ emit_insn (gen_callt_restore_all_interrupt ());
+ else
emit_insn (gen_restore_all_interrupt ());
}
else
*************** Saved %d bytes via epilogue function (%d
*** 1926,1932 ****
/* And return or use reti for interrupt handlers. */
if (interrupt_handler)
! emit_jump_insn (gen_restore_interrupt ());
else if (actual_fsize)
emit_jump_insn (gen_return_internal ());
else
--- 2051,2062 ----
/* And return or use reti for interrupt handlers. */
if (interrupt_handler)
! {
! if (TARGET_V850E && ! TARGET_DISABLE_CALLT)
! emit_insn (gen_callt_return_interrupt ());
! else
! emit_jump_insn (gen_return_interrupt ());
! }
else if (actual_fsize)
emit_jump_insn (gen_return_internal ());
else
*************** register_is_ok_for_epilogue (op, mode)
*** 2233,2242 ****
rtx op;
enum machine_mode ATTRIBUTE_UNUSED mode;
{
! /* The save/restore routines can only cope with registers 2, and 20 - 31 */
! return (GET_CODE (op) == REG)
! && (((REGNO (op) >= 20) && REGNO (op) <= 31)
! || REGNO (op) == 2);
}
/* Return non-zero if the given RTX is suitable for collapsing into
--- 2363,2371 ----
rtx op;
enum machine_mode ATTRIBUTE_UNUSED mode;
{
! /* The save/restore routines can only cope with registers 20 - 31. */
! return ((GET_CODE (op) == REG)
! && (((REGNO (op) >= 20) && REGNO (op) <= 31)));
}
/* Return non-zero if the given RTX is suitable for collapsing into
*************** v850_insert_attributes (decl, attr_ptr)
*** 2816,2821 ****
--- 2945,3336 ----
DECL_SECTION_NAME (decl) = chosen_section;
}
}
+ }
+
+ /* Return non-zero if the given RTX is suitable
+ for collapsing into a DISPOSE instruction. */
+
+ int
+ pattern_is_ok_for_dispose (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ {
+ int count = XVECLEN (op, 0);
+ int i;
+
+ /* If there are no registers to restore then
+ the dispose instruction is not suitable. */
+ if (count <= 2)
+ return 0;
+
+ /* The pattern matching has already established that we are performing a
+ function epilogue and that we are popping at least one register. We must
+ now check the remaining entries in the vector to make sure that they are
+ also register pops. There is no good reason why there should ever be
+ anything else in this vector, but being paranoid always helps...
+
+ The test below performs the C equivalent of this machine description
+ pattern match:
+
+ (set (match_operand:SI n "register_is_ok_for_epilogue" "r")
+ (mem:SI (plus:SI (reg:SI 3)
+ (match_operand:SI n "immediate_operand" "i"))))
+ */
+
+ for (i = 3; i < count; i++)
+ {
+ rtx vector_element = XVECEXP (op, 0, i);
+ rtx dest;
+ rtx src;
+ rtx plus;
+
+ if (GET_CODE (vector_element) != SET)
+ return 0;
+
+ dest = SET_DEST (vector_element);
+ src = SET_SRC (vector_element);
+
+ if ( GET_CODE (dest) != REG
+ || GET_MODE (dest) != SImode
+ || ! register_is_ok_for_epilogue (dest, SImode)
+ || GET_CODE (src) != MEM
+ || GET_MODE (src) != SImode)
+ return 0;
+
+ plus = XEXP (src, 0);
+
+ if ( GET_CODE (plus) != PLUS
+ || GET_CODE (XEXP (plus, 0)) != REG
+ || GET_MODE (XEXP (plus, 0)) != SImode
+ || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM
+ || GET_CODE (XEXP (plus, 1)) != CONST_INT)
+ return 0;
+ }
+
+ return 1;
+ }
+
+ /* Construct a DISPOSE instruction that is the equivalent of
+ the given RTX. We have already verified that this should
+ be possible. */
+
+ char *
+ construct_dispose_instruction (op)
+ rtx op;
+ {
+ int count = XVECLEN (op, 0);
+ int stack_bytes;
+ unsigned long int mask;
+ int i;
+ static char buff[ 100 ]; /* XXX */
+ int use_callt = 0;
+
+ if (count <= 2)
+ {
+ error ("Bogus DISPOSE construction: %d\n", count);
+ return NULL;
+ }
+
+ /* Work out how many bytes to pop off the
+ stack before retrieving registers. */
+ if (GET_CODE (XVECEXP (op, 0, 1)) != SET)
+ abort ();
+ if (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) != PLUS)
+ abort ();
+ if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) != CONST_INT)
+ abort ();
+
+ stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1));
+
+ /* Each pop will remove 4 bytes from the stack... */
+ stack_bytes -= (count - 2) * 4;
+
+ /* Make sure that the amount we are popping
+ will fit into the DISPOSE instruction. */
+ if (stack_bytes > 128)
+ {
+ error ("Too much stack space to dispose of: %d", stack_bytes);
+ return NULL;
+ }
+
+ /* Now compute the bit mask of registers to push. */
+ mask = 0;
+
+ for (i = 2; i < count; i++)
+ {
+ rtx vector_element = XVECEXP (op, 0, i);
+
+ if (GET_CODE (vector_element) != SET)
+ abort ();
+ if (GET_CODE (SET_DEST (vector_element)) != REG)
+ abort ();
+ if (! register_is_ok_for_epilogue (SET_DEST (vector_element), SImode))
+ abort ();
+
+ if (REGNO (SET_DEST (vector_element)) == 2)
+ use_callt = 1;
+ else
+ mask |= 1 << REGNO (SET_DEST (vector_element));
+ }
+
+ if (! TARGET_DISABLE_CALLT
+ && (use_callt || stack_bytes == 0 || stack_bytes == 16))
+ {
+ if (use_callt)
+ {
+ sprintf (buff, "callt ctoff(__callt_return_r2_r%d)", (mask & (1 << 31)) ? 31 : 29);
+ return buff;
+ }
+ else
+ {
+ for (i = 20; i < 32; i++)
+ if (mask & (1 << i))
+ break;
+
+ if (i == 31)
+ sprintf (buff, "callt ctoff(__callt_return_r31c)");
+ else
+ sprintf (buff, "callt ctoff(__callt_return_r%d_r%d%s)",
+ i, (mask & (1 << 31)) ? 31 : 29, stack_bytes ? "c" : "");
+ }
+ }
+ else
+ {
+ static char regs [100]; /* XXX */
+ int done_one;
+
+ /* Generate the DISPOSE instruction. Note we could just issue the
+ bit mask as a number as the assembler can cope with this, but for
+ the sake of our readers we turn it into a textual description. */
+ regs[0] = 0;
+ done_one = 0;
+
+ for (i = 20; i < 32; i++)
+ {
+ if (mask & (1 << i))
+ {
+ int first;
+
+ if (done_one)
+ strcat (regs, ", ");
+ else
+ done_one = 1;
+
+ first = i;
+ strcat (regs, reg_names[ first ]);
+
+ for (i++; i < 32; i++)
+ if ((mask & (1 << i)) == 0)
+ break;
+
+ if (i > first + 1)
+ {
+ strcat (regs, " - ");
+ strcat (regs, reg_names[ i - 1 ] );
+ }
+ }
+ }
+
+ sprintf (buff, "dispose %d {%s}, r31", stack_bytes / 4, regs);
+ }
+
+ return buff;
+ }
+
+ /* Return non-zero if the given RTX is suitable
+ for collapsing into a PREPARE instruction. */
+
+ int
+ pattern_is_ok_for_prepare (op, mode)
+ rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ {
+ int count = XVECLEN (op, 0);
+ int i;
+
+ /* If there are no registers to restore then the prepare instruction
+ is not suitable. */
+ if (count <= 1)
+ return 0;
+
+ /* The pattern matching has already established that we are adjusting the
+ stack and pushing at least one register. We must now check that the
+ remaining entries in the vector to make sure that they are also register
+ pushes.
+
+ The test below performs the C equivalent of this machine description
+ pattern match:
+
+ (set (mem:SI (plus:SI (reg:SI 3)
+ (match_operand:SI 2 "immediate_operand" "i")))
+ (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))
+
+ */
+
+ for (i = 2; i < count; i++)
+ {
+ rtx vector_element = XVECEXP (op, 0, i);
+ rtx dest;
+ rtx src;
+ rtx plus;
+
+ if (GET_CODE (vector_element) != SET)
+ return 0;
+
+ dest = SET_DEST (vector_element);
+ src = SET_SRC (vector_element);
+
+ if ( GET_CODE (dest) != MEM
+ || GET_MODE (dest) != SImode
+ || GET_CODE (src) != REG
+ || GET_MODE (src) != SImode
+ || ! register_is_ok_for_epilogue (src, SImode)
+ )
+ return 0;
+
+ plus = XEXP (dest, 0);
+
+ if ( GET_CODE (plus) != PLUS
+ || GET_CODE (XEXP (plus, 0)) != REG
+ || GET_MODE (XEXP (plus, 0)) != SImode
+ || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM
+ || GET_CODE (XEXP (plus, 1)) != CONST_INT)
+ return 0;
+
+ /* If the register is being pushed somewhere other than the stack
+ space just aquired by the first operand then abandon this quest.
+ Note: the test is <= becuase both values are negative. */
+ if (INTVAL (XEXP (plus, 1))
+ <= INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)))
+ return 0;
+ }
+
+ return 1;
+ }
+
+ /* Construct a PREPARE instruction that is the equivalent of
+ the given RTL. We have already verified that this should
+ be possible. */
+
+ char *
+ construct_prepare_instruction (op)
+ rtx op;
+ {
+ int count = XVECLEN (op, 0);
+ int stack_bytes;
+ unsigned long int mask;
+ int i;
+ static char buff[ 100 ]; /* XXX */
+ int use_callt = 0;
+
+ if (count <= 1)
+ {
+ error ("Bogus PREPEARE construction: %d\n", count);
+ return NULL;
+ }
+
+ /* Work out how many bytes to push onto
+ the stack after storing the registers. */
+ if (GET_CODE (XVECEXP (op, 0, 0)) != SET)
+ abort ();
+ if (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != PLUS)
+ abort ();
+ if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) != CONST_INT)
+ abort ();
+
+ stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1));
+
+ /* Each push will put 4 bytes from the stack. */
+ stack_bytes += (count - 1) * 4;
+
+ /* Make sure that the amount we are popping
+ will fit into the DISPOSE instruction. */
+ if (stack_bytes < -128)
+ {
+ error ("Too much stack space to prepare: %d", stack_bytes);
+ return NULL;
+ }
+
+ /* Now compute the bit mask of registers to push. */
+ mask = 0;
+ for (i = 1; i < count; i++)
+ {
+ rtx vector_element = XVECEXP (op, 0, i);
+
+ if (GET_CODE (vector_element) != SET)
+ abort ();
+ if (GET_CODE (SET_SRC (vector_element)) != REG)
+ abort ();
+ if (! register_is_ok_for_epilogue (SET_SRC (vector_element), SImode))
+ abort ();
+
+ if (REGNO (SET_SRC (vector_element)) == 2)
+ use_callt = 1;
+ else
+ mask |= 1 << REGNO (SET_SRC (vector_element));
+ }
+
+ if ((! TARGET_DISABLE_CALLT)
+ && (use_callt || stack_bytes == 0 || stack_bytes == -16))
+ {
+ if (use_callt)
+ {
+ sprintf (buff, "callt ctoff(__callt_save_r2_r%d)", (mask & (1 << 31)) ? 31 : 29 );
+ return buff;
+ }
+
+ for (i = 20; i < 32; i++)
+ if (mask & (1 << i))
+ break;
+
+ if (i == 31)
+ sprintf (buff, "callt ctoff(__callt_save_r31c)");
+ else
+ sprintf (buff, "callt ctoff(__callt_save_r%d_r%d%s)",
+ i, (mask & (1 << 31)) ? 31 : 29, stack_bytes ? "c" : "");
+ }
+ else
+ {
+ static char regs [100]; /* XXX */
+ int done_one;
+
+
+ /* Generate the PREPARE instruction. Note we could just issue the
+ bit mask as a number as the assembler can cope with this, but for
+ the sake of our readers we turn it into a textual description. */
+ regs[0] = 0;
+ done_one = 0;
+
+ for (i = 20; i < 32; i++)
+ {
+ if (mask & (1 << i))
+ {
+ int first;
+
+ if (done_one)
+ strcat (regs, ", ");
+ else
+ done_one = 1;
+
+ first = i;
+ strcat (regs, reg_names[ first ]);
+
+ for (i++; i < 32; i++)
+ if ((mask & (1 << i)) == 0)
+ break;
+
+ if (i > first + 1)
+ {
+ strcat (regs, " - ");
+ strcat (regs, reg_names[ i - 1 ] );
+ }
+ }
+ }
+
+ sprintf (buff, "prepare {%s}, %d", regs, (- stack_bytes) / 4);
+ }
+
+ return buff;
}
/* Implement `va_arg'. */
Index: gcc/config/v850/v850.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/v850/v850.h,v
retrieving revision 1.70
diff -c -3 -p -w -r1.70 v850.h
*** gcc/config/v850/v850.h 20 Aug 2002 23:27:03 -0000 1.70
--- gcc/config/v850/v850.h 27 Aug 2002 19:56:39 -0000
*************** Boston, MA 02111-1307, USA. */
*** 31,38 ****
#undef STARTFILE_SPEC
#undef ASM_SPEC
-
#define TARGET_CPU_generic 1
#ifndef TARGET_CPU_DEFAULT
#define TARGET_CPU_DEFAULT TARGET_CPU_generic
--- 31,38 ----
#undef STARTFILE_SPEC
#undef ASM_SPEC
#define TARGET_CPU_generic 1
+ #define TARGET_CPU_v850e 2
#ifndef TARGET_CPU_DEFAULT
#define TARGET_CPU_DEFAULT TARGET_CPU_generic
*************** Boston, MA 02111-1307, USA. */
*** 43,51 ****
#define SUBTARGET_CPP_SPEC "%{!mv*:-D__v850__}"
#define TARGET_VERSION fprintf (stderr, " (NEC V850)");
#define ASM_SPEC "%{mv*:-mv%*}"
! #define CPP_SPEC "%{mv850ea:-D__v850ea__} %{mv850e:-D__v850e__} %{mv850:-D__v850__} %(subtarget_cpp_spec)"
#define EXTRA_SPECS \
{ "subtarget_asm_spec", SUBTARGET_ASM_SPEC }, \
--- 43,64 ----
#define SUBTARGET_CPP_SPEC "%{!mv*:-D__v850__}"
#define TARGET_VERSION fprintf (stderr, " (NEC V850)");
+ /* Choose which processor will be the default.
+ We must pass a -mv850xx option to the assembler if no explicit -mv* option
+ is given, because the assembler's processor default may not be correct. */
+ #if TARGET_CPU_DEFAULT == TARGET_CPU_v850e
+ #undef MASK_DEFAULT
+ #define MASK_DEFAULT MASK_V850E
+ #undef SUBTARGET_ASM_SPEC
+ #define SUBTARGET_ASM_SPEC "%{!mv*:-mv850e}"
+ #undef SUBTARGET_CPP_SPEC
+ #define SUBTARGET_CPP_SPEC "%{!mv*:-D__v850e__}"
+ #undef TARGET_VERSION
+ #define TARGET_VERSION fprintf (stderr, " (NEC V850E)");
+ #endif
#define ASM_SPEC "%{mv*:-mv%*}"
! #define CPP_SPEC "%{mv850e:-D__v850e__} %{mv850:-D__v850__} %(subtarget_cpp_spec)"
#define EXTRA_SPECS \
{ "subtarget_asm_spec", SUBTARGET_ASM_SPEC }, \
*************** extern int target_flags;
*** 67,74 ****
--- 80,94 ----
#define MASK_CPU 0x00000030
#define MASK_V850 0x00000010
+ #define MASK_V850E 0x00000020
+ #define MASK_SMALL_SLD 0x00000040
#define MASK_BIG_SWITCH 0x00000100
+ #define MASK_NO_APP_REGS 0x00000200
+ #define MASK_DISABLE_CALLT 0x00000400
+
+ #define MASK_US_BIT_SET 0x00001000
+ #define MASK_US_MASK_SET 0x00002000
/* Macros used in the machine description to test the flags. */
*************** extern int target_flags;
*** 107,114 ****
/* 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)
/* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces,
--- 127,149 ----
/* 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)
+ #define TARGET_V850E ((target_flags & MASK_V850E) == MASK_V850E)
+
+ #define TARGET_US_BIT_SET (target_flags & MASK_US_BIT_SET)
+
+ /* Whether to assume that the SLD.B and SLD.H instructions only have small
+ displacement fields, thus allowing the generated code to run on any of
+ the V850 range of processors. */
+ #define TARGET_SMALL_SLD (target_flags & MASK_SMALL_SLD)
+
+ /* True if callt will not be used for function prolog & epilog. */
+ #define TARGET_DISABLE_CALLT (target_flags & MASK_DISABLE_CALLT)
+
+ /* False if r2 and r5 can be used by the compiler. True if r2
+ and r5 are to be fixed registers (for compatibility with GHS). */
+ #define TARGET_NO_APP_REGS (target_flags & MASK_NO_APP_REGS)
/* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces,
*************** extern int target_flags;
*** 134,139 ****
--- 169,187 ----
{ "v850", MASK_V850, \
N_("Compile for the v850 processor") }, \
{ "v850", -(MASK_V850 ^ MASK_CPU), "" }, \
+ { "v850e", MASK_V850E, N_("Compile for v850e processor") }, \
+ { "v850e", -(MASK_V850E ^ MASK_CPU), "" }, /* Make sure that the other bits are cleared. */ \
+ { "small-sld", MASK_SMALL_SLD, N_("Enable the use of the short load instructions") }, \
+ { "no-small-sld", -MASK_SMALL_SLD, "" }, \
+ { "disable-callt", MASK_DISABLE_CALLT, \
+ N_("Do not use the callt instruction") }, \
+ { "no-disable-callt", -MASK_DISABLE_CALLT, "" }, \
+ { "US-bit-set", (MASK_US_BIT_SET | MASK_US_MASK_SET), "" }, \
+ { "no-US-bit-set", -MASK_US_BIT_SET, "" }, \
+ { "no-US-bit-set", MASK_US_MASK_SET, "" }, \
+ { "app-regs", -MASK_NO_APP_REGS, "" }, \
+ { "no-app-regs", MASK_NO_APP_REGS, \
+ N_("Do not use registers r2 and r5") }, \
{ "big-switch", MASK_BIG_SWITCH, \
N_("Use 4 byte entries in switch tables") },\
{ "", MASK_DEFAULT, ""}}
*************** extern struct small_memory_info small_me
*** 327,332 ****
--- 375,391 ----
0, 1, 3, 4, 5, 30, 32, 33 /* fixed registers */ \
}
+ /* If TARGET_NO_APP_REGS is not defined then add r2 and r5 to
+ the pool of fixed registers. See PR 14505. */
+ #define CONDITIONAL_REGISTER_USAGE \
+ { \
+ if (TARGET_NO_APP_REGS) \
+ { \
+ fixed_regs[2] = 1; call_used_regs[2] = 1; \
+ fixed_regs[5] = 1; call_used_regs[5] = 1; \
+ } \
+ }
+
/* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE.
*************** enum reg_class
*** 457,467 ****
#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_O(VALUE) 0
#define CONST_OK_FOR_P(VALUE) 0
-
#define CONST_OK_FOR_LETTER_P(VALUE, C) \
((C) == 'I' ? CONST_OK_FOR_I (VALUE) : \
(C) == 'J' ? CONST_OK_FOR_J (VALUE) : \
--- 516,526 ----
#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)
+ /* 9 bit signed immediate for word multiply instruction. */
+ #define CONST_OK_FOR_O(VALUE) ((unsigned) (VALUE) + 0x100 < 0x200)
#define CONST_OK_FOR_P(VALUE) 0
#define CONST_OK_FOR_LETTER_P(VALUE, C) \
((C) == 'I' ? CONST_OK_FOR_I (VALUE) : \
(C) == 'J' ? CONST_OK_FOR_J (VALUE) : \
*************** extern int current_function_anonymous_ar
*** 851,857 ****
((C) == 'Q' ? ep_memory_operand (OP, GET_MODE (OP), 0) \
: (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' ? ((GET_CODE (OP) == SYMBOL_REF && ZDA_NAME_P (XSTR (OP, 0))) \
|| (GET_CODE (OP) == CONST \
&& GET_CODE (XEXP (OP, 0)) == PLUS \
--- 910,916 ----
((C) == 'Q' ? ep_memory_operand (OP, GET_MODE (OP), 0) \
: (C) == 'R' ? special_symbolref_operand (OP, VOIDmode) \
: (C) == 'S' ? (GET_CODE (OP) == SYMBOL_REF && ! ZDA_NAME_P (XSTR (OP, 0))) \
! : (C) == 'T' ? ep_memory_operand(OP,GET_MODE(OP),TRUE) \
: (C) == 'U' ? ((GET_CODE (OP) == SYMBOL_REF && ZDA_NAME_P (XSTR (OP, 0))) \
|| (GET_CODE (OP) == CONST \
&& GET_CODE (XEXP (OP, 0)) == PLUS \
*************** zbss_section () \
*** 1136,1152 ****
#undef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX "_"
- /* When assemble_integer is used to emit the offsets for a switch
- table it can encounter (TRUNCATE:HI (MINUS:SI (LABEL_REF:SI) (LABEL_REF:SI))).
- output_addr_const will normally barf at this, but it is OK to omit
- the truncate and just emit the difference of the two labels. The
- .hword directive will automatically handle the truncation for us. */
-
#define OUTPUT_ADDR_CONST_EXTRA(FILE, X, FAIL) \
! if (GET_CODE (x) == TRUNCATE) \
! output_addr_const (FILE, XEXP (X, 0)); \
! else \
! goto FAIL;
/* This says how to output the assembler to define a global
uninitialized but not common symbol. */
--- 1195,1203 ----
#undef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX "_"
#define OUTPUT_ADDR_CONST_EXTRA(FILE, X, FAIL) \
! if (! v850_output_addr_const_extra (FILE, X)) \
! goto FAIL
/* This says how to output the assembler to define a global
uninitialized but not common symbol. */
*************** zbss_section () \
*** 1244,1252 ****
/* This is how to output an element of a case-vector that is relative. */
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, 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) \
--- 1295,1305 ----
/* This is how to output an element of a case-vector that is relative. */
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
! fprintf (FILE, "\t%s %s.L%d-.L%d%s\n", \
(TARGET_BIG_SWITCH ? ".long" : ".short"), \
! (! TARGET_BIG_SWITCH && TARGET_V850E ? "(" : ""), \
! VALUE, REL, \
! (! TARGET_BIG_SWITCH && TARGET_V850E ? ")>>1" : ""))
#define ASM_OUTPUT_ALIGN(FILE, LOG) \
if ((LOG) != 0) \
*************** extern union tree_node * GHS_current_sec
*** 1426,1431 ****
--- 1479,1487 ----
{ "pattern_is_ok_for_prologue", { PARALLEL }}, \
{ "pattern_is_ok_for_epilogue", { PARALLEL }}, \
{ "register_is_ok_for_epilogue",{ REG }}, \
+ { "pattern_is_ok_for_dispose", { PARALLEL }}, \
+ { "pattern_is_ok_for_prepare", { PARALLEL }}, \
+ { "register_is_ok_for_dispose", { REG }}, \
{ "not_power_of_two_operand", { CONST_INT }},
#endif /* ! GCC_V850_H */
Index: gcc/config/v850/v850.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/v850/v850.md,v
retrieving revision 1.17
diff -c -3 -p -w -r1.17 v850.md
*** gcc/config/v850/v850.md 20 Jul 2001 13:42:57 -0000 1.17
--- gcc/config/v850/v850.md 27 Aug 2002 19:56:39 -0000
***************
*** 1,5 ****
;; GCC machine description for NEC V850
! ;; Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
;; Contributed by Jeff Law (law@cygnus.com).
;; This file is part of GNU CC.
--- 1,5 ----
;; GCC machine description for NEC V850
! ;; Copyright (C) 1996, 1997, 1998, 1999, 2002 Free Software Foundation, Inc.
;; Contributed by Jeff Law (law@cygnus.com).
;; This file is part of GNU CC.
***************
*** 153,158 ****
--- 153,159 ----
must be done with HIGH & LO_SUM patterns. */
if (CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != HIGH
+ && ! TARGET_V850E
&& !special_symbolref_operand (operands[1], VOIDmode)
&& !(GET_CODE (operands[1]) == CONST_INT
&& (CONST_OK_FOR_J (INTVAL (operands[1]))
***************
*** 174,179 ****
--- 175,198 ----
}
}")
+ ;; This is the same as the following pattern, except that it includes
+ ;; support for arbitrary 32 bit immediates.
+
+ ;; ??? This always loads addresses using hilo. If the only use of this address
+ ;; was in a load/store, then we would get smaller code if we only loaded the
+ ;; upper part with hi, and then put the lower part in the load/store insn.
+
+ (define_insn "*movsi_internal_v850e"
+ [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,Q,r,r,m,m,r")
+ (match_operand:SI 1 "general_operand" "Jr,K,L,Q,Ir,m,R,r,I,i"))]
+ "TARGET_V850E
+ && (register_operand (operands[0], SImode)
+ || reg_or_0_operand (operands[1], SImode))"
+ "* return output_move_single (operands);"
+ [(set_attr "length" "2,4,4,2,2,4,4,4,4,6")
+ (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")
+ (set_attr "type" "other,other,other,load,other,load,other,other,other,other")])
+
(define_insn "*movsi_internal"
[(set (match_operand:SI 0 "general_operand" "=r,r,r,r,Q,r,r,m,m")
(match_operand:SI 1 "movsi_source_operand" "Jr,K,L,Q,Ir,m,R,r,I"))]
***************
*** 377,382 ****
--- 396,489 ----
(set_attr "cc" "none_0hit,none_0hit")
(set_attr "type" "mult")])
+ ;; ??? The scheduling info is probably wrong.
+
+ ;; ??? This instruction can also generate the 32 bit highpart, but using it
+ ;; may increase code size counter to the desired result.
+
+ ;; ??? This instructions can also give a DImode result.
+
+ ;; ??? There is unsigned version, but it matters only for the DImode/highpart
+ ;; results.
+
+ (define_insn "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (match_operand:SI 1 "register_operand" "%0")
+ ;; %redact changeone /reg_or_int9/ 'register' unless nec-no-copyright
+ (match_operand:SI 2 "reg_or_int9_operand" "rO")))]
+ "TARGET_V850E"
+ "mul %2,%1,%."
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")
+ (set_attr "type" "mult")])
+
+ ;; ----------------------------------------------------------------------
+ ;; DIVIDE INSTRUCTIONS
+ ;; ----------------------------------------------------------------------
+
+ ;; ??? These insns do set the Z/N condition codes, except that they are based
+ ;; on only one of the two results, so it doesn't seem to make sense to use
+ ;; them.
+
+ ;; ??? The scheduling info is probably wrong.
+
+ (define_insn "divmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mod:SI (match_dup 1)
+ (match_dup 2)))]
+ "TARGET_V850E"
+ "div %2,%0,%3"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")
+ (set_attr "type" "other")])
+
+ (define_insn "udivmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "register_operand" "r")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (umod:SI (match_dup 1)
+ (match_dup 2)))]
+ "TARGET_V850E"
+ "divu %2,%0,%3"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")
+ (set_attr "type" "other")])
+
+ ;; ??? There is a 2 byte instruction for generating only the quotient.
+ ;; However, it isn't clear how to compute the length field correctly.
+
+ (define_insn "divmodhi4"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (div:HI (match_operand:HI 1 "register_operand" "0")
+ (match_operand:HI 2 "register_operand" "r")))
+ (set (match_operand:HI 3 "register_operand" "=r")
+ (mod:HI (match_dup 1)
+ (match_dup 2)))]
+ "TARGET_V850E"
+ "divh %2,%0,%3"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")
+ (set_attr "type" "other")])
+
+ ;; Half-words are sign-extended by default, so we must zero extend to a word
+ ;; here before doing the divide.
+
+ (define_insn "udivmodhi4"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (udiv:HI (match_operand:HI 1 "register_operand" "0")
+ (match_operand:HI 2 "register_operand" "r")))
+ (set (match_operand:HI 3 "register_operand" "=r")
+ (umod:HI (match_dup 1)
+ (match_dup 2)))]
+ "TARGET_V850E"
+ "zxh %0 ; divhu %2,%0,%3"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")
+ (set_attr "type" "other")])
;; ----------------------------------------------------------------------
;; AND INSTRUCTIONS
***************
*** 734,739 ****
--- 841,1085 ----
[(set_attr "length" "4")
(set_attr "cc" "none_0hit")])
+ ;; ----------------------------------------------------------------------
+ ;; CONDITIONAL MOVE INSTRUCTIONS
+ ;; ----------------------------------------------------------------------
+
+ ;; Instructions using cc0 aren't allowed to have input reloads, so we must
+ ;; hide the fact that this instruction uses cc0. We do so by including the
+ ;; compare instruction inside it.
+
+ ;; ??? This is very ugly. The right way to do this is to modify cmpsi so
+ ;; that it doesn't emit RTL, and then modify the bcc/scc patterns so that
+ ;; they emit RTL for the compare instruction. Unfortunately, this requires
+ ;; lots of changes that will be hard to sanitise. So for now, cmpsi still
+ ;; emits RTL, and I get the compare operands here from the previous insn.
+
+ (define_expand "movsicc"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (if_then_else:SI
+ (match_operator 1 "comparison_operator"
+ [(match_dup 4) (match_dup 5)])
+ ;; %redact changeone /const/ 'int5' unless nec-no-copyright
+ (match_operand:SI 2 "reg_or_const_operand" "rJ")
+ ;; %redact changeone /const/ '0' unless nec-no-copyright
+ (match_operand:SI 3 "reg_or_const_operand" "rI")))]
+ "TARGET_V850E"
+ "
+ {
+ rtx insn = get_last_insn_anywhere ();
+
+ if ( (GET_CODE (operands[2]) == CONST_INT
+ && GET_CODE (operands[3]) == CONST_INT))
+ {
+ int o2 = INTVAL (operands[2]);
+ int o3 = INTVAL (operands[3]);
+
+ if (o2 == 1 && o3 == 0)
+ FAIL; /* setf */
+ if (o3 == 1 && o2 == 0)
+ FAIL; /* setf */
+ if (o2 == 0 && (o3 < -16 || o3 > 15) && exact_log2 (o3) >= 0)
+ FAIL; /* setf + shift */
+ if (o3 == 0 && (o2 < -16 || o2 > 15) && exact_log2 (o2) >=0)
+ FAIL; /* setf + shift */
+ if (o2 != 0)
+ operands[2] = copy_to_mode_reg (SImode, operands[2]);
+ if (o3 !=0 )
+ operands[3] = copy_to_mode_reg (SImode, operands[3]);
+ }
+ else
+ {
+ if (GET_CODE (operands[2]) != REG)
+ operands[2] = copy_to_mode_reg (SImode,operands[2]);
+ if (GET_CODE (operands[3]) != REG)
+ operands[3] = copy_to_mode_reg (SImode, operands[3]);
+ }
+ if (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == SET
+ && SET_DEST (PATTERN (insn)) == cc0_rtx)
+ {
+ rtx src = SET_SRC (PATTERN (insn));
+
+ if (GET_CODE (src) == COMPARE)
+ {
+ operands[4] = XEXP (src, 0);
+ operands[5] = XEXP (src, 1);
+ }
+ else if (GET_CODE (src) == REG
+ || GET_CODE (src) == SUBREG)
+ {
+ operands[4] = src;
+ operands[5] = const0_rtx;
+ }
+ else
+ abort ();
+ }
+ else
+ abort ();
+ }")
+
+ ;; ??? Clobbering the condition codes is overkill.
+
+ ;; ??? We sometimes emit an unnecessary compare instruction because the
+ ;; condition codes may have already been set by an earlier instruction,
+ ;; but we have no code here to avoid the compare if it is unnecessary.
+
+ (define_insn "*movsicc_normal"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (if_then_else:SI
+ (match_operator 1 "comparison_operator"
+ [(match_operand:SI 4 "register_operand" "r")
+ (match_operand:SI 5 "reg_or_int5_operand" "rJ")])
+ (match_operand:SI 2 "reg_or_int5_operand" "rJ")
+ (match_operand:SI 3 "reg_or_0_operand" "rI")))]
+ "TARGET_V850E"
+ "cmp %5,%4 ; cmov %c1,%2,%z3,%0"
+ [(set_attr "length" "6")
+ (set_attr "cc" "clobber")])
+
+ (define_insn "*movsicc_reversed"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (if_then_else:SI
+ (match_operator 1 "comparison_operator"
+ [(match_operand:SI 4 "register_operand" "r")
+ (match_operand:SI 5 "reg_or_int5_operand" "rJ")])
+ (match_operand:SI 2 "reg_or_0_operand" "rI")
+ (match_operand:SI 3 "reg_or_int5_operand" "rJ")))]
+ "TARGET_V850E"
+ "cmp %5,%4 ; cmov %C1,%3,%z2,%0"
+ [(set_attr "length" "6")
+ (set_attr "cc" "clobber")])
+
+ (define_insn "*movsicc_tst1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (if_then_else:SI
+ (match_operator 1 "comparison_operator"
+ [(zero_extract:SI
+ (match_operand:QI 2 "memory_operand" "m")
+ (const_int 1)
+ (match_operand 3 "const_int_operand" "n"))
+ (const_int 0)])
+ (match_operand:SI 4 "reg_or_int5_operand" "rJ")
+ (match_operand:SI 5 "reg_or_0_operand" "rI")))]
+ "TARGET_V850E"
+ "tst1 %3,%2 ; cmov %c1,%4,%z5,%0"
+ [(set_attr "length" "8")
+ (set_attr "cc" "clobber")])
+
+ (define_insn "*movsicc_tst1_reversed"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (if_then_else:SI
+ (match_operator 1 "comparison_operator"
+ [(zero_extract:SI
+ (match_operand:QI 2 "memory_operand" "m")
+ (const_int 1)
+ (match_operand 3 "const_int_operand" "n"))
+ (const_int 0)])
+ (match_operand:SI 4 "reg_or_0_operand" "rI")
+ (match_operand:SI 5 "reg_or_int5_operand" "rJ")))]
+ "TARGET_V850E"
+ "tst1 %3,%2 ; cmov %C1,%5,%z4,%0"
+ [(set_attr "length" "8")
+ (set_attr "cc" "clobber")])
+
+ ;; Matching for sasf requires combining 4 instructions, so we provide a
+ ;; dummy pattern to match the first 3, which will always be turned into the
+ ;; second pattern by subsequent combining. As above, we must include the
+ ;; comparison to avoid input reloads in an insn using cc0.
+
+ (define_insn "*sasf_1"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (ior:SI (match_operator 1 "comparison_operator" [(cc0) (const_int 0)])
+ (ashift:SI (match_operand:SI 2 "register_operand" "")
+ (const_int 1))))]
+ "TARGET_V850E"
+ "* abort ();")
+
+ (define_insn "*sasf_2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI
+ (match_operator 1 "comparison_operator"
+ [(match_operand:SI 3 "register_operand" "r")
+ (match_operand:SI 4 "reg_or_int5_operand" "rJ")])
+ (ashift:SI (match_operand:SI 2 "register_operand" "0")
+ (const_int 1))))]
+ "TARGET_V850E"
+ "cmp %4,%3 ; sasf %c1,%0"
+ [(set_attr "length" "6")
+ (set_attr "cc" "clobber")])
+
+ (define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (if_then_else:SI
+ (match_operator 1 "comparison_operator"
+ [(match_operand:SI 4 "register_operand" "")
+ (match_operand:SI 5 "reg_or_int5_operand" "")])
+ (match_operand:SI 2 "const_int_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")))]
+ "TARGET_V850E
+ && ((INTVAL (operands[2]) ^ INTVAL (operands[3])) == 1)
+ && ((INTVAL (operands[2]) + INTVAL (operands[3])) != 1)
+ && (GET_CODE (operands[5]) == CONST_INT
+ || REGNO (operands[0]) != REGNO (operands[5]))
+ && REGNO (operands[0]) != REGNO (operands[4])"
+ [(set (match_dup 0) (match_dup 6))
+ (set (match_dup 0)
+ (ior:SI (match_op_dup 7 [(match_dup 4) (match_dup 5)])
+ (ashift:SI (match_dup 0) (const_int 1))))]
+ "
+ {
+ operands[6] = GEN_INT (INTVAL (operands[2]) >> 1);
+ if (INTVAL (operands[2]) & 0x1)
+ operands[7] = operands[1];
+ else
+ operands[7] = gen_rtx (reverse_condition (GET_CODE (operands[1])),
+ GET_MODE (operands[1]), XEXP (operands[1], 0),
+ XEXP (operands[1], 1));
+ }")
+ ;; ---------------------------------------------------------------------
+ ;; BYTE SWAP INSTRUCTIONS
+ ;; ---------------------------------------------------------------------
+
+ (define_expand "rotlhi3"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (rotate:HI (match_operand:HI 1 "register_operand" "")
+ (match_operand:HI 2 "const_int_operand" "")))]
+ "TARGET_V850E"
+ "
+ {
+ if (INTVAL (operands[2]) != 8)
+ FAIL;
+ }")
+
+ (define_insn "*rotlhi3_8"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (rotate:HI (match_operand:HI 1 "register_operand" "r")
+ (const_int 8)))]
+ "TARGET_V850E"
+ "bsh %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+ (define_expand "rotlsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (rotate:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")))]
+ "TARGET_V850E"
+ "
+ {
+ if (INTVAL (operands[2]) != 16)
+ FAIL;
+ }")
+
+ (define_insn "*rotlsi3_16"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (rotate:SI (match_operand:SI 1 "register_operand" "r")
+ (const_int 16)))]
+ "TARGET_V850E"
+ "hsw %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
;; ----------------------------------------------------------------------
;; JUMP INSTRUCTIONS
***************
*** 921,926 ****
--- 1267,1286 ----
[(set_attr "length" "2")
(set_attr "cc" "none")])
+ (define_insn "switch"
+ [(set (pc)
+ (plus:SI
+ (sign_extend:SI
+ (mem:HI
+ (plus:SI (ashift:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1))
+ (label_ref (match_operand 1 "" "")))))
+ (label_ref (match_dup 1))))]
+ "TARGET_V850E"
+ "switch %0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "none")])
+
(define_expand "casesi"
[(match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "register_operand" "")
***************
*** 940,945 ****
--- 1300,1311 ----
/* Branch to the default label if out of range of the table. */
emit_jump_insn (gen_bgtu (operands[4]));
+ if (! TARGET_BIG_SWITCH && TARGET_V850E)
+ {
+ emit_jump_insn (gen_switch (reg, operands[3]));
+ DONE;
+ }
+
/* 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 pseudo. */
***************
*** 1084,1089 ****
--- 1450,1467 ----
;; EXTEND INSTRUCTIONS
;; ----------------------------------------------------------------------
+ (define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+ (zero_extend:SI
+ (match_operand:HI 1 "nonimmediate_operand" "0,r,T,m")))]
+ "TARGET_V850E"
+ "@
+ zxh %0
+ andi 65535,%1,%0
+ sld.hu %1,%0
+ ld.hu %1,%0"
+ [(set_attr "length" "2,4,2,4")
+ (set_attr "cc" "none_0hit,set_znv,none_0hit,none_0hit")])
(define_insn "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
***************
*** 1094,1099 ****
--- 1472,1489 ----
[(set_attr "length" "4")
(set_attr "cc" "set_znv")])
+ (define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+ (zero_extend:SI
+ (match_operand:QI 1 "nonimmediate_operand" "0,r,T,m")))]
+ "TARGET_V850E"
+ "@
+ zxb %0
+ andi 255,%1,%0
+ sld.bu %1,%0
+ ld.bu %1,%0"
+ [(set_attr "length" "2,4,2,4")
+ (set_attr "cc" "none_0hit,set_znv,none_0hit,none_0hit")])
(define_insn "zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
***************
*** 1106,1111 ****
--- 1496,1513 ----
;;- sign extension instructions
+ ;; ??? The extendhisi2 pattern should not emit shifts for v850e?
+
+ (define_insn "*extendhisi_insn"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m")))]
+ "TARGET_V850E"
+ "@
+ sxh %0
+ sld.h %1,%0
+ ld.h %1,%0"
+ [(set_attr "length" "2,2,4")
+ (set_attr "cc" "none_0hit,none_0hit,none_0hit")])
;; ??? This is missing a sign extend from memory pattern to match the ld.h
;; instruction.
***************
*** 1124,1129 ****
--- 1526,1543 ----
operands[2] = gen_reg_rtx (SImode);
}")
+ ;; ??? The extendqisi2 pattern should not emit shifts for v850e?
+
+ (define_insn "*extendqisi_insn"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m")))]
+ "TARGET_V850E"
+ "@
+ sxb %0
+ sld.b %1,%0
+ ld.b %1,%0"
+ [(set_attr "length" "2,2,4")
+ (set_attr "cc" "none_0hit,none_0hit,none_0hit")])
;; ??? This is missing a sign extend from memory pattern to match the ld.b
;; instruction.
***************
*** 1229,1234 ****
--- 1643,1663 ----
;; RTXs. These RTXs will then be turned into a suitable call to a worker
;; function.
+ ;;
+ ;; Actually, convert the RTXs into a PREPARE instruction.
+ ;;
+ (define_insn ""
+ [(match_parallel 0 "pattern_is_ok_for_prepare"
+ [(set (reg:SI 3)
+ (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i")))
+ (set (mem:SI (plus:SI (reg:SI 3)
+ (match_operand:SI 2 "immediate_operand" "i")))
+ (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))])]
+ "TARGET_PROLOG_FUNCTION && TARGET_V850E"
+ "* return construct_prepare_instruction (operands[0]);
+ "
+ [(set_attr "length" "4")
+ (set_attr "cc" "none")])
(define_insn ""
[(match_parallel 0 "pattern_is_ok_for_prologue"
***************
*** 1245,1250 ****
--- 1674,1696 ----
(const_string "4")))
(set_attr "cc" "clobber")])
+ ;;
+ ;; Actually, turn the RTXs into a DISPOSE instruction.
+ ;;
+ (define_insn ""
+ [(match_parallel 0 "pattern_is_ok_for_dispose"
+ [(return)
+ (set (reg:SI 3)
+ (plus:SI (reg:SI 3) (match_operand:SI 1 "immediate_operand" "i")))
+ (set (match_operand:SI 2 "register_is_ok_for_epilogue" "=r")
+ (mem:SI (plus:SI (reg:SI 3)
+ (match_operand:SI 3 "immediate_operand" "i"))))])]
+ "TARGET_PROLOG_FUNCTION && TARGET_V850E"
+ "* return construct_dispose_instruction (operands[0]);
+ "
+ [(set_attr "length" "4")
+ (set_attr "cc" "none")])
+
;; This pattern will match a return RTX followed by any number of pop RTXs
;; and possible a stack adjustment as well. These RTXs will be turned into
;; a suitable call to a worker function.
***************
*** 1266,1296 ****
(set_attr "cc" "clobber")])
;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION.
(define_insn "save_interrupt"
[(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -16)))
! (set (mem:SI (reg:SI 3)) (reg:SI 30))
! (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 10))
! (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 4))
! (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1))]
! "TARGET_V850 && ! TARGET_LONG_CALLS"
! "add -16, sp ; st.w r10, 12[sp] ; jarl __save_interrupt, r10"
! [(set_attr "length" "12")
(set_attr "cc" "clobber")])
;; Restore r1, r4, r10, and return from the interrupt
! (define_insn "restore_interrupt"
[(return)
(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 16)))
! (set (reg:SI 30) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
! (set (reg:SI 10) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
(set (reg:SI 4) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))
! (set (reg:SI 1) (mem:SI (reg:SI 3)))]
""
! "jr __return_interrupt"
! [(set_attr "length" "4")
(set_attr "cc" "clobber")])
-
;; Save all registers except for the registers saved in save_interrupt when
;; an interrupt function makes a call.
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
--- 1712,1806 ----
(set_attr "cc" "clobber")])
;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION.
+ (define_insn "callt_save_interrupt"
+ [(unspec_volatile [(const_int 0)] 2)]
+ "TARGET_V850E && !TARGET_DISABLE_CALLT"
+ ;; The CALLT instruction stores the next address of CALLT to CTPC register
+ ;; without saving its previous value. So if the interrupt handler
+ ;; or its caller could possibily execute the CALLT insn, save_interrupt
+ ;; MUST NOT be called via CALLT.
+ "*
+ {
+ output_asm_insn (\"addi -24, sp, sp\", operands);
+ output_asm_insn (\"st.w r10, 12[sp]\", operands);
+ output_asm_insn (\"stsr ctpc, r10\", operands);
+ output_asm_insn (\"st.w r10, 16[sp]\", operands);
+ output_asm_insn (\"stsr ctpsw, r10\", operands);
+ output_asm_insn (\"st.w r10, 20[sp]\", operands);
+ output_asm_insn (\"callt ctoff(__callt_save_interrupt)\", operands);
+ return \"\";
+ }"
+ [(set_attr "length" "26")
+ (set_attr "cc" "none")])
+
+ (define_insn "callt_return_interrupt"
+ [(unspec_volatile [(const_int 0)] 3)]
+ "TARGET_V850E && !TARGET_DISABLE_CALLT"
+ "callt ctoff(__callt_return_interrupt)"
+ [(set_attr "length" "2")
+ (set_attr "cc" "clobber")])
+
(define_insn "save_interrupt"
[(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -16)))
! (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 30))
! (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 4))
! (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 1))
! (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 10))]
! ""
! "*
! {
! if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
! return \"add -16,sp\;st.w r10,12[sp]\;jarl __save_interrupt,r10\";
! else
! {
! output_asm_insn (\"add -16, sp\", operands);
! output_asm_insn (\"st.w r10, 12[sp]\", operands);
! output_asm_insn (\"st.w ep, 0[sp]\", operands);
! output_asm_insn (\"st.w gp, 4[sp]\", operands);
! output_asm_insn (\"st.w r1, 8[sp]\", operands);
! output_asm_insn (\"movhi hi(__ep), r0, ep\", operands);
! output_asm_insn (\"movea lo(__ep), ep, ep\", operands);
! output_asm_insn (\"movhi hi(__gp), r0, gp\", operands);
! output_asm_insn (\"movea lo(__gp), gp, gp\", operands);
! return \"\";
! }
! }"
! [(set (attr "length")
! (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") (const_int 0))
! (const_int 10)
! (const_int 34)))
(set_attr "cc" "clobber")])
;; Restore r1, r4, r10, and return from the interrupt
! (define_insn "return_interrupt"
[(return)
(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 16)))
! (set (reg:SI 10) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
! (set (reg:SI 1) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
(set (reg:SI 4) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))
! (set (reg:SI 30) (mem:SI (reg:SI 3)))]
""
! "*
! {
! if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
! return \"jr __return_interrupt\";
! else
! {
! output_asm_insn (\"ld.w 0[sp], ep\", operands);
! output_asm_insn (\"ld.w 4[sp], gp\", operands);
! output_asm_insn (\"ld.w 8[sp], r1\", operands);
! output_asm_insn (\"ld.w 12[sp], r10\", operands);
! output_asm_insn (\"addi 16, sp, sp\", operands);
! output_asm_insn (\"reti\", operands);
! return \"\";
! }
! }"
! [(set (attr "length")
! (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") (const_int 0))
! (const_int 4)
! (const_int 24)))
(set_attr "cc" "clobber")])
;; Save all registers except for the registers saved in save_interrupt when
;; an interrupt function makes a call.
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
***************
*** 1298,1325 ****
;; This is needed because the rest of the compiler is not ready to handle
;; insns this complicated.
(define_insn "save_all_interrupt"
[(unspec_volatile [(const_int 0)] 0)]
"TARGET_V850 && ! TARGET_LONG_CALLS"
"jarl __save_all_interrupt,r10"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
-
;; Restore all registers saved when an interrupt function makes a call.
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; all of memory. This blocks insns from being moved across this point.
;; This is needed because the rest of the compiler is not ready to handle
;; insns this complicated.
(define_insn "restore_all_interrupt"
[(unspec_volatile [(const_int 0)] 1)]
"TARGET_V850 && ! TARGET_LONG_CALLS"
"jarl __restore_all_interrupt,r10"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
;; Save r6-r9 for a variable argument function
(define_insn "save_r6_r9"
[(set (mem:SI (reg:SI 3)) (reg:SI 6))
(set (mem:SI (plus:SI (reg:SI 3) (const_int 4))) (reg:SI 7))
--- 1808,1955 ----
;; This is needed because the rest of the compiler is not ready to handle
;; insns this complicated.
+ (define_insn "callt_save_all_interrupt"
+ [(unspec_volatile [(const_int 0)] 0)]
+ "TARGET_V850E && !TARGET_DISABLE_CALLT"
+ "callt ctoff(__callt_save_all_interrupt)"
+ [(set_attr "length" "2")
+ (set_attr "cc" "none")])
+
(define_insn "save_all_interrupt"
[(unspec_volatile [(const_int 0)] 0)]
+ ""
+ "*
+ {
+ if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
+ return \"jarl __save_all_interrupt,r10\";
+
+ output_asm_insn (\"addi -120, sp, sp\", operands);
+ output_asm_insn (\"mov ep, r1\", operands);
+ output_asm_insn (\"mov sp, ep\", operands);
+ output_asm_insn (\"sst.w r31, 116[ep]\", operands);
+ output_asm_insn (\"sst.w r2, 112[ep]\", operands);
+ output_asm_insn (\"sst.w gp, 108[ep]\", operands);
+ output_asm_insn (\"sst.w r6, 104[ep]\", operands);
+ output_asm_insn (\"sst.w r7, 100[ep]\", operands);
+ output_asm_insn (\"sst.w r8, 96[ep]\", operands);
+ output_asm_insn (\"sst.w r9, 92[ep]\", operands);
+ output_asm_insn (\"sst.w r11, 88[ep]\", operands);
+ output_asm_insn (\"sst.w r12, 84[ep]\", operands);
+ output_asm_insn (\"sst.w r13, 80[ep]\", operands);
+ output_asm_insn (\"sst.w r14, 76[ep]\", operands);
+ output_asm_insn (\"sst.w r15, 72[ep]\", operands);
+ output_asm_insn (\"sst.w r16, 68[ep]\", operands);
+ output_asm_insn (\"sst.w r17, 64[ep]\", operands);
+ output_asm_insn (\"sst.w r18, 60[ep]\", operands);
+ output_asm_insn (\"sst.w r19, 56[ep]\", operands);
+ output_asm_insn (\"sst.w r20, 52[ep]\", operands);
+ output_asm_insn (\"sst.w r21, 48[ep]\", operands);
+ output_asm_insn (\"sst.w r22, 44[ep]\", operands);
+ output_asm_insn (\"sst.w r23, 40[ep]\", operands);
+ output_asm_insn (\"sst.w r24, 36[ep]\", operands);
+ output_asm_insn (\"sst.w r25, 32[ep]\", operands);
+ output_asm_insn (\"sst.w r26, 28[ep]\", operands);
+ output_asm_insn (\"sst.w r27, 24[ep]\", operands);
+ output_asm_insn (\"sst.w r28, 20[ep]\", operands);
+ output_asm_insn (\"sst.w r29, 16[ep]\", operands);
+ output_asm_insn (\"mov r1, ep\", operands);
+ return \"\";
+ }"
+ [(set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") (const_int 0))
+ (const_int 4)
+ (const_int 62)
+ ))
+ (set_attr "cc" "clobber")])
+
+ (define_insn "_save_all_interrupt"
+ [(unspec_volatile [(const_int 0)] 0)]
"TARGET_V850 && ! TARGET_LONG_CALLS"
"jarl __save_all_interrupt,r10"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
;; Restore all registers saved when an interrupt function makes a call.
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; all of memory. This blocks insns from being moved across this point.
;; This is needed because the rest of the compiler is not ready to handle
;; insns this complicated.
+ (define_insn "callt_restore_all_interrupt"
+ [(unspec_volatile [(const_int 0)] 1)]
+ "TARGET_V850E && !TARGET_DISABLE_CALLT"
+ "callt ctoff(__callt_restore_all_interrupt)"
+ [(set_attr "length" "2")
+ (set_attr "cc" "none")])
+
(define_insn "restore_all_interrupt"
[(unspec_volatile [(const_int 0)] 1)]
+ ""
+ "*
+ {
+ if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS)
+ return \"jarl __restore_all_interrupt,r10\";
+ else
+ {
+ output_asm_insn (\"mov ep, r1\", operands);
+ output_asm_insn (\"mov sp, ep\", operands);
+ output_asm_insn (\"sld.w 116[ep], r31\", operands);
+ output_asm_insn (\"sld.w 112[ep], r2\", operands);
+ output_asm_insn (\"sld.w 108[ep], gp\", operands);
+ output_asm_insn (\"sld.w 104[ep], r6\", operands);
+ output_asm_insn (\"sld.w 100[ep], r7\", operands);
+ output_asm_insn (\"sld.w 96[ep], r8\", operands);
+ output_asm_insn (\"sld.w 92[ep], r9\", operands);
+ output_asm_insn (\"sld.w 88[ep], r11\", operands);
+ output_asm_insn (\"sld.w 84[ep], r12\", operands);
+ output_asm_insn (\"sld.w 80[ep], r13\", operands);
+ output_asm_insn (\"sld.w 76[ep], r14\", operands);
+ output_asm_insn (\"sld.w 72[ep], r15\", operands);
+ output_asm_insn (\"sld.w 68[ep], r16\", operands);
+ output_asm_insn (\"sld.w 64[ep], r17\", operands);
+ output_asm_insn (\"sld.w 60[ep], r18\", operands);
+ output_asm_insn (\"sld.w 56[ep], r19\", operands);
+ output_asm_insn (\"sld.w 52[ep], r20\", operands);
+ output_asm_insn (\"sld.w 48[ep], r21\", operands);
+ output_asm_insn (\"sld.w 44[ep], r22\", operands);
+ output_asm_insn (\"sld.w 40[ep], r23\", operands);
+ output_asm_insn (\"sld.w 36[ep], r24\", operands);
+ output_asm_insn (\"sld.w 32[ep], r25\", operands);
+ output_asm_insn (\"sld.w 28[ep], r26\", operands);
+ output_asm_insn (\"sld.w 24[ep], r27\", operands);
+ output_asm_insn (\"sld.w 20[ep], r28\", operands);
+ output_asm_insn (\"sld.w 16[ep], r29\", operands);
+ output_asm_insn (\"mov r1, ep\", operands);
+ output_asm_insn (\"addi 120, sp, sp\", operands);
+ return \"\";
+ }
+ }"
+ [(set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_LONG_CALLS") (const_int 0))
+ (const_int 4)
+ (const_int 62)
+ ))
+ (set_attr "cc" "clobber")])
+
+ (define_insn "_restore_all_interrupt"
+ [(unspec_volatile [(const_int 0)] 1)]
"TARGET_V850 && ! TARGET_LONG_CALLS"
"jarl __restore_all_interrupt,r10"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
;; Save r6-r9 for a variable argument function
+ (define_insn "save_r6_r9_v850e"
+ [(set (mem:SI (reg:SI 3)) (reg:SI 6))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int 4))) (reg:SI 7))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int 8))) (reg:SI 8))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int 12))) (reg:SI 9))
+ ]
+ "TARGET_PROLOG_FUNCTION && TARGET_V850E && !TARGET_DISABLE_CALLT"
+ "callt ctoff(__callt_save_r6_r9)"
+ [(set_attr "length" "2")
+ (set_attr "cc" "none")])
+
(define_insn "save_r6_r9"
[(set (mem:SI (reg:SI 3)) (reg:SI 6))
(set (mem:SI (plus:SI (reg:SI 3) (const_int 4))) (reg:SI 7))
Index: gcc/doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.175
diff -c -3 -p -w -r1.175 invoke.texi
*** gcc/doc/invoke.texi 20 Aug 2002 19:56:30 -0000 1.175
--- gcc/doc/invoke.texi 27 Aug 2002 19:56:43 -0000
*************** in the following sections.
*** 577,582 ****
--- 577,585 ----
-mlong-calls -mno-long-calls -mep -mno-ep @gol
-mprolog-function -mno-prolog-function -mspace @gol
-mtda=@var{n} -msda=@var{n} -mzda=@var{n} @gol
+ -mapp-regs -mno-app-regs @gol
+ -mdisable-callt -mno-disable-callt @gol
+ -mv850e @gol
-mv850 -mbig-switch}
@emph{NS32K Options}
*************** Specify that the target processor is the
*** 8682,8687 ****
--- 8685,8718 ----
Generate code suitable for big switch tables. Use this option only if
the assembler/linker complain about out of range branches within a switch
table.
+
+ @item -mapp-regs
+ @opindex -mapp-regs
+ This option will cause r2 and r5 to be used in the code generated by
+ the compiler. This setting is the default.
+
+ @item -mno-app-regs
+ @opindex -mno-app-regs
+ This option will cause r2 and r5 to be treated as fixed registers.
+
+ @item -mv850e
+ @opindex -mv850e
+ Specify that the target processor is the V850E. The preprocessor
+ constant @samp{__v850e__} will be defined if this option is used.
+
+ If neither @option{-mv850} nor @option{-mv850e} are defined
+ then a default target processor will be chosen and the relevant
+ @samp{__v850*__} preprocessor constant will be defined.
+
+ The preprocessor constants @samp{__v850} and @samp{__v851__} are always
+ defined, regardless of which processor variant is the target.
+
+ @item -mdisable-callt
+ @opindex -mdisable-callt
+ This option will suppress generation of the CALLT instruction for the
+ v850e flavors of the v850 architecture. The default is
+ @option{-mno-disable-callt} which allows the CALLT instruction to be used.
+
@end table
@node ARC Options