aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <law@gcc.gnu.org>1997-09-05 11:41:24 -0600
committerJeff Law <law@gcc.gnu.org>1997-09-05 11:41:24 -0600
commitae180d84fc7bb97b09fb67a1e478288d748e41fb (patch)
treea46d3dd141bcd31d33f4ff1c5bbe8c1713f4ac8b
parent89cc6098e680140f7b56f639d20be360c23d23ba (diff)
downloadgcc-ae180d84fc7bb97b09fb67a1e478288d748e41fb.zip
gcc-ae180d84fc7bb97b09fb67a1e478288d748e41fb.tar.gz
gcc-ae180d84fc7bb97b09fb67a1e478288d748e41fb.tar.bz2
v850: New directory for v850 port.
Fri Sep 5 10:08:44 1997 Jeffrey A Law (law@cygnus.com) * v850: New directory for v850 port. * v850/lib1funcs.asm: New file. * t-v850, v850.c, v850.h, v850.md, xm-v850.h: New files. * ginclude/va-v850.h: New file. * varargs.h, stdarg.h: Include va-mn10200.h. * configure.in (mn10200-*-*): New target. * Makefile.in (USER_H): Add va-mn10200.h. From-SVN: r15103
-rw-r--r--gcc/config/v850/lib1funcs.asm1271
-rw-r--r--gcc/config/v850/t-v85054
-rw-r--r--gcc/config/v850/v850.c1942
-rw-r--r--gcc/config/v850/v850.h1406
-rw-r--r--gcc/config/v850/v850.md1852
-rw-r--r--gcc/config/v850/xm-v850.h51
6 files changed, 6576 insertions, 0 deletions
diff --git a/gcc/config/v850/lib1funcs.asm b/gcc/config/v850/lib1funcs.asm
new file mode 100644
index 0000000..d441590
--- /dev/null
+++ b/gcc/config/v850/lib1funcs.asm
@@ -0,0 +1,1271 @@
+/* CYGNUS LOCAL entire file v850/law */
+/* libgcc1 routines for NEC V850.
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file. (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* As a special exception, if you link this library with files
+ compiled with GCC to produce an executable, this does not cause
+ the resulting executable to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+#ifdef L_mulsi3
+ .text
+ .globl ___mulsi3
+ .type ___mulsi3,@function
+
+/*
+ * In order to not deal with negative numbers (mulh is a signed multiply
+ * and we want an unsigned multiply, code the multiplication as a series
+ * of 7 bit multiplies).
+ *
+ * int __mulsi3 (unsigned a, unsigned b)
+ * {
+ * int i, j;
+ * int ret = 0;
+ *
+ * for (i = 0; i < 32; i += 7)
+ * {
+ * short a_part = a & 0x7f;
+ * unsigned b_tmp = b;
+ * a >>= 7;
+ *
+ * for (j = 0; (i+j) < 32; j += 7)
+ * {
+ * short b_part = b_tmp & 0x7f;
+ * ret += (((int)a_part) * ((int)b_part)) << (i+j);
+ * b_tmp >>= 7;
+ * }
+ * }
+ *
+ * return ret;
+ * }
+ */
+
+___mulsi3:
+ mov 0,r10 /* total */
+ mov 0,r14 /* i = 0, index for multiply a's part */
+ movea lo(31),r0,r16 /* upper bounds for loop */
+.L5:
+ mov r7,r13 /* b_tmp = b */
+ andi 0x7f,r6,r15 /* a_part = (a & 127) */
+ shr 7,r6 /* a >>= 7 */
+ mov r14,r12 /* i+j = i */
+.L9:
+ andi 0x7f,r13,r11 /* b_part = (b_tmp & 127) */
+ mulh r15,r11 /* ((int)a_part) * ((int)b_part) */
+ shr 7,r13 /* b_tmp >>= 7 */
+ shl r12,r11 /* (((int)a_part) * ((int)b_part)) << (i+j) */
+ add r11,r10 /* ret += (((int)a_part) * ((int)b_part)) << (i+j) */
+ add 7,r12 /* i+j += 7 */
+ cmp r16,r12 /* i+j < 32 */
+ ble .L9
+
+ add 7,r14 /* i += 7 */
+ cmp r16,r14 /* i < 32 */
+ ble .L5
+
+ jmp [r31] /* return */
+ .size __mulsi3,.-__mulsi3
+#endif
+
+#ifdef L_udivsi3
+ .global ___udivsi3
+___udivsi3:
+ mov 1,r12
+ mov 0,r10
+ cmp r6,r7
+ bnl .L12
+ movhi hi(-2147483648),r0,r13
+ cmp r0,r7
+ blt .L12
+.L4:
+ shl 1,r7
+ shl 1,r12
+ cmp r6,r7
+ bnl .L12
+ cmp r0,r12
+ be .L8
+ mov r7,r5
+ and r13,r5
+ be .L4
+ br .L12
+.L9:
+ cmp r7,r6
+ bl .L10
+ sub r7,r6
+ or r12,r10
+.L10:
+ shr 1,r12
+ shr 1,r7
+.L12:
+ cmp r0,r12
+ bne .L9
+.L8:
+ jmp [r31]
+ .size __udivsi3,.-__udivsi3
+#endif
+
+#ifdef L_divsi3
+ .text
+ .globl ___divsi3
+ .type ___divsi3,@function
+___divsi3:
+ add -8,sp
+ st.w r31,4[sp]
+ st.w r22,0[sp]
+ mov 1,r22
+ tst r7,r7
+ bp .L3
+ subr r0,r7
+ subr r0,r22
+.L3:
+ tst r6,r6
+ bp .L4
+ subr r0,r6
+ subr r0,r22
+.L4:
+ jarl ___udivsi3,r31
+ cmp r0,r22
+ bp .L7
+ subr r0,r10
+.L7:
+ ld.w 0[sp],r22
+ ld.w 4[sp],r31
+ add 8,sp
+ jmp [r31]
+ .size __divsi3,.-__divsi3
+#endif
+
+#ifdef L_umodsi3
+ .text
+ .globl ___umodsi3
+ .type ___umodsi3,@function
+___umodsi3:
+ add -12,sp
+ st.w r31,8[sp]
+ st.w r7,4[sp]
+ st.w r6,0[sp]
+ jarl ___udivsi3,r31
+ ld.w 4[sp],r7
+ mov r10,r6
+ jarl ___mulsi3,r31
+ ld.w 0[sp],r6
+ subr r6,r10
+ ld.w 8[sp],r31
+ add 12,sp
+ jmp [r31]
+ .size __umodsi3,.-__umodsi3
+#endif /* L_umodsi3 */
+
+#ifdef L_modsi3
+ .text
+ .globl ___modsi3
+ .type ___modsi3,@function
+___modsi3:
+ add -12,sp
+ st.w r31,8[sp]
+ st.w r7,4[sp]
+ st.w r6,0[sp]
+ jarl ___divsi3,r31
+ ld.w 4[sp],r7
+ mov r10,r6
+ jarl ___mulsi3,r31
+ ld.w 0[sp],r6
+ subr r6,r10
+ ld.w 8[sp],r31
+ add 12,sp
+ jmp [r31]
+ .size __modsi3,.-__modsi3
+#endif /* L_modsi3 */
+
+#ifdef L_save_2
+ .text
+ .align 2
+ .globl __save_r2_r29
+ .type __save_r2_r29,@function
+ /* Allocate space and save registers 2, 20 .. 29 on the stack */
+ /* Called via: jalr __save_r2_r29,r10 */
+__save_r2_r29:
+ mov ep,r1
+ addi -44,sp,sp
+ mov sp,ep
+ sst.w r29,0[ep]
+ sst.w r28,4[ep]
+ sst.w r27,8[ep]
+ sst.w r26,12[ep]
+ sst.w r25,16[ep]
+ sst.w r24,20[ep]
+ sst.w r23,24[ep]
+ sst.w r22,28[ep]
+ sst.w r21,32[ep]
+ sst.w r20,36[ep]
+ sst.w r2,40[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r2_r29,.-__save_r2_r29
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r2_r29 */
+ .align 2
+ .globl __return_r2_r29
+ .type __return_r2_r29,@function
+__return_r2_r29:
+ mov ep,r1
+ mov sp,ep
+ sld.w 0[ep],r29
+ sld.w 4[ep],r28
+ sld.w 8[ep],r27
+ sld.w 12[ep],r26
+ sld.w 16[ep],r25
+ sld.w 20[ep],r24
+ sld.w 24[ep],r23
+ sld.w 28[ep],r22
+ sld.w 32[ep],r21
+ sld.w 36[ep],r20
+ sld.w 40[ep],r2
+ addi 44,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r2_r29,.-__return_r2_r29
+#endif /* L_save_2 */
+
+#ifdef L_save_20
+ .text
+ .align 2
+ .globl __save_r20_r29
+ .type __save_r20_r29,@function
+ /* Allocate space and save registers 20 .. 29 on the stack */
+ /* Called via: jalr __save_r20_r29,r10 */
+__save_r20_r29:
+ mov ep,r1
+ addi -40,sp,sp
+ mov sp,ep
+ sst.w r29,0[ep]
+ sst.w r28,4[ep]
+ sst.w r27,8[ep]
+ sst.w r26,12[ep]
+ sst.w r25,16[ep]
+ sst.w r24,20[ep]
+ sst.w r23,24[ep]
+ sst.w r22,28[ep]
+ sst.w r21,32[ep]
+ sst.w r20,36[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r20_r29,.-__save_r20_r29
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r20_r29 */
+ .align 2
+ .globl __return_r20_r29
+ .type __return_r20_r29,@function
+__return_r20_r29:
+ mov ep,r1
+ mov sp,ep
+ sld.w 0[ep],r29
+ sld.w 4[ep],r28
+ sld.w 8[ep],r27
+ sld.w 12[ep],r26
+ sld.w 16[ep],r25
+ sld.w 20[ep],r24
+ sld.w 24[ep],r23
+ sld.w 28[ep],r22
+ sld.w 32[ep],r21
+ sld.w 36[ep],r20
+ addi 40,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r20_r29,.-__return_r20_r29
+#endif /* L_save_20 */
+
+#ifdef L_save_21
+ .text
+ .align 2
+ .globl __save_r21_r29
+ .type __save_r21_r29,@function
+ /* Allocate space and save registers 21 .. 29 on the stack */
+ /* Called via: jalr __save_r21_r29,r10 */
+__save_r21_r29:
+ mov ep,r1
+ addi -36,sp,sp
+ mov sp,ep
+ sst.w r29,0[ep]
+ sst.w r28,4[ep]
+ sst.w r27,8[ep]
+ sst.w r26,12[ep]
+ sst.w r25,16[ep]
+ sst.w r24,20[ep]
+ sst.w r23,24[ep]
+ sst.w r22,28[ep]
+ sst.w r21,32[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r21_r29,.-__save_r21_r29
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r21_r29 */
+ .align 2
+ .globl __return_r21_r29
+ .type __return_r21_r29,@function
+__return_r21_r29:
+ mov ep,r1
+ mov sp,ep
+ sld.w 0[ep],r29
+ sld.w 4[ep],r28
+ sld.w 8[ep],r27
+ sld.w 12[ep],r26
+ sld.w 16[ep],r25
+ sld.w 20[ep],r24
+ sld.w 24[ep],r23
+ sld.w 28[ep],r22
+ sld.w 32[ep],r21
+ addi 36,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r21_r29,.-__return_r21_r29
+#endif /* L_save_21 */
+
+#ifdef L_save_22
+ .text
+ .align 2
+ .globl __save_r22_r29
+ .type __save_r22_r29,@function
+ /* Allocate space and save registers 22 .. 29 on the stack */
+ /* Called via: jalr __save_r22_r29,r10 */
+__save_r22_r29:
+ mov ep,r1
+ addi -32,sp,sp
+ mov sp,ep
+ sst.w r29,0[ep]
+ sst.w r28,4[ep]
+ sst.w r27,8[ep]
+ sst.w r26,12[ep]
+ sst.w r25,16[ep]
+ sst.w r24,20[ep]
+ sst.w r23,24[ep]
+ sst.w r22,28[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r22_r29,.-__save_r22_r29
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r22_r29 */
+ .align 2
+ .globl __return_r22_r29
+ .type __return_r22_r29,@function
+__return_r22_r29:
+ mov ep,r1
+ mov sp,ep
+ sld.w 0[ep],r29
+ sld.w 4[ep],r28
+ sld.w 8[ep],r27
+ sld.w 12[ep],r26
+ sld.w 16[ep],r25
+ sld.w 20[ep],r24
+ sld.w 24[ep],r23
+ sld.w 28[ep],r22
+ addi 32,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r22_r29,.-__return_r22_r29
+#endif /* L_save_22 */
+
+#ifdef L_save_23
+ .text
+ .align 2
+ .globl __save_r23_r29
+ .type __save_r23_r29,@function
+ /* Allocate space and save registers 23 .. 29 on the stack */
+ /* Called via: jalr __save_r23_r29,r10 */
+__save_r23_r29:
+ mov ep,r1
+ addi -28,sp,sp
+ mov sp,ep
+ sst.w r29,0[ep]
+ sst.w r28,4[ep]
+ sst.w r27,8[ep]
+ sst.w r26,12[ep]
+ sst.w r25,16[ep]
+ sst.w r24,20[ep]
+ sst.w r23,24[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r23_r29,.-__save_r23_r29
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r23_r29 */
+ .align 2
+ .globl __return_r23_r29
+ .type __return_r23_r29,@function
+__return_r23_r29:
+ mov ep,r1
+ mov sp,ep
+ sld.w 0[ep],r29
+ sld.w 4[ep],r28
+ sld.w 8[ep],r27
+ sld.w 12[ep],r26
+ sld.w 16[ep],r25
+ sld.w 20[ep],r24
+ sld.w 24[ep],r23
+ addi 28,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r23_r29,.-__return_r23_r29
+#endif /* L_save_23 */
+
+#ifdef L_save_24
+ .text
+ .align 2
+ .globl __save_r24_r29
+ .type __save_r24_r29,@function
+ /* Allocate space and save registers 24 .. 29 on the stack */
+ /* Called via: jalr __save_r24_r29,r10 */
+__save_r24_r29:
+ mov ep,r1
+ addi -24,sp,sp
+ mov sp,ep
+ sst.w r29,0[ep]
+ sst.w r28,4[ep]
+ sst.w r27,8[ep]
+ sst.w r26,12[ep]
+ sst.w r25,16[ep]
+ sst.w r24,20[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r24_r29,.-__save_r24_r29
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r24_r29 */
+ .align 2
+ .globl __return_r24_r29
+ .type __return_r24_r29,@function
+__return_r24_r29:
+ mov ep,r1
+ mov sp,ep
+ sld.w 0[ep],r29
+ sld.w 4[ep],r28
+ sld.w 8[ep],r27
+ sld.w 12[ep],r26
+ sld.w 16[ep],r25
+ sld.w 20[ep],r24
+ addi 24,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r24_r29,.-__return_r24_r29
+#endif /* L_save_24 */
+
+#ifdef L_save_25
+ .text
+ .align 2
+ .globl __save_r25_r29
+ .type __save_r25_r29,@function
+ /* Allocate space and save registers 25 .. 29 on the stack */
+ /* Called via: jalr __save_r25_r29,r10 */
+__save_r25_r29:
+ mov ep,r1
+ addi -20,sp,sp
+ mov sp,ep
+ sst.w r29,0[ep]
+ sst.w r28,4[ep]
+ sst.w r27,8[ep]
+ sst.w r26,12[ep]
+ sst.w r25,16[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r25_r29,.-__save_r25_r29
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r25_r29 */
+ .align 2
+ .globl __return_r25_r29
+ .type __return_r25_r29,@function
+__return_r25_r29:
+ mov ep,r1
+ mov sp,ep
+ sld.w 0[ep],r29
+ sld.w 4[ep],r28
+ sld.w 8[ep],r27
+ sld.w 12[ep],r26
+ sld.w 16[ep],r25
+ addi 20,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r25_r29,.-__return_r25_r29
+#endif /* L_save_25 */
+
+#ifdef L_save_26
+ .text
+ .align 2
+ .globl __save_r26_r29
+ .type __save_r26_r29,@function
+ /* Allocate space and save registers 26 .. 29 on the stack */
+ /* Called via: jalr __save_r26_r29,r10 */
+__save_r26_r29:
+ mov ep,r1
+ add -16,sp
+ mov sp,ep
+ sst.w r29,0[ep]
+ sst.w r28,4[ep]
+ sst.w r27,8[ep]
+ sst.w r26,12[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r26_r29,.-__save_r26_r29
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r26_r29 */
+ .align 2
+ .globl __return_r26_r29
+ .type __return_r26_r29,@function
+__return_r26_r29:
+ mov ep,r1
+ mov sp,ep
+ sld.w 0[ep],r29
+ sld.w 4[ep],r28
+ sld.w 8[ep],r27
+ sld.w 12[ep],r26
+ addi 16,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r26_r29,.-__return_r26_r29
+#endif /* L_save_26 */
+
+#ifdef L_save_27
+ .text
+ .align 2
+ .globl __save_r27_r29
+ .type __save_r27_r29,@function
+ /* Allocate space and save registers 27 .. 29 on the stack */
+ /* Called via: jalr __save_r27_r29,r10 */
+__save_r27_r29:
+ add -12,sp
+ st.w r29,0[sp]
+ st.w r28,4[sp]
+ st.w r27,8[sp]
+ jmp [r10]
+ .size __save_r27_r29,.-__save_r27_r29
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r27_r29 */
+ .align 2
+ .globl __return_r27_r29
+ .type __return_r27_r29,@function
+__return_r27_r29:
+ ld.w 0[sp],r29
+ ld.w 4[sp],r28
+ ld.w 8[sp],r27
+ add 12,sp
+ jmp [r31]
+ .size __return_r27_r29,.-__return_r27_r29
+#endif /* L_save_27 */
+
+#ifdef L_save_28
+ .text
+ .align 2
+ .globl __save_r28_r29
+ .type __save_r28_r29,@function
+ /* Allocate space and save registers 28,29 on the stack */
+ /* Called via: jalr __save_r28_r29,r10 */
+__save_r28_r29:
+ add -8,sp
+ st.w r29,0[sp]
+ st.w r28,4[sp]
+ jmp [r10]
+ .size __save_r28_r29,.-__save_r28_r29
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r28_r29 */
+ .align 2
+ .globl __return_r28_r29
+ .type __return_r28_r29,@function
+__return_r28_r29:
+ ld.w 0[sp],r29
+ ld.w 4[sp],r28
+ add 8,sp
+ jmp [r31]
+ .size __return_r28_r29,.-__return_r28_r29
+#endif /* L_save_28 */
+
+#ifdef L_save_29
+ .text
+ .align 2
+ .globl __save_r29
+ .type __save_r29,@function
+ /* Allocate space and save register 29 on the stack */
+ /* Called via: jalr __save_r29,r10 */
+__save_r29:
+ add -4,sp
+ st.w r29,0[sp]
+ jmp [r10]
+ .size __save_r29,.-__save_r29
+
+ /* Restore saved register 29, deallocate stack and return to the user */
+ /* Called via: jr __return_r29 */
+ .align 2
+ .globl __return_r29
+ .type __return_r29,@function
+__return_r29:
+ ld.w 0[sp],r29
+ add 4,sp
+ jmp [r31]
+ .size __return_r29,.-__return_r29
+#endif /* L_save_28 */
+
+#ifdef L_save_2c
+ .text
+ .align 2
+ .globl __save_r2_r31
+ .type __save_r2_r31,@function
+ /* Allocate space and save registers 20 .. 29, 31 on the stack */
+ /* Also allocate space for the argument save area */
+ /* Called via: jalr __save_r2_r31,r10 */
+__save_r2_r31:
+ mov ep,r1
+ addi -64,sp,sp
+ mov sp,ep
+ sst.w r29,16[ep]
+ sst.w r28,20[ep]
+ sst.w r27,24[ep]
+ sst.w r26,28[ep]
+ sst.w r25,32[ep]
+ sst.w r24,36[ep]
+ sst.w r23,40[ep]
+ sst.w r22,44[ep]
+ sst.w r21,48[ep]
+ sst.w r20,52[ep]
+ sst.w r2,56[ep]
+ sst.w r31,60[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r2_r31,.-__save_r2_r31
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r20_r31 */
+ .align 2
+ .globl __return_r2_r31
+ .type __return_r2_r31,@function
+__return_r2_r31:
+ mov ep,r1
+ mov sp,ep
+ sld.w 16[ep],r29
+ sld.w 20[ep],r28
+ sld.w 24[ep],r27
+ sld.w 28[ep],r26
+ sld.w 32[ep],r25
+ sld.w 36[ep],r24
+ sld.w 40[ep],r23
+ sld.w 44[ep],r22
+ sld.w 48[ep],r21
+ sld.w 52[ep],r20
+ sld.w 56[ep],r2
+ sld.w 60[ep],r31
+ addi 64,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r2_r31,.-__return_r2_r31
+#endif /* L_save_2c */
+
+#ifdef L_save_20c
+ .text
+ .align 2
+ .globl __save_r20_r31
+ .type __save_r20_r31,@function
+ /* Allocate space and save registers 20 .. 29, 31 on the stack */
+ /* Also allocate space for the argument save area */
+ /* Called via: jalr __save_r20_r31,r10 */
+__save_r20_r31:
+ mov ep,r1
+ addi -60,sp,sp
+ mov sp,ep
+ sst.w r29,16[ep]
+ sst.w r28,20[ep]
+ sst.w r27,24[ep]
+ sst.w r26,28[ep]
+ sst.w r25,32[ep]
+ sst.w r24,36[ep]
+ sst.w r23,40[ep]
+ sst.w r22,44[ep]
+ sst.w r21,48[ep]
+ sst.w r20,52[ep]
+ sst.w r31,56[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r20_r31,.-__save_r20_r31
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r20_r31 */
+ .align 2
+ .globl __return_r20_r31
+ .type __return_r20_r31,@function
+__return_r20_r31:
+ mov ep,r1
+ mov sp,ep
+ sld.w 16[ep],r29
+ sld.w 20[ep],r28
+ sld.w 24[ep],r27
+ sld.w 28[ep],r26
+ sld.w 32[ep],r25
+ sld.w 36[ep],r24
+ sld.w 40[ep],r23
+ sld.w 44[ep],r22
+ sld.w 48[ep],r21
+ sld.w 52[ep],r20
+ sld.w 56[ep],r31
+ addi 60,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r20_r31,.-__return_r20_r31
+#endif /* L_save_20c */
+
+#ifdef L_save_21c
+ .text
+ .align 2
+ .globl __save_r21_r31
+ .type __save_r21_r31,@function
+ /* Allocate space and save registers 21 .. 29, 31 on the stack */
+ /* Also allocate space for the argument save area */
+ /* Called via: jalr __save_r21_r31,r10 */
+__save_r21_r31:
+ mov ep,r1
+ addi -56,sp,sp
+ mov sp,ep
+ sst.w r29,16[ep]
+ sst.w r28,20[ep]
+ sst.w r27,24[ep]
+ sst.w r26,28[ep]
+ sst.w r25,32[ep]
+ sst.w r24,36[ep]
+ sst.w r23,40[ep]
+ sst.w r22,44[ep]
+ sst.w r21,48[ep]
+ sst.w r31,52[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r21_r31,.-__save_r21_r31
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r21_r31 */
+ .align 2
+ .globl __return_r21_r31
+ .type __return_r21_r31,@function
+__return_r21_r31:
+ mov ep,r1
+ mov sp,ep
+ sld.w 16[ep],r29
+ sld.w 20[ep],r28
+ sld.w 24[ep],r27
+ sld.w 28[ep],r26
+ sld.w 32[ep],r25
+ sld.w 36[ep],r24
+ sld.w 40[ep],r23
+ sld.w 44[ep],r22
+ sld.w 48[ep],r21
+ sld.w 52[ep],r31
+ addi 56,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r21_r31,.-__return_r21_r31
+#endif /* L_save_21c */
+
+#ifdef L_save_22c
+ .text
+ .align 2
+ .globl __save_r22_r31
+ .type __save_r22_r31,@function
+ /* Allocate space and save registers 22 .. 29, 31 on the stack */
+ /* Also allocate space for the argument save area */
+ /* Called via: jalr __save_r22_r31,r10 */
+__save_r22_r31:
+ mov ep,r1
+ addi -52,sp,sp
+ mov sp,ep
+ sst.w r29,16[ep]
+ sst.w r28,20[ep]
+ sst.w r27,24[ep]
+ sst.w r26,28[ep]
+ sst.w r25,32[ep]
+ sst.w r24,36[ep]
+ sst.w r23,40[ep]
+ sst.w r22,44[ep]
+ sst.w r31,48[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r22_r31,.-__save_r22_r31
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r22_r31 */
+ .align 2
+ .globl __return_r22_r31
+ .type __return_r22_r31,@function
+__return_r22_r31:
+ mov ep,r1
+ mov sp,ep
+ sld.w 16[ep],r29
+ sld.w 20[ep],r28
+ sld.w 24[ep],r27
+ sld.w 28[ep],r26
+ sld.w 32[ep],r25
+ sld.w 36[ep],r24
+ sld.w 40[ep],r23
+ sld.w 44[ep],r22
+ sld.w 48[ep],r31
+ addi 52,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r22_r31,.-__return_r22_r31
+#endif /* L_save_22c */
+
+#ifdef L_save_23c
+ .text
+ .align 2
+ .globl __save_r23_r31
+ .type __save_r23_r31,@function
+ /* Allocate space and save registers 23 .. 29, 31 on the stack */
+ /* Also allocate space for the argument save area */
+ /* Called via: jalr __save_r23_r31,r10 */
+__save_r23_r31:
+ mov ep,r1
+ addi -48,sp,sp
+ mov sp,ep
+ sst.w r29,16[ep]
+ sst.w r28,20[ep]
+ sst.w r27,24[ep]
+ sst.w r26,28[ep]
+ sst.w r25,32[ep]
+ sst.w r24,36[ep]
+ sst.w r23,40[ep]
+ sst.w r31,44[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r23_r31,.-__save_r23_r31
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r23_r31 */
+ .align 2
+ .globl __return_r23_r31
+ .type __return_r23_r31,@function
+__return_r23_r31:
+ mov ep,r1
+ mov sp,ep
+ sld.w 16[ep],r29
+ sld.w 20[ep],r28
+ sld.w 24[ep],r27
+ sld.w 28[ep],r26
+ sld.w 32[ep],r25
+ sld.w 36[ep],r24
+ sld.w 40[ep],r23
+ sld.w 44[ep],r31
+ addi 48,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r23_r31,.-__return_r23_r31
+#endif /* L_save_23c */
+
+#ifdef L_save_24c
+ .text
+ .align 2
+ .globl __save_r24_r31
+ .type __save_r24_r31,@function
+ /* Allocate space and save registers 24 .. 29, 31 on the stack */
+ /* Also allocate space for the argument save area */
+ /* Called via: jalr __save_r24_r31,r10 */
+__save_r24_r31:
+ mov ep,r1
+ addi -44,sp,sp
+ mov sp,ep
+ sst.w r29,16[ep]
+ sst.w r28,20[ep]
+ sst.w r27,24[ep]
+ sst.w r26,28[ep]
+ sst.w r25,32[ep]
+ sst.w r24,36[ep]
+ sst.w r31,40[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r24_r31,.-__save_r24_r31
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r24_r31 */
+ .align 2
+ .globl __return_r24_r31
+ .type __return_r24_r31,@function
+__return_r24_r31:
+ mov ep,r1
+ mov sp,ep
+ sld.w 16[ep],r29
+ sld.w 20[ep],r28
+ sld.w 24[ep],r27
+ sld.w 28[ep],r26
+ sld.w 32[ep],r25
+ sld.w 36[ep],r24
+ sld.w 40[ep],r31
+ addi 44,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r24_r31,.-__return_r24_r31
+#endif /* L_save_24c */
+
+#ifdef L_save_25c
+ .text
+ .align 2
+ .globl __save_r25_r31
+ .type __save_r25_r31,@function
+ /* Allocate space and save registers 25 .. 29, 31 on the stack */
+ /* Also allocate space for the argument save area */
+ /* Called via: jalr __save_r25_r31,r10 */
+__save_r25_r31:
+ mov ep,r1
+ addi -40,sp,sp
+ mov sp,ep
+ sst.w r29,16[ep]
+ sst.w r28,20[ep]
+ sst.w r27,24[ep]
+ sst.w r26,28[ep]
+ sst.w r25,32[ep]
+ sst.w r31,36[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r25_r31,.-__save_r25_r31
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r25_r31 */
+ .align 2
+ .globl __return_r25_r31
+ .type __return_r25_r31,@function
+__return_r25_r31:
+ mov ep,r1
+ mov sp,ep
+ sld.w 16[ep],r29
+ sld.w 20[ep],r28
+ sld.w 24[ep],r27
+ sld.w 28[ep],r26
+ sld.w 32[ep],r25
+ sld.w 36[ep],r31
+ addi 40,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r25_r31,.-__return_r25_r31
+#endif /* L_save_25c */
+
+#ifdef L_save_26c
+ .text
+ .align 2
+ .globl __save_r26_r31
+ .type __save_r26_r31,@function
+ /* Allocate space and save registers 26 .. 29, 31 on the stack */
+ /* Also allocate space for the argument save area */
+ /* Called via: jalr __save_r26_r31,r10 */
+__save_r26_r31:
+ mov ep,r1
+ addi -36,sp,sp
+ mov sp,ep
+ sst.w r29,16[ep]
+ sst.w r28,20[ep]
+ sst.w r27,24[ep]
+ sst.w r26,28[ep]
+ sst.w r31,32[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r26_r31,.-__save_r26_r31
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r26_r31 */
+ .align 2
+ .globl __return_r26_r31
+ .type __return_r26_r31,@function
+__return_r26_r31:
+ mov ep,r1
+ mov sp,ep
+ sld.w 16[ep],r29
+ sld.w 20[ep],r28
+ sld.w 24[ep],r27
+ sld.w 28[ep],r26
+ sld.w 32[ep],r31
+ addi 36,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r26_r31,.-__return_r26_r31
+#endif /* L_save_26c */
+
+#ifdef L_save_27c
+ .text
+ .align 2
+ .globl __save_r27_r31
+ .type __save_r27_r31,@function
+ /* Allocate space and save registers 27 .. 29, 31 on the stack */
+ /* Also allocate space for the argument save area */
+ /* Called via: jalr __save_r27_r31,r10 */
+__save_r27_r31:
+ mov ep,r1
+ addi -32,sp,sp
+ mov sp,ep
+ sst.w r29,16[ep]
+ sst.w r28,20[ep]
+ sst.w r27,24[ep]
+ sst.w r31,28[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_r27_r31,.-__save_r27_r31
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r27_r31 */
+ .align 2
+ .globl __return_r27_r31
+ .type __return_r27_r31,@function
+__return_r27_r31:
+ mov ep,r1
+ mov sp,ep
+ sld.w 16[ep],r29
+ sld.w 20[ep],r28
+ sld.w 24[ep],r27
+ sld.w 28[ep],r31
+ addi 32,sp,sp
+ mov r1,ep
+ jmp [r31]
+ .size __return_r27_r31,.-__return_r27_r31
+#endif /* L_save_27c */
+
+#ifdef L_save_28c
+ .text
+ .align 2
+ .globl __save_r28_r31
+ .type __save_r28_r31,@function
+ /* Allocate space and save registers 28 .. 29, 31 on the stack */
+ /* Also allocate space for the argument save area */
+ /* Called via: jalr __save_r28_r31,r10 */
+__save_r28_r31:
+ addi -28,sp,sp
+ st.w r29,16[sp]
+ st.w r28,20[sp]
+ st.w r31,24[sp]
+ jmp [r10]
+ .size __save_r28_r31,.-__save_r28_r31
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r28_r31 */
+ .align 2
+ .globl __return_r28_r31
+ .type __return_r28_r31,@function
+__return_r28_r31:
+ ld.w 16[sp],r29
+ ld.w 20[sp],r28
+ ld.w 24[sp],r31
+ addi 28,sp,sp
+ jmp [r31]
+ .size __return_r28_r31,.-__return_r28_r31
+#endif /* L_save_28c */
+
+#ifdef L_save_29c
+ .text
+ .align 2
+ .globl __save_r29_r31
+ .type __save_r29_r31,@function
+ /* Allocate space and save registers 29 & 31 on the stack */
+ /* Also allocate space for the argument save area */
+ /* Called via: jalr __save_r29_r31,r10 */
+__save_r29_r31:
+ addi -24,sp,sp
+ st.w r29,16[sp]
+ st.w r31,20[sp]
+ jmp [r10]
+ .size __save_r29_r31,.-__save_r29_r31
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r29_r31 */
+ .align 2
+ .globl __return_r29_r31
+ .type __return_r29_r31,@function
+__return_r29_r31:
+ ld.w 16[sp],r29
+ ld.w 20[sp],r31
+ addi 24,sp,sp
+ jmp [r31]
+ .size __return_r29_r31,.-__return_r29_r31
+#endif /* L_save_29c */
+
+#ifdef L_save_31c
+ .text
+ .align 2
+ .globl __save_r31
+ .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]
+ jmp [r10]
+ .size __save_r31,.-__save_r31
+
+ /* Restore saved registers, deallocate stack and return to the user */
+ /* Called via: jr __return_r31 */
+ .align 2
+ .globl __return_r31
+ .type __return_r31,@function
+__return_r31:
+ 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
+ .text
+ .align 2
+ .globl __save_r6_r9
+ .type __save_r6_r9,@function
+ /* Save registers 6 .. 9 on the stack for variable argument functions */
+ /* Called via: jalr __save_r6_r9,r10 */
+__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
+ jmp [r10]
+ .size __save_r6_r9,.-__save_r6_r9
+#endif /* L_save_varargs */
+
+#ifdef L_save_interrupt
+ .text
+ .align 2
+ .globl __save_interrupt
+ .type __save_interrupt,@function
+ /* Save registers r1, r5 on stack and load up with expected values */
+ /* Note, 12 bytes of stack have already been allocated. */
+ /* Called via: jalr __save_interrupt,r10 */
+__save_interrupt:
+ st.w ep,0[sp]
+ st.w gp,4[sp]
+ st.w r1,8[sp]
+ movhi hi(__ep),r0,ep
+ movea lo(__ep),ep,ep
+ movhi hi(__gp),r0,gp
+ movea lo(__gp),gp,gp
+ jmp [r10]
+ .size __save_interrupt,.-__save_interrupt
+
+ /* Restore saved registers, deallocate stack and return from the interrupt */
+ /* Called via: jr __return_interupt */
+ .align 2
+ .globl __return_interrupt
+ .type __return_interrupt,@function
+__return_interrupt:
+ ld.w 0[sp],ep
+ ld.w 4[sp],gp
+ ld.w 8[ep],r1
+ ld.w 12[ep],r10
+ add 12,sp
+ reti
+ .size __return_interrupt,.-__return_interrupt
+#endif /* L_save_interrupt */
+
+#ifdef L_save_all_interrupt
+ .text
+ .align 2
+ .globl __save_all_interrupt
+ .type __save_all_interrupt,@function
+ /* Save all registers except for those saved in __save_interrupt */
+ /* allocate enough stack for all of the registers & 16 bytes of space */
+ /* Called via: jalr __save_all_interrupt,r10 */
+__save_all_interrupt:
+ addi -120,sp,sp
+ mov ep,r1
+ mov sp,ep
+ sst.w r31,116[ep]
+ sst.w r2,112[ep]
+ sst.w gp,108[ep]
+ sst.w r6,104[ep]
+ sst.w r7,100[ep]
+ sst.w r8,96[ep]
+ sst.w r9,92[ep]
+ sst.w r11,88[ep]
+ sst.w r12,84[ep]
+ sst.w r13,80[ep]
+ sst.w r14,76[ep]
+ sst.w r15,72[ep]
+ sst.w r16,68[ep]
+ sst.w r17,64[ep]
+ sst.w r18,60[ep]
+ sst.w r19,56[ep]
+ sst.w r20,52[ep]
+ sst.w r21,48[ep]
+ sst.w r22,44[ep]
+ sst.w r23,40[ep]
+ sst.w r24,36[ep]
+ sst.w r25,32[ep]
+ sst.w r26,28[ep]
+ sst.w r27,24[ep]
+ sst.w r28,20[ep]
+ sst.w r29,16[ep]
+ mov r1,ep
+ jmp [r10]
+ .size __save_all_interrupt,.-__save_all_interrupt
+
+ .globl __restore_all_interrupt
+ .type __restore_all_interrupt,@function
+ /* Restore all registers saved in __save_all_interrupt */
+ /* & deallocate the stack space */
+ /* Called via: jalr __restore_all_interrupt,r10 */
+__restore_all_interrupt:
+ mov ep,r1
+ mov sp,ep
+ sld.w 116[ep],r31
+ sld.w 112[ep],r2
+ sld.w 108[ep],gp
+ sld.w 104[ep],r6
+ sld.w 100[ep],r7
+ sld.w 96[ep],r8
+ sld.w 92[ep],r9
+ sld.w 88[ep],r11
+ sld.w 84[ep],r12
+ sld.w 80[ep],r13
+ sld.w 76[ep],r14
+ sld.w 72[ep],r15
+ sld.w 68[ep],r16
+ sld.w 64[ep],r17
+ sld.w 60[ep],r18
+ sld.w 56[ep],r19
+ sld.w 52[ep],r20
+ sld.w 48[ep],r21
+ sld.w 44[ep],r22
+ sld.w 40[ep],r23
+ sld.w 36[ep],r24
+ sld.w 32[ep],r25
+ sld.w 28[ep],r26
+ sld.w 24[ep],r27
+ sld.w 20[ep],r28
+ sld.w 16[ep],r29
+ mov r1,ep
+ addi 120,sp,sp
+ jmp [r10]
+ .size __restore_all_interrupt,.-__restore_all_interrupt
+#endif /* L_save_all_interrupt */
+/* END CYGNUS LOCAL */
diff --git a/gcc/config/v850/t-v850 b/gcc/config/v850/t-v850
new file mode 100644
index 0000000..5203441
--- /dev/null
+++ b/gcc/config/v850/t-v850
@@ -0,0 +1,54 @@
+# CYGNUS LOCAL entire file v850/law
+CROSS_LIBGCC1 = libgcc1-asm.a
+LIB1ASMSRC = v850/lib1funcs.asm
+LIB1ASMFUNCS = _mulsi3 \
+ _divsi3 \
+ _udivsi3 \
+ _modsi3 \
+ _umodsi3 \
+ _save_2 \
+ _save_20 \
+ _save_21 \
+ _save_22 \
+ _save_23 \
+ _save_24 \
+ _save_25 \
+ _save_26 \
+ _save_27 \
+ _save_28 \
+ _save_29 \
+ _save_2c \
+ _save_20c \
+ _save_21c \
+ _save_22c \
+ _save_23c \
+ _save_24c \
+ _save_25c \
+ _save_26c \
+ _save_27c \
+ _save_28c \
+ _save_29c \
+ _save_31c \
+ _save_varargs \
+ _save_interrupt \
+ _save_all_interrupt
+
+
+# These are really part of libgcc1, but this will cause them to be
+# built correctly, so...
+
+LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#ifdef __LITTLE_ENDIAN__' > dp-bit.c
+ echo '#define FLOAT_BIT_ORDER_MISMATCH' >>dp-bit.c
+ echo '#endif' >> dp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ echo '#ifdef __LITTLE_ENDIAN__' >> fp-bit.c
+ echo '#define FLOAT_BIT_ORDER_MISMATCH' >>fp-bit.c
+ echo '#endif' >> fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+#END CYGNUS LOCAL
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
new file mode 100644
index 0000000..6435d409
--- /dev/null
+++ b/gcc/config/v850/v850.c
@@ -0,0 +1,1942 @@
+/* Subroutines for insn-output.c for NEC V850 series
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Contributed by Jeff Law (law@cygnus.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "config.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-flags.h"
+#include "output.h"
+#include "insn-attr.h"
+#include "flags.h"
+#include "recog.h"
+#include "expr.h"
+#include "tree.h"
+#include "obstack.h"
+
+/* True if the current function has anonymous arguments. */
+int current_function_anonymous_args;
+
+/* Information about the various small memory areas. */
+struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] =
+{
+ /* name value max physical max */
+ { "tda", (char *)0, 0, 256 },
+ { "sda", (char *)0, 0, 65536 },
+ { "zda", (char *)0, 0, 32768 },
+};
+
+/* True if we don't need to check any more if the current
+ function is an interrupt handler */
+static int v850_interrupt_cache_p = FALSE;
+
+/* Whether current function is an interrupt handler. */
+static int v850_interrupt_p = FALSE;
+
+
+/* Sometimes certain combinations of command options do not make
+ sense on a particular target machine. You can define a macro
+ `OVERRIDE_OPTIONS' to take account of this. This macro, if
+ defined, is executed once just after all the command options have
+ been parsed.
+
+ Don't use this macro to turn on various extra optimizations for
+ `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
+
+void
+override_options ()
+{
+ int i;
+ extern int atoi ();
+
+ /* Parse -m{s,t,z}da=nnn switches */
+ for (i = 0; i < (int)SMALL_MEMORY_max; i++)
+ {
+ if (small_memory[i].value)
+ {
+ if (!isdigit (*small_memory[i].value))
+ error ("%s=%s is not numeric.",
+ small_memory[i].name,
+ small_memory[i].value);
+ else
+ {
+ small_memory[i].max = atoi (small_memory[i].value);
+ if (small_memory[i].max > small_memory[i].physical_max)
+ error ("%s=%s is too large.",
+ small_memory[i].name,
+ small_memory[i].value);
+ }
+ }
+ }
+}
+
+
+/* Output assembly code for the start of the file. */
+
+void
+asm_file_start (file)
+ FILE *file;
+{
+ output_file_directive (file, main_input_filename);
+}
+
+
+/* Return an RTX to represent where a value with mode MODE will be returned
+ from a function. If the result is 0, the argument is pushed. */
+
+rtx
+function_arg (cum, mode, type, named)
+ CUMULATIVE_ARGS *cum;
+ enum machine_mode mode;
+ tree type;
+ int named;
+{
+ rtx result = 0;
+ int size, align;
+
+ if (TARGET_GHS && !named)
+ return NULL_RTX;
+
+ if (mode == BLKmode)
+ size = int_size_in_bytes (type);
+ else
+ size = GET_MODE_SIZE (mode);
+
+ if (type)
+ align = TYPE_ALIGN (type) / BITS_PER_UNIT;
+ else
+ align = size;
+
+ cum->nbytes = (cum->nbytes + align - 1) &~(align - 1);
+
+ if (cum->nbytes > 4 * UNITS_PER_WORD)
+ return 0;
+
+ if (type == NULL_TREE
+ && cum->nbytes + size > 4 * UNITS_PER_WORD)
+ return 0;
+
+ switch (cum->nbytes / UNITS_PER_WORD)
+ {
+ case 0:
+ result = gen_rtx (REG, mode, 6);
+ break;
+ case 1:
+ result = gen_rtx (REG, mode, 7);
+ break;
+ case 2:
+ result = gen_rtx (REG, mode, 8);
+ break;
+ case 3:
+ result = gen_rtx (REG, mode, 9);
+ break;
+ default:
+ result = 0;
+ }
+
+ return result;
+}
+
+
+/* Return the number of words which must be put into registers
+ for values which are part in registers and part in memory. */
+
+int
+function_arg_partial_nregs (cum, mode, type, named)
+ CUMULATIVE_ARGS *cum;
+ enum machine_mode mode;
+ tree type;
+ int named;
+{
+ int size, align;
+
+ if (TARGET_GHS && !named)
+ return 0;
+
+ if (mode == BLKmode)
+ size = int_size_in_bytes (type);
+ else
+ size = GET_MODE_SIZE (mode);
+
+ if (type)
+ align = TYPE_ALIGN (type) / BITS_PER_UNIT;
+ else
+ align = size;
+
+ cum->nbytes = (cum->nbytes + align - 1) &~(align - 1);
+
+ if (cum->nbytes > 4 * UNITS_PER_WORD)
+ return 0;
+
+ if (cum->nbytes + size <= 4 * UNITS_PER_WORD)
+ return 0;
+
+ if (type == NULL_TREE
+ && cum->nbytes + size > 4 * UNITS_PER_WORD)
+ return 0;
+
+ return (4 * UNITS_PER_WORD - cum->nbytes) / UNITS_PER_WORD;
+}
+
+
+/* Return the high and low words of a CONST_DOUBLE */
+
+static void
+const_double_split (x, p_high, p_low)
+ rtx x;
+ HOST_WIDE_INT *p_high;
+ HOST_WIDE_INT *p_low;
+{
+ if (GET_CODE (x) == CONST_DOUBLE)
+ {
+ long t[2];
+ REAL_VALUE_TYPE rv;
+
+ switch (GET_MODE (x))
+ {
+ case DFmode:
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
+ REAL_VALUE_TO_TARGET_DOUBLE (rv, t);
+ *p_high = t[1]; /* since v850 is little endian */
+ *p_low = t[0]; /* high is second word */
+ return;
+
+ case SFmode:
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
+ REAL_VALUE_TO_TARGET_SINGLE (rv, *p_high);
+ *p_low = 0;
+ return;
+
+ case VOIDmode:
+ case DImode:
+ *p_high = CONST_DOUBLE_HIGH (x);
+ *p_low = CONST_DOUBLE_LOW (x);
+ return;
+ }
+ }
+
+ fatal_insn ("const_double_split got a bad insn:", x);
+}
+
+
+/* Return the cost of the rtx R with code CODE. */
+
+static int
+const_costs_int (value, zero_cost)
+ HOST_WIDE_INT value;
+ int zero_cost;
+{
+ if (CONST_OK_FOR_I (value))
+ return zero_cost;
+ else if (CONST_OK_FOR_J (value))
+ return 1;
+ else if (CONST_OK_FOR_K (value))
+ return 2;
+ else
+ return 4;
+}
+
+int
+const_costs (r, c)
+ rtx r;
+ enum rtx_code c;
+{
+ HOST_WIDE_INT high, low;
+
+ switch (c)
+ {
+ case CONST_INT:
+ return const_costs_int (INTVAL (r), 0);
+
+ case CONST_DOUBLE:
+ const_double_split (r, &high, &low);
+ if (GET_MODE (r) == SFmode)
+ return const_costs_int (high, 1);
+ else
+ return const_costs_int (high, 1) + const_costs_int (low, 1);
+
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case CONST:
+ return 2;
+
+ case HIGH:
+ return 1;
+
+ default:
+ return 4;
+ }
+}
+
+
+/* Print operand X using operand code CODE to assembly language output file
+ FILE. */
+
+void
+print_operand (file, x, code)
+ FILE *file;
+ rtx x;
+ int code;
+{
+ HOST_WIDE_INT high, low;
+
+ switch (code)
+ {
+ case 'b':
+ case 'B':
+ switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
+ {
+ case NE:
+ fprintf (file, "bne");
+ break;
+ case EQ:
+ fprintf (file, "be");
+ break;
+ case GE:
+ fprintf (file, "bge");
+ 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");
+ 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");
+ break;
+ default:
+ abort ();
+ }
+ break;
+ case 'F': /* high word of CONST_DOUBLE */
+ if (GET_CODE (x) == CONST_INT)
+ fprintf (file, "%d", (INTVAL (x) >= 0) ? 0 : -1);
+ else if (GET_CODE (x) == CONST_DOUBLE)
+ {
+ const_double_split (x, &high, &low);
+ fprintf (file, "%ld", (long) high);
+ }
+ else
+ abort ();
+ break;
+ case 'G': /* low word of CONST_DOUBLE */
+ if (GET_CODE (x) == CONST_INT)
+ fprintf (file, "%ld", (long) INTVAL (x));
+ else if (GET_CODE (x) == CONST_DOUBLE)
+ {
+ const_double_split (x, &high, &low);
+ fprintf (file, "%ld", (long) low);
+ }
+ else
+ abort ();
+ break;
+ case 'L':
+ fprintf (file, "%d\n", INTVAL (x) & 0xffff);
+ break;
+ case 'M':
+ fprintf (file, "%d", exact_log2 (INTVAL (x)));
+ break;
+ case 'O':
+ if (special_symbolref_operand (x, VOIDmode))
+ {
+ char* name;
+
+ if (GET_CODE (x) == SYMBOL_REF)
+ name = XSTR (x, 0);
+ else if (GET_CODE (x) == CONST)
+ name = XSTR (XEXP (XEXP (x, 0), 0), 0);
+ else
+ abort ();
+
+ if (ZDA_NAME_P (name))
+ fprintf (file, "zdaoff");
+ else if (SDA_NAME_P (name))
+ fprintf (file, "sdaoff");
+ else if (TDA_NAME_P (name))
+ fprintf (file, "tdaoff");
+ else
+ abort();
+ }
+ else
+ abort();
+ break;
+ case 'P':
+ if (special_symbolref_operand (x, VOIDmode))
+ output_addr_const (file, x);
+ else
+ abort();
+ break;
+ case 'Q':
+ if (special_symbolref_operand (x, VOIDmode))
+ {
+ char* name;
+
+ if (GET_CODE (x) == SYMBOL_REF)
+ name = XSTR (x, 0);
+ else if (GET_CODE (x) == CONST)
+ name = XSTR (XEXP (XEXP (x, 0), 0), 0);
+ else
+ abort ();
+
+ if (ZDA_NAME_P (name))
+ fprintf (file, "r0");
+ else if (SDA_NAME_P (name))
+ fprintf (file, "gp");
+ else if (TDA_NAME_P (name))
+ fprintf (file, "ep");
+ else
+ abort();
+ }
+ else
+ abort();
+ break;
+ case 'R': /* 2nd word of a double. */
+ switch (GET_CODE (x))
+ {
+ case REG:
+ fprintf (file, reg_names[REGNO (x) + 1]);
+ break;
+ case MEM:
+ print_operand_address (file,
+ XEXP (adj_offsettable_operand (x, 4), 0));
+ break;
+ }
+ break;
+ case 'S':
+ {
+ /* if it's a referance to a TDA variable, use sst/sld vs. st/ld */
+ if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x)))
+ fputs ("s", file);
+
+ break;
+ }
+ case 'W': /* print the instruction suffix */
+ switch (GET_MODE (x))
+ {
+ default:
+ abort ();
+
+ case QImode: fputs (".b", file); break;
+ case HImode: fputs (".h", file); break;
+ case SImode: fputs (".w", file); break;
+ case SFmode: fputs (".w", file); break;
+ }
+ break;
+ case '.': /* register r0 */
+ fputs (reg_names[0], file);
+ break;
+ default:
+ switch (GET_CODE (x))
+ {
+ case MEM:
+ if (GET_CODE (XEXP (x, 0)) == CONST_INT)
+ output_address (gen_rtx (PLUS, SImode,
+ gen_rtx (REG, SImode, 0),
+ XEXP (x, 0)));
+ else
+ output_address (XEXP (x, 0));
+ break;
+
+ case REG:
+ fputs (reg_names[REGNO (x)], file);
+ break;
+ case SUBREG:
+ fputs (reg_names[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)], file);
+ break;
+ case CONST_INT:
+ case SYMBOL_REF:
+ case CONST:
+ case LABEL_REF:
+ case CODE_LABEL:
+ print_operand_address (file, x);
+ break;
+ default:
+ abort ();
+ }
+ break;
+
+ }
+}
+
+
+/* Output assembly language output for the address ADDR to FILE. */
+
+void
+print_operand_address (file, addr)
+ FILE *file;
+ rtx addr;
+{
+ switch (GET_CODE (addr))
+ {
+ case REG:
+ fprintf (file, "0[");
+ print_operand (file, addr, 0);
+ fprintf (file, "]");
+ break;
+ case LO_SUM:
+ if (GET_CODE (XEXP (addr, 0)) == REG)
+ {
+ /* reg,foo */
+ fprintf (file, "lo(");
+ print_operand (file, XEXP (addr, 1), 0);
+ fprintf (file, ")[");
+ print_operand (file, XEXP (addr, 0), 0);
+ fprintf (file, "]");
+ }
+ break;
+ case PLUS:
+ if (GET_CODE (XEXP (addr, 0)) == REG
+ || GET_CODE (XEXP (addr, 0)) == SUBREG)
+ {
+ /* reg,foo */
+ print_operand (file, XEXP (addr, 1), 0);
+ fprintf (file, "[");
+ print_operand (file, XEXP (addr, 0), 0);
+ fprintf (file, "]");
+ }
+ else
+ {
+ print_operand (file, XEXP (addr, 0), 0);
+ fprintf (file, "+");
+ print_operand (file, XEXP (addr, 1), 0);
+ }
+ break;
+ case SYMBOL_REF:
+ if (ENCODED_NAME_P (XSTR (addr, 0)))
+ {
+ char* name = XSTR (addr, 0);
+ char* off_name;
+ char* reg_name;
+
+ if (ZDA_NAME_P (name))
+ {
+ off_name = "zdaoff";
+ reg_name = "r0";
+ }
+ else if (SDA_NAME_P (name))
+ {
+ off_name = "sdaoff";
+ reg_name = "gp";
+ }
+ else if (TDA_NAME_P (name))
+ {
+ off_name = "tdaoff";
+ reg_name = "ep";
+ }
+ else
+ abort();
+
+ fprintf (file, "%s(", off_name);
+ output_addr_const (file, addr);
+ fprintf (file, ")[%s]", reg_name);
+ }
+ else
+ output_addr_const (file, addr);
+ break;
+ case CONST:
+ if (special_symbolref_operand (addr, VOIDmode))
+ {
+ char* name = XSTR (XEXP (XEXP (addr, 0), 0), 0);
+ char* off_name;
+ char* reg_name;
+
+ if (ZDA_NAME_P (name))
+ {
+ off_name = "zdaoff";
+ reg_name = "r0";
+ }
+ else if (SDA_NAME_P (name))
+ {
+ off_name = "sdaoff";
+ reg_name = "gp";
+ }
+ else if (TDA_NAME_P (name))
+ {
+ off_name = "tdaoff";
+ reg_name = "ep";
+ }
+ else
+ abort();
+
+ fprintf (file, "%s(", off_name);
+ output_addr_const (file, addr);
+ fprintf (file, ")[%s]", reg_name);
+ }
+ else
+ output_addr_const (file, addr);
+ break;
+ default:
+ output_addr_const (file, addr);
+ break;
+ }
+}
+
+
+/* Return appropriate code to load up a 1, 2, or 4 integer/floating
+ point value. */
+
+char *
+output_move_single (operands)
+ rtx *operands;
+{
+ rtx dst = operands[0];
+ rtx src = operands[1];
+
+ if (REG_P (dst))
+ {
+ if (REG_P (src))
+ return "mov %1,%0";
+
+ else if (GET_CODE (src) == CONST_INT)
+ {
+ 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";
+ }
+
+ else if (GET_CODE (src) == CONST_DOUBLE && GET_MODE (src) == SFmode)
+ {
+ 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";
+ }
+
+ else if (GET_CODE (src) == MEM)
+ return "%S1ld%W1 %1,%0";
+
+ else if (special_symbolref_operand (src, VOIDmode))
+ return "movea %O1(%P1),%Q1,%0";
+
+ else if (GET_CODE (src) == LABEL_REF
+ || GET_CODE (src) == SYMBOL_REF
+ || GET_CODE (src) == CONST)
+ return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0";
+
+ else if (GET_CODE (src) == HIGH)
+ return "movhi hi(%1),%.,%0";
+
+ else if (GET_CODE (src) == LO_SUM)
+ {
+ operands[2] = XEXP (src, 0);
+ operands[3] = XEXP (src, 1);
+ return "movea lo(%3),%2,%0";
+ }
+ }
+
+ else if (GET_CODE (dst) == MEM)
+ {
+ if (REG_P (src))
+ return "%S0st%W0 %1,%0";
+
+ else if (GET_CODE (src) == CONST_INT && INTVAL (src) == 0)
+ return "%S0st%W0 %.,%0";
+
+ else if (GET_CODE (src) == CONST_DOUBLE
+ && CONST0_RTX (GET_MODE (dst)) == src)
+ return "%S0st%W0 %.,%0";
+ }
+
+ fatal_insn ("output_move_single:", gen_rtx (SET, VOIDmode, dst, src));
+ return "";
+}
+
+
+/* Return appropriate code to load up an 8 byte integer or floating point value */
+
+char *
+output_move_double (operands)
+ rtx *operands;
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ rtx dst = operands[0];
+ rtx src = operands[1];
+
+ if (register_operand (dst, mode)
+ && register_operand (src, mode))
+ {
+ if (REGNO (src) + 1 == REGNO (dst))
+ return "mov %R1,%R0\n\tmov %1,%0";
+ else
+ return "mov %1,%0\n\tmov %R1,%R0";
+ }
+
+ /* Storing 0 */
+ if (GET_CODE (dst) == MEM
+ && ((GET_CODE (src) == CONST_INT && INTVAL (src) == 0)
+ || (GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src))))
+ return "st.w %.,%0\n\tst.w %.,%R0";
+
+ if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
+ {
+ HOST_WIDE_INT high_low[2];
+ int i;
+ rtx xop[10];
+
+ if (GET_CODE (src) == CONST_DOUBLE)
+ const_double_split (src, &high_low[1], &high_low[0]);
+ else
+ {
+ high_low[0] = INTVAL (src);
+ high_low[1] = (INTVAL (src) >= 0) ? 0 : -1;
+ }
+
+ for (i = 0; i < 2; i++)
+ {
+ xop[0] = gen_rtx (REG, SImode, REGNO (dst)+i);
+ xop[1] = GEN_INT (high_low[i]);
+ output_asm_insn (output_move_single (xop), xop);
+ }
+
+ return "";
+ }
+
+ if (GET_CODE (src) == MEM)
+ {
+ int ptrreg = -1;
+ int dreg = REGNO (dst);
+ rtx inside = XEXP (src, 0);
+
+ if (GET_CODE (inside) == REG)
+ ptrreg = REGNO (inside);
+ else if (GET_CODE (inside) == SUBREG)
+ ptrreg = REGNO (SUBREG_REG (inside)) + SUBREG_WORD (inside);
+ else if (GET_CODE (inside) == PLUS)
+ ptrreg = REGNO (XEXP (inside, 0));
+ else if (GET_CODE (inside) == LO_SUM)
+ ptrreg = REGNO (XEXP (inside, 0));
+
+ if (dreg == ptrreg)
+ return "ld.w %R1,%R0\n\tld.w %1,%0";
+ }
+
+ if (GET_CODE (src) == MEM)
+ return "ld.w %1,%0\n\tld.w %R1,%R0";
+
+ if (GET_CODE (dst) == MEM)
+ return "st.w %1,%0\n\tst.w %R1,%R0";
+
+ return "mov %1,%0\n\tmov %R1,%R0";
+}
+
+
+/* Return true if OP is a valid short EP memory reference */
+
+int
+ep_memory_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ rtx addr, op0, op1;
+ int max_offset;
+ int mask;
+
+ if (GET_CODE (op) != MEM)
+ return FALSE;
+
+ switch (GET_MODE (op))
+ {
+ default:
+ return FALSE;
+
+ case QImode:
+ max_offset = 128;
+ mask = 0;
+ break;
+
+ case HImode:
+ max_offset = 256;
+ mask = 1;
+ break;
+
+ case SImode:
+ case SFmode:
+ max_offset = 256;
+ mask = 3;
+ break;
+ }
+
+ addr = XEXP (op, 0);
+ if (GET_CODE (addr) == CONST)
+ addr = XEXP (addr, 0);
+
+ switch (GET_CODE (addr))
+ {
+ default:
+ break;
+
+ case SYMBOL_REF:
+ return TDA_NAME_P (XSTR (addr, 0));
+
+ case REG:
+ return REGNO (addr) == EP_REGNUM;
+
+ case PLUS:
+ op0 = XEXP (addr, 0);
+ op1 = XEXP (addr, 1);
+ if (GET_CODE (op1) == CONST_INT
+ && INTVAL (op1) < max_offset
+ && (INTVAL (op1) & mask) == 0)
+ {
+ if (GET_CODE (op0) == REG && REGNO (op0) == EP_REGNUM)
+ return TRUE;
+
+ if (GET_CODE (op0) == SYMBOL_REF && TDA_NAME_P (XSTR (op0, 0)))
+ return TRUE;
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/* Return true if OP is either a register or 0 */
+
+int
+reg_or_0_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) == CONST_INT)
+ return INTVAL (op) == 0;
+
+ 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;
+}
+
+/* Return true if OP is either a register or a signed five bit integer */
+
+int
+reg_or_int5_operand (op, mode)
+ rtx op;
+ enum machine_mode 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;
+}
+
+/* Return true if OP is a valid call operand. */
+
+int
+call_address_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ /* Only registers are valid call operands if TARGET_LONG_CALLS. */
+ if (TARGET_LONG_CALLS)
+ return GET_CODE (op) == REG;
+ return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);
+}
+
+int
+special_symbolref_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) == SYMBOL_REF)
+ return ENCODED_NAME_P (XSTR (op, 0));
+
+ else if (GET_CODE (op) == CONST)
+ return (GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
+ && ENCODED_NAME_P (XSTR (XEXP (XEXP (op, 0), 0), 0))
+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
+ && CONST_OK_FOR_K (INTVAL (XEXP (XEXP (op, 0), 1))));
+
+ return FALSE;
+}
+
+int
+movsi_source_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ /* Some constants, as well as symbolic operands
+ must be done with HIGH & LO_SUM patterns. */
+ if (CONSTANT_P (op)
+ && GET_CODE (op) != HIGH
+ && !(GET_CODE (op) == CONST_INT
+ && (CONST_OK_FOR_J (INTVAL (op))
+ || CONST_OK_FOR_K (INTVAL (op))
+ || CONST_OK_FOR_L (INTVAL (op)))))
+ return special_symbolref_operand (op, mode);
+ else
+ return general_operand (op, mode);
+}
+
+int
+power_of_two_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+
+ if (exact_log2 (INTVAL (op)) == -1)
+ return 0;
+ return 1;
+}
+
+int
+not_power_of_two_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ unsigned int mask;
+
+ if (mode == QImode)
+ mask = 0xff;
+ else if (mode == HImode)
+ mask = 0xffff;
+ else if (mode == SImode)
+ mask = 0xffffffff;
+ else
+ return 0;
+
+ if (GET_CODE (op) != CONST_INT)
+ return 0;
+
+ if (exact_log2 (~INTVAL (op) & mask) == -1)
+ return 0;
+ return 1;
+}
+
+
+/* Substitute memory references involving a pointer, to use the ep pointer,
+ taking care to save and preserve the ep. */
+
+static void
+substitute_ep_register (first_insn, last_insn, uses, regno, p_r1, p_ep)
+ rtx first_insn;
+ rtx last_insn;
+ int uses;
+ int regno;
+ rtx *p_r1;
+ rtx *p_ep;
+{
+ rtx reg = gen_rtx (REG, Pmode, regno);
+ rtx insn;
+ int i;
+
+ if (!*p_r1)
+ {
+ regs_ever_live[1] = 1;
+ *p_r1 = gen_rtx (REG, Pmode, 1);
+ *p_ep = gen_rtx (REG, Pmode, 30);
+ }
+
+ if (TARGET_DEBUG)
+ fprintf (stderr, "Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d\n",
+ 2 * (uses - 3), uses, reg_names[regno],
+ IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),
+ INSN_UID (first_insn), INSN_UID (last_insn));
+
+ if (GET_CODE (first_insn) == NOTE)
+ first_insn = next_nonnote_insn (first_insn);
+
+ last_insn = next_nonnote_insn (last_insn);
+ for (insn = first_insn; insn && insn != last_insn; insn = NEXT_INSN (insn))
+ {
+ if (GET_CODE (insn) == INSN)
+ {
+ rtx pattern = single_set (insn);
+
+ /* Replace the memory references. */
+ if (pattern)
+ {
+ rtx *p_mem;
+
+ if (GET_CODE (SET_DEST (pattern)) == MEM
+ && GET_CODE (SET_SRC (pattern)) == MEM)
+ p_mem = (rtx *)0;
+
+ else if (GET_CODE (SET_DEST (pattern)) == MEM)
+ p_mem = &SET_DEST (pattern);
+
+ else if (GET_CODE (SET_SRC (pattern)) == MEM)
+ p_mem = &SET_SRC (pattern);
+
+ else
+ p_mem = (rtx *)0;
+
+ if (p_mem)
+ {
+ rtx addr = XEXP (*p_mem, 0);
+
+ if (GET_CODE (addr) == REG && REGNO (addr) == regno)
+ *p_mem = change_address (*p_mem, VOIDmode, *p_ep);
+
+ else if (GET_CODE (addr) == PLUS
+ && 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))
+ *p_mem = change_address (*p_mem, VOIDmode,
+ gen_rtx (PLUS, Pmode,
+ *p_ep, XEXP (addr, 1)));
+ }
+ }
+ }
+ }
+
+ /* Optimize back to back cases of ep <- r1 & r1 <- ep. */
+ insn = prev_nonnote_insn (first_insn);
+ if (insn && GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == SET
+ && SET_DEST (PATTERN (insn)) == *p_ep
+ && SET_SRC (PATTERN (insn)) == *p_r1)
+ delete_insn (insn);
+ else
+ emit_insn_before (gen_rtx (SET, Pmode, *p_r1, *p_ep), first_insn);
+
+ emit_insn_before (gen_rtx (SET, Pmode, *p_ep, reg), first_insn);
+ emit_insn_before (gen_rtx (SET, Pmode, *p_ep, *p_r1), last_insn);
+}
+
+
+/* In rare cases, correct code generation requires extra machine
+ dependent processing between the second jump optimization pass and
+ delayed branch scheduling. On those machines, define this macro
+ as a C statement to act on the code starting at INSN.
+
+ On the 850, we use it to implement the -mep mode to copy heavily used
+ pointers to ep to use the implicit addressing */
+
+void v850_reorg (start_insn)
+ rtx start_insn;
+{
+ struct {
+ int uses;
+ rtx first_insn;
+ rtx last_insn;
+ } regs[FIRST_PSEUDO_REGISTER];
+
+ int i;
+ int use_ep = FALSE;
+ rtx r1 = NULL_RTX;
+ rtx ep = NULL_RTX;
+ rtx insn;
+ rtx pattern;
+
+ /* If not ep mode, just return now */
+ if (!TARGET_EP)
+ return;
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ regs[i].uses = 0;
+ regs[i].first_insn = NULL_RTX;
+ regs[i].last_insn = NULL_RTX;
+ }
+
+ for (insn = start_insn; insn != NULL_RTX; insn = NEXT_INSN (insn))
+ {
+ switch (GET_CODE (insn))
+ {
+ /* End of basic block */
+ default:
+ if (!use_ep)
+ {
+ int max_uses = -1;
+ int max_regno = -1;
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ if (max_uses < regs[i].uses)
+ {
+ max_uses = regs[i].uses;
+ max_regno = i;
+ }
+ }
+
+ if (max_uses > 3)
+ substitute_ep_register (regs[max_regno].first_insn,
+ regs[max_regno].last_insn,
+ max_uses, max_regno, &r1, &ep);
+ }
+
+ use_ep = FALSE;
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ regs[i].uses = 0;
+ regs[i].first_insn = NULL_RTX;
+ regs[i].last_insn = NULL_RTX;
+ }
+ break;
+
+ case NOTE:
+ break;
+
+ case INSN:
+ pattern = single_set (insn);
+
+ /* See if there are any memory references we can shorten */
+ if (pattern)
+ {
+ rtx src = SET_SRC (pattern);
+ rtx dest = SET_DEST (pattern);
+ rtx mem;
+
+ if (GET_CODE (dest) == MEM && GET_CODE (src) == MEM)
+ mem = NULL_RTX;
+
+ else if (GET_CODE (dest) == MEM)
+ mem = dest;
+
+ else if (GET_CODE (src) == MEM)
+ mem = src;
+
+ else
+ mem = NULL_RTX;
+
+ if (mem && ep_memory_operand (mem, GET_MODE (mem)))
+ use_ep = TRUE;
+
+ else if (!use_ep && mem
+ && GET_MODE_SIZE (GET_MODE (mem)) <= UNITS_PER_WORD)
+ {
+ rtx addr = XEXP (mem, 0);
+ int regno = -1;
+ int short_p;
+
+ if (GET_CODE (addr) == REG)
+ {
+ short_p = TRUE;
+ regno = REGNO (addr);
+ }
+
+ 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))
+ {
+ short_p = TRUE;
+ regno = REGNO (XEXP (addr, 0));
+ }
+
+ else
+ short_p = FALSE;
+
+ if (short_p)
+ {
+ regs[regno].uses++;
+ regs[regno].last_insn = insn;
+ if (!regs[regno].first_insn)
+ regs[regno].first_insn = insn;
+ }
+ }
+
+ /* Loading up a register in the basic block zaps any savings
+ for the register */
+ if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG)
+ {
+ enum machine_mode mode = GET_MODE (dest);
+ int word = 0;
+ int regno;
+ int endregno;
+
+ while (GET_CODE (dest) == SUBREG)
+ {
+ word = SUBREG_WORD (dest);
+ dest = SUBREG_REG (dest);
+ }
+
+ regno = REGNO (dest) + word;
+ endregno = regno + HARD_REGNO_NREGS (regno, mode);
+
+ if (!use_ep)
+ {
+ /* See if we can use the pointer before this
+ modification. */
+ int max_uses = -1;
+ int max_regno = -1;
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ if (max_uses < regs[i].uses)
+ {
+ max_uses = regs[i].uses;
+ max_regno = i;
+ }
+ }
+
+ if (max_uses > 3
+ && max_regno >= regno
+ && max_regno < endregno)
+ {
+ substitute_ep_register (regs[max_regno].first_insn,
+ regs[max_regno].last_insn,
+ max_uses, max_regno, &r1, &ep);
+
+ /* Since we made a substitution, zap all remembered
+ registers. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ regs[i].uses = 0;
+ regs[i].first_insn = NULL_RTX;
+ regs[i].last_insn = NULL_RTX;
+ }
+ }
+ }
+
+ for (i = regno; i < endregno; i++)
+ {
+ regs[i].uses = 0;
+ regs[i].first_insn = NULL_RTX;
+ regs[i].last_insn = NULL_RTX;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/* # of registers saved by the interrupt handler. */
+#define INTERRUPT_FIXED_NUM 4
+
+/* # of bytes for registers saved by the interrupt handler. */
+#define INTERRUPT_FIXED_SAVE_SIZE (4 * INTERRUPT_FIXED_NUM)
+
+/* # of registers saved in register parameter area. */
+#define INTERRUPT_REGPARM_NUM 4
+/* # of words saved for other registers. */
+#define INTERRUPT_ALL_SAVE_NUM \
+ (30 - INTERRUPT_FIXED_NUM + INTERRUPT_REGPARM_NUM)
+
+#define INTERRUPT_ALL_SAVE_SIZE (4 * INTERRUPT_ALL_SAVE_NUM)
+
+int
+compute_register_save_size (p_reg_saved)
+ long *p_reg_saved;
+{
+ int size = 0;
+ int i;
+ int interrupt_handler = v850_interrupt_function_p (current_function_decl);
+ int call_p = regs_ever_live[31];
+ long reg_saved = 0;
+
+ /* Count the return pointer if we need to save it. */
+ if (profile_flag && !call_p)
+ regs_ever_live[31] = call_p = 1;
+
+ /* Count space for the register saves. */
+ if (interrupt_handler)
+ {
+ for (i = 0; i <= 31; i++)
+ switch (i)
+ {
+ default:
+ if (regs_ever_live[i] || call_p)
+ {
+ size += 4;
+ reg_saved |= 1L << i;
+ }
+ break;
+
+ /* We don't save/restore r0 or the stack pointer */
+ case 0:
+ case STACK_POINTER_REGNUM:
+ break;
+
+ /* For registers with fixed use, we save them, set them to the
+ appropriate value, and then restore them.
+ These registers are handled specially, so don't list them
+ on the list of registers to save in the prologue. */
+ case 1: /* temp used to hold ep */
+ case 5: /* gp */
+ case 10: /* temp used to call interrupt save/restore */
+ case EP_REGNUM: /* ep */
+ size += 4;
+ break;
+ }
+ }
+
+ else
+ for (i = 0; i <= 31; i++)
+ if (regs_ever_live[i] && ((! call_used_regs[i]) || i == 31))
+ {
+ size += 4;
+ reg_saved |= 1L << i;
+ }
+
+ if (p_reg_saved)
+ *p_reg_saved = reg_saved;
+
+ return size;
+}
+
+int
+compute_frame_size (size, p_reg_saved)
+ int size;
+ long *p_reg_saved;
+{
+ extern int current_function_outgoing_args_size;
+
+ return (size
+ + compute_register_save_size (p_reg_saved)
+ + current_function_outgoing_args_size);
+}
+
+
+void
+expand_prologue ()
+{
+ unsigned int i;
+ int offset;
+ unsigned int size = get_frame_size ();
+ unsigned int actual_fsize;
+ unsigned int init_stack_alloc = 0;
+ rtx save_regs[32];
+ rtx save_all;
+ int num_save;
+ int default_stack;
+ int code;
+ int interrupt_handler = v850_interrupt_function_p (current_function_decl);
+ long reg_saved = 0;
+
+ actual_fsize = compute_frame_size (size, &reg_saved);
+
+ /* Save/setup global registers for interrupt functions right now */
+ if (interrupt_handler)
+ {
+ emit_insn (gen_save_interrupt ());
+ actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE;
+ if (((1L << 31) & reg_saved) != 0)
+ actual_fsize -= INTERRUPT_ALL_SAVE_SIZE;
+ }
+
+ /* Save arg registers to the stack if necessary. */
+ else if (current_function_anonymous_args)
+ {
+ if (TARGET_PROLOG_FUNCTION)
+ emit_insn (gen_save_r6_r9 ());
+ else
+ {
+ offset = 0;
+ for (i = 6; i < 10; i++)
+ {
+ emit_move_insn (gen_rtx (MEM, SImode,
+ plus_constant (stack_pointer_rtx,
+ offset)),
+ gen_rtx (REG, SImode, i));
+ offset += 4;
+ }
+ }
+ }
+
+ /* Identify all of the saved registers */
+ num_save = 0;
+ default_stack = 0;
+ for (i = 1; i < 31; i++)
+ {
+ if (((1L << i) & reg_saved) != 0)
+ save_regs[num_save++] = gen_rtx (REG, Pmode, i);
+ }
+
+ /* If the return pointer is saved, the helper functions also allocate
+ 16 bytes of stack for arguments to be saved in. */
+ if (((1L << 31) & reg_saved) != 0)
+ {
+ save_regs[num_save++] = gen_rtx (REG, Pmode, 31);
+ default_stack = 16;
+ }
+
+ /* See if we have an insn that allocates stack space and saves the particular
+ registers we want to. */
+ save_all = NULL_RTX;
+ if (TARGET_PROLOG_FUNCTION && num_save > 0 && actual_fsize >= default_stack)
+ {
+ int alloc_stack = (4 * num_save) + default_stack;
+ int unalloc_stack = actual_fsize - alloc_stack;
+ int save_func_len = 4;
+ int save_normal_len;
+
+ if (unalloc_stack)
+ save_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4;
+
+ /* see if we would have used ep to save the stack */
+ if (TARGET_EP && num_save > 3 && (unsigned)actual_fsize < 255)
+ save_normal_len = (3 * 2) + (2 * num_save);
+ else
+ save_normal_len = 4 * num_save;
+
+ save_normal_len += CONST_OK_FOR_J (actual_fsize) ? 2 : 4;
+
+ /* Don't bother checking if we don't actually save any space.
+ This happens for instance if one register is saved and additional
+ stack space is allocated. */
+ if (save_func_len < save_normal_len)
+ {
+ save_all = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (num_save + 2));
+ XVECEXP (save_all, 0, 0) = gen_rtx (SET, VOIDmode,
+ stack_pointer_rtx,
+ gen_rtx (PLUS, Pmode,
+ stack_pointer_rtx,
+ GEN_INT (-alloc_stack)));
+
+ XVECEXP (save_all, 0, num_save+1)
+ = gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, Pmode, 10));
+
+ offset = - default_stack;
+ for (i = 0; i < num_save; i++)
+ {
+ XVECEXP (save_all, 0, i+1)
+ = gen_rtx (SET, VOIDmode,
+ gen_rtx (MEM, Pmode,
+ plus_constant (stack_pointer_rtx, offset)),
+ save_regs[i]);
+ offset -= 4;
+ }
+
+ code = recog (save_all, NULL_RTX, NULL_PTR);
+ if (code >= 0)
+ {
+ rtx insn = emit_insn (save_all);
+ INSN_CODE (insn) = code;
+ actual_fsize -= alloc_stack;
+
+ if (TARGET_DEBUG)
+ fprintf (stderr, "Saved %d bytes via prologue function (%d vs. %d) for function %s\n",
+ save_normal_len - save_func_len,
+ save_normal_len, save_func_len,
+ IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
+ }
+ else
+ save_all = NULL_RTX;
+ }
+ }
+
+ /* If no prolog save function is available, store the registers the old fashioned
+ way (one by one). */
+ if (!save_all)
+ {
+ /* Special case interrupt functions that save all registers for a call. */
+ if (interrupt_handler && ((1L << 31) & reg_saved) != 0)
+ emit_insn (gen_save_all_interrupt ());
+
+ else
+ {
+ /* If the stack is too big, allocate it in chunks so we can do the
+ register saves. We use the register save size so we use the ep
+ register. */
+ if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize))
+ init_stack_alloc = compute_register_save_size (NULL);
+ else
+ init_stack_alloc = actual_fsize;
+
+ /* Save registers at the beginning of the stack frame */
+ offset = init_stack_alloc - 4;
+
+ if (init_stack_alloc)
+ emit_insn (gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (-init_stack_alloc)));
+
+ /* Save the return pointer first. */
+ if (num_save > 0 && REGNO (save_regs[num_save-1]) == 31)
+ {
+ emit_move_insn (gen_rtx (MEM, SImode,
+ plus_constant (stack_pointer_rtx,
+ offset)),
+ save_regs[--num_save]);
+ offset -= 4;
+ }
+
+ for (i = 0; i < num_save; i++)
+ {
+ emit_move_insn (gen_rtx (MEM, SImode,
+ plus_constant (stack_pointer_rtx,
+ offset)),
+ save_regs[i]);
+ offset -= 4;
+ }
+ }
+ }
+
+ /* Allocate the rest of the stack that was not allocated above (either it is
+ > 32K or we just called a function to save the registers and needed more
+ stack. */
+ if (actual_fsize > init_stack_alloc)
+ {
+ int diff = actual_fsize - init_stack_alloc;
+ if (CONST_OK_FOR_K (diff))
+ emit_insn (gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (-diff)));
+ else
+ {
+ rtx reg = gen_rtx (REG, Pmode, 12);
+ emit_move_insn (reg, GEN_INT (-diff));
+ emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
+ }
+ }
+
+ /* If we need a frame pointer, set it up now. */
+ if (frame_pointer_needed)
+ emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+}
+
+
+void
+expand_epilogue ()
+{
+ unsigned int i;
+ int offset;
+ unsigned int size = get_frame_size ();
+ long reg_saved = 0;
+ unsigned int actual_fsize = compute_frame_size (size, &reg_saved);
+ unsigned int init_stack_free = 0;
+ rtx restore_regs[32];
+ rtx restore_all;
+ int num_restore;
+ int default_stack;
+ int code;
+ int interrupt_handler = v850_interrupt_function_p (current_function_decl);
+
+ /* Eliminate the initial stack stored by interrupt functions. */
+ if (interrupt_handler)
+ {
+ actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE;
+ if (((1L << 31) & reg_saved) != 0)
+ actual_fsize -= INTERRUPT_ALL_SAVE_SIZE;
+ }
+
+ /* Cut off any dynamic stack created. */
+ if (frame_pointer_needed)
+ emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
+
+ /* Identify all of the saved registers */
+ num_restore = 0;
+ default_stack = 0;
+ for (i = 1; i < 31; i++)
+ {
+ if (((1L << i) & reg_saved) != 0)
+ restore_regs[num_restore++] = gen_rtx (REG, Pmode, i);
+ }
+
+ /* If the return pointer is saved, the helper functions also allocate
+ 16 bytes of stack for arguments to be saved in. */
+ if (((1L << 31) & reg_saved) != 0)
+ {
+ restore_regs[num_restore++] = gen_rtx (REG, Pmode, 31);
+ default_stack = 16;
+ }
+
+ /* See if we have an insn that restores the particular registers we
+ want to. */
+ restore_all = NULL_RTX;
+ if (TARGET_PROLOG_FUNCTION && num_restore > 0 && actual_fsize >= default_stack
+ && !interrupt_handler)
+ {
+ int alloc_stack = (4 * num_restore) + default_stack;
+ int unalloc_stack = actual_fsize - alloc_stack;
+ int restore_func_len = 4;
+ int restore_normal_len;
+
+ if (unalloc_stack)
+ restore_func_len += CONST_OK_FOR_J (unalloc_stack) ? 2 : 4;
+
+ /* see if we would have used ep to restore the registers */
+ if (TARGET_EP && num_restore > 3 && (unsigned)actual_fsize < 255)
+ restore_normal_len = (3 * 2) + (2 * num_restore);
+ else
+ restore_normal_len = 4 * num_restore;
+
+ restore_normal_len += (CONST_OK_FOR_J (actual_fsize) ? 2 : 4) + 2;
+
+ /* Don't bother checking if we don't actually save any space. */
+ if (restore_func_len < restore_normal_len)
+ {
+ restore_all = gen_rtx (PARALLEL, VOIDmode,
+ rtvec_alloc (num_restore + 2));
+ XVECEXP (restore_all, 0, 0) = gen_rtx (RETURN, VOIDmode);
+ XVECEXP (restore_all, 0, 1)
+ = gen_rtx (SET, VOIDmode, stack_pointer_rtx,
+ gen_rtx (PLUS, Pmode,
+ stack_pointer_rtx,
+ GEN_INT (alloc_stack)));
+
+ offset = alloc_stack - 4;
+ for (i = 0; i < num_restore; i++)
+ {
+ XVECEXP (restore_all, 0, i+2)
+ = gen_rtx (SET, VOIDmode,
+ restore_regs[i],
+ gen_rtx (MEM, Pmode,
+ plus_constant (stack_pointer_rtx, offset)));
+ offset -= 4;
+ }
+
+ code = recog (restore_all, NULL_RTX, NULL_PTR);
+ if (code >= 0)
+ {
+ rtx insn;
+
+ actual_fsize -= alloc_stack;
+ if (actual_fsize)
+ {
+ if (CONST_OK_FOR_K (actual_fsize))
+ emit_insn (gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (actual_fsize)));
+ else
+ {
+ rtx reg = gen_rtx (REG, Pmode, 12);
+ emit_move_insn (reg, GEN_INT (actual_fsize));
+ emit_insn (gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ reg));
+ }
+ }
+
+ insn = emit_jump_insn (restore_all);
+ INSN_CODE (insn) = code;
+
+ if (TARGET_DEBUG)
+ fprintf (stderr, "Saved %d bytes via epilogue function (%d vs. %d) in function %s\n",
+ restore_normal_len - restore_func_len,
+ restore_normal_len, restore_func_len,
+ IDENTIFIER_POINTER (DECL_NAME (current_function_decl)));
+ }
+ else
+ restore_all = NULL_RTX;
+ }
+ }
+
+ /* If no epilog save function is available, restore the registers the
+ old fashioned way (one by one). */
+ if (!restore_all)
+ {
+ /* If the stack is large, we need to cut it down in 2 pieces. */
+ if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize))
+ init_stack_free = 4 * num_restore;
+ else
+ init_stack_free = actual_fsize;
+
+ /* Deallocate the rest of the stack if it is > 32K or if extra stack
+ was allocated for an interrupt handler that makes a call. */
+ if (actual_fsize > init_stack_free || (interrupt_handler && actual_fsize))
+ {
+ int diff = actual_fsize - ((interrupt_handler) ? 0 : init_stack_free);
+ if (CONST_OK_FOR_K (diff))
+ emit_insn (gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (diff)));
+ else
+ {
+ rtx reg = gen_rtx (REG, Pmode, 12);
+ emit_move_insn (reg, GEN_INT (diff));
+ emit_insn (gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ reg));
+ }
+ }
+
+ /* Special case interrupt functions that save all registers
+ for a call. */
+ if (interrupt_handler && ((1L << 31) & reg_saved) != 0)
+ emit_insn (gen_restore_all_interrupt ());
+ else
+ {
+ /* Restore registers from the beginning of the stack frame */
+ offset = init_stack_free - 4;
+
+ /* Restore the return pointer first. */
+ if (num_restore > 0 && REGNO (restore_regs[num_restore-1]) == 31)
+ {
+ emit_move_insn (restore_regs[--num_restore],
+ gen_rtx (MEM, SImode,
+ plus_constant (stack_pointer_rtx,
+ offset)));
+ offset -= 4;
+ }
+
+ for (i = 0; i < num_restore; i++)
+ {
+ emit_move_insn (restore_regs[i],
+ gen_rtx (MEM, SImode,
+ plus_constant (stack_pointer_rtx,
+ offset)));
+
+ offset -= 4;
+ }
+
+ /* Cut back the remainder of the stack. */
+ if (init_stack_free)
+ emit_insn (gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (init_stack_free)));
+ }
+
+ /* 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
+ emit_jump_insn (gen_return ());
+ }
+
+ current_function_anonymous_args = 0;
+ v850_interrupt_cache_p = FALSE;
+ v850_interrupt_p = FALSE;
+}
+
+
+/* Update the condition code from the insn. */
+
+void
+notice_update_cc (body, insn)
+ rtx body;
+ rtx insn;
+{
+ switch (get_attr_cc (insn))
+ {
+ case CC_NONE:
+ /* Insn does not affect CC at all. */
+ break;
+
+ case CC_NONE_0HIT:
+ /* Insn does not change CC, but the 0'th operand has been changed. */
+ if (cc_status.value1 != 0
+ && reg_overlap_mentioned_p (recog_operand[0], cc_status.value1))
+ cc_status.value1 = 0;
+ break;
+
+ case CC_SET_ZN:
+ /* Insn sets the Z,N flags of CC to recog_operand[0].
+ V,C is in an unusable state. */
+ CC_STATUS_INIT;
+ cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
+ cc_status.value1 = recog_operand[0];
+ break;
+
+ case CC_SET_ZNV:
+ /* Insn sets the Z,N,V flags of CC to recog_operand[0].
+ C is in an unusable state. */
+ CC_STATUS_INIT;
+ cc_status.flags |= CC_NO_CARRY;
+ cc_status.value1 = recog_operand[0];
+ break;
+
+ case CC_COMPARE:
+ /* The insn is a compare instruction. */
+ CC_STATUS_INIT;
+ cc_status.value1 = SET_SRC (body);
+ break;
+
+ case CC_CLOBBER:
+ /* Insn doesn't leave CC in a usable state. */
+ CC_STATUS_INIT;
+ break;
+ }
+}
+
+
+/* Return nonzero if ATTR is a valid attribute for DECL.
+ ATTRIBUTES are any existing attributes and ARGS are the arguments
+ supplied with ATTR.
+
+ Supported attributes:
+
+ interrupt_handler or interrupt: output a prologue and epilogue suitable
+ for an interrupt handler. */
+
+int
+v850_valid_machine_decl_attribute (decl, attributes, attr, args)
+ tree decl;
+ tree attributes;
+ tree attr;
+ tree args;
+{
+ if (args != NULL_TREE)
+ return 0;
+
+ if (is_attribute_p ("interrupt_handler", attr)
+ || is_attribute_p ("interrupt", attr))
+ return TREE_CODE (decl) == FUNCTION_DECL;
+
+ return 0;
+}
+
+
+/* Return nonzero if FUNC is an interrupt function as specified
+ by the "interrupt" attribute. */
+
+int
+v850_interrupt_function_p (func)
+ tree func;
+{
+ tree a;
+ int ret = 0;
+
+ if (v850_interrupt_cache_p)
+ return v850_interrupt_p;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return 0;
+
+ a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func));
+ if (a != NULL_TREE)
+ ret = 1;
+
+ else
+ {
+ a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
+ ret = a != NULL_TREE;
+ }
+
+ /* Its not safe to trust global variables until after function inlining has
+ been done. */
+ if (reload_completed | reload_in_progress)
+ v850_interrupt_p = ret;
+
+ return ret;
+}
+
+
+extern struct obstack *saveable_obstack;
+
+v850_encode_data_area (decl)
+ tree decl;
+{
+ char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+ int len = strlen (str);
+ char *newstr;
+
+ /* In the Cygnus sources we actually do something; this is just
+ here to make merges easier. */
+ return;
+}
diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h
new file mode 100644
index 0000000..2a05aef
--- /dev/null
+++ b/gcc/config/v850/v850.h
@@ -0,0 +1,1406 @@
+/* CYGNUS LOCAL entire file/law */
+/* Definitions of target machine for GNU compiler.
+ NEC V850 series
+ Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+ Contributed by Jeff Law (law@cygnus.com).
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#include "svr4.h"
+
+#undef ASM_SPEC
+#undef ASM_FINAL_SPEC
+#undef LIB_SPEC
+#undef ENDFILE_SPEC
+#undef LINK_SPEC
+#undef STARTFILE_SPEC
+
+/* Names to predefine in the preprocessor for this target machine. */
+
+#define CPP_PREDEFINES "-D__v850__ -D__v851__ -D__v850"
+
+
+/* Run-time compilation parameters selecting different hardware subsets. */
+
+extern int target_flags;
+
+/* Target flags bits, see below for an explanation of the bits. */
+#define MASK_GHS 0x00000001
+#define MASK_LONG_CALLS 0x00000002
+#define MASK_EP 0x00000004
+#define MASK_PROLOG_FUNCTION 0x00000008
+#define MASK_DEBUG 0x40000000
+
+/* Macros used in the machine description to test the flags. */
+
+/* The GHS calling convention support doesn't really work,
+ mostly due to a lack of documentation. Outstanding issues:
+
+ * How do varargs & stdarg really work. How to they handle
+ passing structures (if at all).
+
+ * Doubles are normally 4 byte aligned, except in argument
+ lists where they are 8 byte aligned. Is the alignment
+ in the argument list based on the first parameter,
+ first stack parameter, etc etc.
+
+ * Passing/returning of large structures probably isn't the same
+ as GHS. We don't have enough documentation on their conventions
+ to be compatable.
+
+ * Tests of SETUP_INCOMING_VARARGS need to be made runtime checks
+ since it depends on TARGET_GHS. */
+#define TARGET_GHS (target_flags & MASK_GHS)
+
+/* Don't do PC-relative calls, instead load the address of the target
+ function into a register and perform a register indirect call. */
+#define TARGET_LONG_CALLS (target_flags & MASK_LONG_CALLS)
+
+/* Whether to optimize space by using ep (r30) for pointers with small offsets
+ in basic blocks. */
+#define TARGET_EP (target_flags & MASK_EP)
+
+/* Whether to call out-of-line functions to save registers or not. */
+#define TARGET_PROLOG_FUNCTION (target_flags & MASK_PROLOG_FUNCTION)
+
+/* 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,
+ each pair being { "NAME", VALUE }
+ where VALUE is the bits to set or minus the bits to clear.
+ An empty string NAME is used to identify the default VALUE. */
+
+#define TARGET_SWITCHES \
+ {{ "ghs", MASK_GHS }, \
+ { "no-ghs", -MASK_GHS }, \
+ { "long-calls", MASK_LONG_CALLS }, \
+ { "no-long-calls", -MASK_LONG_CALLS }, \
+ { "ep", MASK_EP }, \
+ { "no-ep", -MASK_EP }, \
+ { "prolog-function", MASK_PROLOG_FUNCTION }, \
+ { "no-prolog-function", -MASK_PROLOG_FUNCTION }, \
+ { "space", MASK_EP | MASK_PROLOG_FUNCTION }, \
+ { "debug", MASK_DEBUG }, \
+ { "", TARGET_DEFAULT}}
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT 0
+#endif
+
+/* Information about the various small memory areas. */
+struct small_memory_info {
+ char *name;
+ char *value;
+ long max;
+ long physical_max;
+};
+
+enum small_memory_type {
+ /* tiny data area, using EP as base register */
+ SMALL_MEMORY_TDA = 0,
+ /* small data area using dp as base register */
+ SMALL_MEMORY_SDA,
+ /* zero data area using r0 as base register */
+ SMALL_MEMORY_ZDA,
+ SMALL_MEMORY_max
+};
+
+extern struct small_memory_info small_memory[(int)SMALL_MEMORY_max];
+
+/* This macro is similar to `TARGET_SWITCHES' but defines names of
+ command options that have values. Its definition is an
+ initializer with a subgrouping for each command option.
+
+ Each subgrouping contains a string constant, that defines the
+ fixed part of the option name, and the address of a variable. The
+ variable, type `char *', is set to the variable part of the given
+ option if the fixed part matches. The actual option name is made
+ by appending `-m' to the specified name.
+
+ Here is an example which defines `-mshort-data-NUMBER'. If the
+ given option is `-mshort-data-512', the variable `m88k_short_data'
+ will be set to the string `"512"'.
+
+ extern char *m88k_short_data;
+ #define TARGET_OPTIONS \
+ { { "short-data-", &m88k_short_data } } */
+
+#define TARGET_OPTIONS \
+{ \
+ { "tda=", &small_memory[ (int)SMALL_MEMORY_TDA ].value }, \
+ { "tda-", &small_memory[ (int)SMALL_MEMORY_TDA ].value }, \
+ { "sda=", &small_memory[ (int)SMALL_MEMORY_SDA ].value }, \
+ { "sda-", &small_memory[ (int)SMALL_MEMORY_SDA ].value }, \
+ { "zda=", &small_memory[ (int)SMALL_MEMORY_ZDA ].value }, \
+ { "zda-", &small_memory[ (int)SMALL_MEMORY_ZDA ].value }, \
+}
+
+/* Print subsidiary information on the compiler version in use. */
+
+#define TARGET_VERSION fprintf (stderr, " (NEC V850)");
+
+/* Sometimes certain combinations of command options do not make
+ sense on a particular target machine. You can define a macro
+ `OVERRIDE_OPTIONS' to take account of this. This macro, if
+ defined, is executed once just after all the command options have
+ been parsed.
+
+ Don't use this macro to turn on various extra optimizations for
+ `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
+#define OVERRIDE_OPTIONS override_options ()
+
+
+/* Show we can debug even without a frame pointer. */
+#define CAN_DEBUG_WITHOUT_FP
+
+/* Some machines may desire to change what optimizations are
+ performed for various optimization levels. This macro, if
+ defined, is executed once just after the optimization level is
+ determined and before the remainder of the command options have
+ been parsed. Values set in this macro are used as the default
+ values for the other command line options.
+
+ LEVEL is the optimization level specified; 2 if `-O2' is
+ specified, 1 if `-O' is specified, and 0 if neither is specified.
+
+ You should not use this macro to change options that are not
+ machine-specific. These should uniformly selected by the same
+ optimization level on all supported machines. Use this macro to
+ enable machine-specific optimizations.
+
+ *Do not examine `write_symbols' in this macro!* The debugging
+ options are not supposed to alter the generated code. */
+
+#define OPTIMIZATION_OPTIONS(LEVEL) \
+{ \
+ if (LEVEL) \
+ target_flags |= (MASK_EP | MASK_PROLOG_FUNCTION); \
+}
+
+
+/* Target machine storage layout */
+
+/* Define this if most significant bit is lowest numbered
+ in instructions that operate on numbered bit-fields.
+ This is not true on the NEC V850. */
+#define BITS_BIG_ENDIAN 0
+
+/* Define this if most significant byte of a word is the lowest numbered. */
+/* This is not true on the NEC V850. */
+#define BYTES_BIG_ENDIAN 0
+
+/* Define this if most significant word of a multiword number is lowest
+ numbered.
+ This is not true on the NEC V850. */
+#define WORDS_BIG_ENDIAN 0
+
+/* Number of bits in an addressable storage unit */
+#define BITS_PER_UNIT 8
+
+/* Width in bits of a "word", which is the contents of a machine register.
+ Note that this is not necessarily the width of data type `int';
+ if using 16-bit ints on a 68000, this would still be 32.
+ But on a machine with 16-bit registers, this would be 16. */
+#define BITS_PER_WORD 32
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD 4
+
+/* Width in bits of a pointer.
+ See also the macro `Pmode' defined below. */
+#define POINTER_SIZE 32
+
+/* Define this macro if it is advisable to hold scalars in registers
+ in a wider mode than that declared by the program. In such cases,
+ the value is constrained to be within the bounds of the declared
+ type, but kept valid in the wider mode. The signedness of the
+ extension may differ from that of the type.
+
+ Some simple experiments have shown that leaving UNSIGNEDP alone
+ generates the best overall code. */
+
+#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \
+ if (GET_MODE_CLASS (MODE) == MODE_INT \
+ && GET_MODE_SIZE (MODE) < 4) \
+ { (MODE) = SImode; }
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY 32
+
+/* The stack goes in 32 bit lumps. */
+#define STACK_BOUNDARY 32
+
+/* Allocation boundary (in *bits*) for the code of a function.
+ 16 is the minimum boundary; 32 would give better performance. */
+#define FUNCTION_BOUNDARY 16
+
+/* No data type wants to be aligned rounder than this. */
+#define BIGGEST_ALIGNMENT 32
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* No structure field wants to be aligned rounder than this. */
+#define BIGGEST_FIELD_ALIGNMENT 32
+
+/* Define this if move instructions will actually fail to work
+ when given unaligned data. */
+#define STRICT_ALIGNMENT 1
+
+/* Define this as 1 if `char' should by default be signed; else as 0.
+
+ On the NEC V850, loads do sign extension, so make this default. */
+#define DEFAULT_SIGNED_CHAR 1
+
+/* Define results of standard character escape sequences. */
+#define TARGET_BELL 007
+#define TARGET_BS 010
+#define TARGET_TAB 011
+#define TARGET_NEWLINE 012
+#define TARGET_VT 013
+#define TARGET_FF 014
+#define TARGET_CR 015
+
+/* Standard register usage. */
+
+/* Number of actual hardware registers.
+ The hardware registers are assigned numbers for the compiler
+ from 0 to just below FIRST_PSEUDO_REGISTER.
+
+ All registers that the compiler knows about must be given numbers,
+ even those that are not normally considered general registers. */
+
+#define FIRST_PSEUDO_REGISTER 34
+
+/* 1 for registers that have pervasive standard uses
+ and are not available for the register allocator. */
+
+#define FIXED_REGISTERS \
+ { 1, 1, 0, 1, 1, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 1, 0, \
+ 1, 1}
+
+/* 1 for registers not available across function calls.
+ These must include the FIXED_REGISTERS and also any
+ registers that can be used without being saved.
+ The latter must include the registers where values are returned
+ and the register where structure-value addresses are passed.
+ Aside from that, you can include as many other registers as you
+ like. */
+
+#define CALL_USED_REGISTERS \
+ { 1, 1, 0, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 1, 1, \
+ 1, 1}
+
+/* List the order in which to allocate registers. Each register must be
+ listed once, even those in FIXED_REGISTERS.
+
+ On the 850, we make the return registers first, then all of the volatile
+ registers, then the saved registers in reverse order to better save the
+ registers with an out of line function , and finnally the fixed
+ registers. */
+
+#define REG_ALLOC_ORDER \
+{ \
+ 10, 11, /* return registers */ \
+ 12, 13, 14, 15, 16, 17, 18, 19, /* scratch registers */ \
+ 6, 7, 8, 9, 31, /* argument registers */ \
+ 29, 28, 27, 26, 25, 24, 23, 22, /* saved registers */ \
+ 21, 20, 2, \
+ 0, 1, 3, 4, 5, 30, 32, 33 /* fixed registers */ \
+}
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers. */
+
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode
+ MODE. */
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ ((((REGNO) & 1) == 0) || (GET_MODE_SIZE (MODE) <= 4))
+
+/* Value is 1 if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be 0 for correct output. */
+#define MODES_TIEABLE_P(MODE1, MODE2) \
+ (MODE1 == MODE2 || GET_MODE_SIZE (MODE1) <= 4 && GET_MODE_SIZE (MODE2) <= 4)
+
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+enum reg_class {
+ NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+/* Give names of register classes as strings for dump file. */
+
+#define REG_CLASS_NAMES \
+{ "NO_REGS", "GENERAL_REGS", "ALL_REGS", "LIM_REGS" }
+
+/* Define which registers fit in which classes.
+ This is an initializer for a vector of HARD_REG_SET
+ of length N_REG_CLASSES. */
+
+#define REG_CLASS_CONTENTS \
+{ 0x00000000, /* No regs */ \
+ 0xffffffff, /* GENERAL_REGS */ \
+ 0xffffffff, /* ALL_REGS */ \
+}
+
+/* The same information, inverted:
+ Return the class number of the smallest class containing
+ reg number REGNO. This could be a conditional expression
+ or could index an array. */
+
+#define REGNO_REG_CLASS(REGNO) GENERAL_REGS
+
+/* The class value for index registers, and the one for base regs. */
+
+#define INDEX_REG_CLASS NO_REGS
+#define BASE_REG_CLASS GENERAL_REGS
+
+/* Get reg_class from a letter such as appears in the machine description. */
+
+#define REG_CLASS_FROM_LETTER(C) (NO_REGS)
+
+/* Macros to check register numbers against specific register classes. */
+
+/* These assume that REGNO is a hard or pseudo reg number.
+ They give nonzero only if REGNO is a hard reg of the suitable class
+ or a pseudo reg currently allocated to a suitable hard reg.
+ Since they use reg_renumber, they are safe only once reg_renumber
+ has been allocated, which happens in local-alloc.c. */
+
+#define REGNO_OK_FOR_BASE_P(regno) \
+ ((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
+
+#define REGNO_OK_FOR_INDEX_P(regno) 0
+
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
+ In general this is just CLASS; but on some machines
+ in some cases it is preferable to use a more restrictive class. */
+
+#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+
+/* The letters I, J, K, L, M, N, O, P in a register constraint string
+ can be used to stand for particular ranges of immediate operands.
+ This macro defines what the ranges are.
+ C is the letter, and VALUE is a constant value.
+ Return 1 if VALUE is in the range specified by C. */
+
+#define INT_7_BITS(VALUE) ((unsigned) (VALUE) + 0x40 < 0x80)
+#define INT_8_BITS(VALUE) ((unsigned) (VALUE) + 0x80 < 0x100)
+#define CONST_OK_FOR_I(VALUE) ((VALUE) == 0)
+#define CONST_OK_FOR_J(VALUE) ((unsigned) (VALUE) + 0x10 < 0x20)
+#define CONST_OK_FOR_K(VALUE) ((unsigned) (VALUE) + 0x8000 < 0x10000)
+#define CONST_OK_FOR_L(VALUE) \
+ (((unsigned) ((int) (VALUE) >> 16) + 0x8000 < 0x10000) \
+ && CONST_OK_FOR_I ((VALUE & 0xffff)))
+#define CONST_OK_FOR_M(VALUE) ((unsigned)(VALUE) < 0x10000)
+
+#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
+
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'I' ? CONST_OK_FOR_I (VALUE) : \
+ (C) == 'J' ? CONST_OK_FOR_J (VALUE) : \
+ (C) == 'K' ? CONST_OK_FOR_K (VALUE) : \
+ (C) == 'L' ? CONST_OK_FOR_L (VALUE) : \
+ (C) == 'M' ? CONST_OK_FOR_M (VALUE) : \
+ (C) == 'N' ? CONST_OK_FOR_N (VALUE) : \
+ (C) == 'O' ? CONST_OK_FOR_O (VALUE) : \
+ (C) == 'P' ? CONST_OK_FOR_P (VALUE) : \
+ 0)
+
+/* Similar, but for floating constants, and defining letters G and H.
+ Here VALUE is the CONST_DOUBLE rtx itself.
+
+ `G' is a zero of some form. */
+
+#define CONST_DOUBLE_OK_FOR_G(VALUE) \
+ ((GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_FLOAT \
+ && (VALUE) == CONST0_RTX (GET_MODE (VALUE))) \
+ || (GET_MODE_CLASS (GET_MODE (VALUE)) == MODE_INT \
+ && CONST_DOUBLE_LOW (VALUE) == 0 \
+ && CONST_DOUBLE_HIGH (VALUE) == 0))
+
+#define CONST_DOUBLE_OK_FOR_H(VALUE) 0
+
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'G' ? CONST_DOUBLE_OK_FOR_G (VALUE) \
+ : (C) == 'H' ? CONST_DOUBLE_OK_FOR_H (VALUE) \
+ : 0)
+
+
+/* Stack layout; function entry, exit and calling. */
+
+/* Define this if pushing a word on the stack
+ makes the stack pointer a smaller address. */
+
+#define STACK_GROWS_DOWNWARD
+
+/* Define this if the nominal address of the stack frame
+ is at the high-address end of the local variables;
+ that is, each additional local variable allocated
+ goes at a more negative offset in the frame. */
+
+#define FRAME_GROWS_DOWNWARD
+
+/* Offset within stack frame to start allocating local variables at.
+ If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+ first local allocated. Otherwise, it is the offset to the BEGINNING
+ of the first local allocated. */
+
+#define STARTING_FRAME_OFFSET 0
+
+/* Offset of first parameter from the argument pointer register value. */
+/* Is equal to the size of the saved fp + pc, even if an fp isn't
+ saved since the value is used before we know. */
+
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* Specify the registers used for certain standard purposes.
+ The values of these macros are register numbers. */
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM 3
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 32
+
+/* On some machines the offset between the frame pointer and starting
+ offset of the automatic variables is not known until after register
+ allocation has been done (for example, because the saved registers
+ are between these two locations). On those machines, define
+ `FRAME_POINTER_REGNUM' the number of a special, fixed register to
+ be used internally until the offset is known, and define
+ `HARD_FRAME_POINTER_REGNUM' to be actual the hard register number
+ used for the frame pointer.
+
+ You should define this macro only in the very rare circumstances
+ when it is not possible to calculate the offset between the frame
+ pointer and the automatic variables until after register
+ allocation has been completed. When this macro is defined, you
+ must also indicate in your definition of `ELIMINABLE_REGS' how to
+ eliminate `FRAME_POINTER_REGNUM' into either
+ `HARD_FRAME_POINTER_REGNUM' or `STACK_POINTER_REGNUM'.
+
+ Do not define this macro if it would be the same as
+ `FRAME_POINTER_REGNUM'. */
+#define HARD_FRAME_POINTER_REGNUM 29
+
+/* Base register for access to arguments of the function. */
+#define ARG_POINTER_REGNUM 33
+
+/* Register in which static-chain is passed to a function. */
+#define STATIC_CHAIN_REGNUM 5
+
+/* Value should be nonzero if functions must have frame pointers.
+ Zero means the frame pointer need not be set up (and parms
+ may be accessed via the stack pointer) in functions that seem suitable.
+ This is computed in `reload', in reload1.c. */
+#define FRAME_POINTER_REQUIRED 0
+
+/* If defined, this macro specifies a table of register pairs used to
+ eliminate unneeded registers that point into the stack frame. If
+ it is not defined, the only elimination attempted by the compiler
+ is to replace references to the frame pointer with references to
+ the stack pointer.
+
+ The definition of this macro is a list of structure
+ initializations, each of which specifies an original and
+ replacement register.
+
+ On some machines, the position of the argument pointer is not
+ known until the compilation is completed. In such a case, a
+ separate hard register must be used for the argument pointer.
+ This register can be eliminated by replacing it with either the
+ frame pointer or the argument pointer, depending on whether or not
+ the frame pointer has been eliminated.
+
+ In this case, you might specify:
+ #define ELIMINABLE_REGS \
+ {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
+ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
+
+ Note that the elimination of the argument pointer with the stack
+ pointer is specified first since that is the preferred elimination. */
+
+#define ELIMINABLE_REGS \
+{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \
+ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }} \
+
+/* A C expression that returns non-zero if the compiler is allowed to
+ try to replace register number FROM-REG with register number
+ TO-REG. This macro need only be defined if `ELIMINABLE_REGS' is
+ defined, and will usually be the constant 1, since most of the
+ cases preventing register elimination are things that the compiler
+ already knows about. */
+
+#define CAN_ELIMINATE(FROM, TO) \
+ ((TO) == STACK_POINTER_REGNUM ? ! frame_pointer_needed : 1)
+
+/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It
+ specifies the initial difference between the specified pair of
+ registers. This macro must be defined if `ELIMINABLE_REGS' is
+ defined. */
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+{ \
+ if ((FROM) == FRAME_POINTER_REGNUM) \
+ (OFFSET) = get_frame_size () + current_function_outgoing_args_size; \
+ else if ((FROM) == ARG_POINTER_REGNUM) \
+ (OFFSET) = compute_frame_size (get_frame_size (), (long *)0); \
+ else \
+ abort (); \
+}
+
+/* A guess for the V850. */
+#define PROMOTE_PROTOTYPES 1
+
+/* Keep the stack pointer constant throughout the function. */
+#define ACCUMULATE_OUTGOING_ARGS
+
+/* Value is the number of bytes of arguments automatically
+ popped when returning from a subroutine call.
+ FUNDECL is the declaration node of the function (as a tree),
+ FUNTYPE is the data type of the function (as a tree),
+ or for a library call it is an identifier node for the subroutine name.
+ SIZE is the number of bytes of arguments passed on the stack. */
+
+#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
+
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go. */
+
+#define CUMULATIVE_ARGS struct cum_arg
+struct cum_arg { int nbytes; };
+
+/* Define where to put the arguments to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+struct rtx_def *function_arg();
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+ function_arg (&CUM, MODE, TYPE, NAMED)
+
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
+ function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED)
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS
+ for a call to a function whose data type is FNTYPE.
+ For a library call, FNTYPE is 0. */
+
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
+ ((CUM).nbytes = 0)
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be available.) */
+
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+ ((CUM).nbytes += ((MODE) != BLKmode \
+ ? (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD \
+ : (int_size_in_bytes (TYPE) + UNITS_PER_WORD - 1) & -UNITS_PER_WORD))
+
+/* When a parameter is passed in a register, stack space is still
+ allocated for it. */
+#define REG_PARM_STACK_SPACE(DECL) (!TARGET_GHS ? 16 : 0)
+
+/* Define this if the above stack space is to be considered part of the
+ space allocated by the caller. */
+#define OUTGOING_REG_PARM_STACK_SPACE
+
+extern int current_function_anonymous_args;
+/* Do any setup necessary for varargs/stdargs functions. */
+#define SETUP_INCOMING_VARARGS(CUM, MODE, TYPE, PAS, SECOND) \
+ current_function_anonymous_args = (!TARGET_GHS ? 1 : 0);
+
+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
+ ((TYPE) && int_size_in_bytes (TYPE) > 8)
+
+#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \
+ ((TYPE) && int_size_in_bytes (TYPE) > 8)
+
+/* 1 if N is a possible register number for function argument passing. */
+
+#define FUNCTION_ARG_REGNO_P(N) (N >= 6 && N <= 9)
+
+/* Define how to find the value returned by a function.
+ VALTYPE is the data type of the value (as a tree).
+ If the precise function being called is known, FUNC is its FUNCTION_DECL;
+ otherwise, FUNC is 0. */
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), 10)
+
+/* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, MODE, 10)
+
+/* 1 if N is a possible register number for a function value. */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == 10)
+
+/* Return values > 8 bytes in length in memory. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+#define RETURN_IN_MEMORY(TYPE) \
+ (int_size_in_bytes (TYPE) > 8 || TYPE_MODE (TYPE) == BLKmode)
+
+/* Register in which address to store a structure value
+ is passed to a function. On the V850 it's passed as
+ the first parameter. */
+
+#define STRUCT_VALUE 0
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+#define EXIT_IGNORE_STACK 1
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) ;
+
+#define TRAMPOLINE_TEMPLATE(FILE) \
+ do { \
+ fprintf (FILE, "\tjarl .+4,r12\n"); \
+ fprintf (FILE, "\tld.w 12[r12],r5\n"); \
+ fprintf (FILE, "\tld.w 16[r12],r12\n"); \
+ fprintf (FILE, "\tjmp [r12]\n"); \
+ fprintf (FILE, "\tnop\n"); \
+ fprintf (FILE, "\t.long 0\n"); \
+ fprintf (FILE, "\t.long 0\n"); \
+ } while (0)
+
+/* Length in units of the trampoline for entering a nested function. */
+
+#define TRAMPOLINE_SIZE 24
+
+/* Emit RTL insns to initialize the variable parts of a trampoline.
+ FNADDR is an RTX for the address of the function's pure code.
+ CXT is an RTX for the static chain value for the function. */
+
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
+{ \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 16)), \
+ (CXT)); \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 20)), \
+ (FNADDR)); \
+}
+
+/* Addressing modes, and classification of registers for them. */
+
+
+/* 1 if X is an rtx for a constant that is a valid address. */
+
+#define CONSTANT_ADDRESS_P(X) \
+ (GET_CODE (X) == CONST_INT \
+ && CONST_OK_FOR_K (INTVAL (X)))
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 1
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects
+ them unless they have been allocated suitable hard regs.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Source files for reload pass need to be strict.
+ After reload, it makes no difference, since pseudo regs have
+ been eliminated by then. */
+
+#ifndef REG_OK_STRICT
+
+/* Nonzero if X is a hard reg that can be used as an index
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_INDEX_P(X) 0
+/* Nonzero if X is a hard reg that can be used as a base reg
+ or if it is a pseudo reg. */
+#define REG_OK_FOR_BASE_P(X) 1
+#define REG_OK_FOR_INDEX_P_STRICT(X) 0
+#define REG_OK_FOR_BASE_P_STRICT(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+#define STRICT 0
+
+#else
+
+/* Nonzero if X is a hard reg that can be used as an index. */
+#define REG_OK_FOR_INDEX_P(X) 0
+/* Nonzero if X is a hard reg that can be used as a base reg. */
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
+#define STRICT 1
+
+#endif
+
+/* A C expression that defines the optional machine-dependent
+ constraint letters that can be used to segregate specific types of
+ operands, usually memory references, for the target machine.
+ Normally this macro will not be defined. If it is required for a
+ particular target machine, it should return 1 if VALUE corresponds
+ to the operand type represented by the constraint letter C. If C
+ is not defined as an extra constraint, the value returned should
+ be 0 regardless of VALUE.
+
+ For example, on the ROMP, load instructions cannot have their
+ output in r0 if the memory reference contains a symbolic address.
+ Constraint letter `Q' is defined as representing a memory address
+ that does *not* contain a symbolic address. An alternative is
+ specified with a `Q' constraint on the input and `r' on the
+ output. The next alternative specifies `m' on the input and a
+ register class that does not include r0 on the output. */
+
+#define EXTRA_CONSTRAINT(OP, C) \
+ ((C) == 'Q' ? ep_memory_operand (OP, GET_MODE (OP)) \
+ : (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 \
+ : 0)
+
+/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
+ that is a valid memory address for an instruction.
+ The MODE argument is the machine mode for the MEM expression
+ that wants to use this address.
+
+ The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS,
+ except for CONSTANT_ADDRESS_P which is actually
+ machine-independent. */
+
+/* Accept either REG or SUBREG where a register is valid. */
+
+#define RTX_OK_FOR_BASE_P(X) \
+ ((REG_P (X) && REG_OK_FOR_BASE_P (X)) \
+ || (GET_CODE (X) == SUBREG && REG_P (SUBREG_REG (X)) \
+ && REG_OK_FOR_BASE_P (SUBREG_REG (X))))
+
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+do { \
+ if (RTX_OK_FOR_BASE_P (X)) goto ADDR; \
+ if (CONSTANT_ADDRESS_P (X) \
+ && (MODE == QImode || INTVAL (X) % 2 == 0)) \
+ goto ADDR; \
+ if (GET_CODE (X) == LO_SUM \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+ && CONSTANT_P (XEXP (X, 1)) \
+ && (GET_CODE (XEXP (X, 1)) != CONST_INT \
+ || ((MODE == QImode || INTVAL (XEXP (X, 1)) % 2 == 0) \
+ && CONST_OK_FOR_K (INTVAL (XEXP (X, 1))))) \
+ && GET_MODE_SIZE (MODE) <= GET_MODE_SIZE (word_mode)) \
+ goto ADDR; \
+ if (special_symbolref_operand (X, MODE) \
+ && (GET_MODE_SIZE (MODE) <= GET_MODE_SIZE (word_mode))) \
+ goto ADDR; \
+ if (GET_CODE (X) == PLUS \
+ && CONSTANT_ADDRESS_P (XEXP (X, 1)) \
+ && (MODE == QImode || INTVAL (XEXP (X, 1)) % 2 == 0) \
+ && RTX_OK_FOR_BASE_P (XEXP (X, 0))) goto ADDR; \
+} while (0)
+
+
+/* Try machine-dependent ways of modifying an illegitimate address
+ to be legitimate. If we find one, return the new, valid address.
+ This macro is used in only one place: `memory_address' in explow.c.
+
+ OLDX is the address as it was before break_out_memory_refs was called.
+ In some cases it is useful to look at this to decide what needs to be done.
+
+ MODE and WIN are passed so that this macro can use
+ GO_IF_LEGITIMATE_ADDRESS.
+
+ It is always safe for this macro to do nothing. It exists to recognize
+ opportunities to optimize the output. */
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) {}
+
+/* Go to LABEL if ADDR (a legitimate address expression)
+ has an effect that depends on the machine mode it is used for. */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {}
+
+/* Nonzero if the constant value X is a legitimate general operand.
+ It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
+
+#define LEGITIMATE_CONSTANT_P(X) \
+ (GET_CODE (X) == CONST_DOUBLE \
+ || !(GET_CODE (X) == CONST \
+ && GET_CODE (XEXP (X, 0)) == PLUS \
+ && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF \
+ && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
+ && ! CONST_OK_FOR_K (INTVAL (XEXP (XEXP (X, 0), 1)))))
+
+/* In rare cases, correct code generation requires extra machine
+ dependent processing between the second jump optimization pass and
+ delayed branch scheduling. On those machines, define this macro
+ as a C statement to act on the code starting at INSN. */
+
+#define MACHINE_DEPENDENT_REORG(INSN) v850_reorg (INSN)
+
+
+/* Tell final.c how to eliminate redundant test instructions. */
+
+/* Here we define machine-dependent flags and fields in cc_status
+ (see `conditions.h'). No extra ones are needed for the vax. */
+
+/* Store in cc_status the expressions
+ that the condition codes will describe
+ after execution of an instruction whose pattern is EXP.
+ Do not alter them if the instruction would not alter the cc's. */
+
+#define CC_OVERFLOW_UNUSABLE 0x200
+#define CC_NO_CARRY CC_NO_OVERFLOW
+#define NOTICE_UPDATE_CC(EXP, INSN) notice_update_cc(EXP, INSN)
+
+/* A part of a C `switch' statement that describes the relative costs
+ of constant RTL expressions. It must contain `case' labels for
+ expression codes `const_int', `const', `symbol_ref', `label_ref'
+ and `const_double'. Each case must ultimately reach a `return'
+ statement to return the relative cost of the use of that kind of
+ constant value in an expression. The cost may depend on the
+ precise value of the constant, which is available for examination
+ in X, and the rtx code of the expression in which it is contained,
+ found in OUTER_CODE.
+
+ CODE is the expression code--redundant, since it can be obtained
+ with `GET_CODE (X)'. */
+
+#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
+ case CONST_INT: \
+ case CONST_DOUBLE: \
+ case CONST: \
+ case SYMBOL_REF: \
+ case LABEL_REF: \
+ { \
+ int _zxy = const_costs(RTX, CODE); \
+ return (_zxy) ? COSTS_N_INSNS (_zxy) : 0; \
+ }
+
+/* A crude cut at RTX_COSTS for the V850. */
+
+/* Provide the costs of a rtl expression. This is in the body of a
+ switch on CODE.
+
+ There aren't DImode MOD, DIV or MULT operations, so call them
+ very expensive. Everything else is pretty much a costant cost. */
+
+#define RTX_COSTS(RTX,CODE,OUTER_CODE) \
+ case MOD: \
+ case DIV: \
+ return 60; \
+ case MULT: \
+ return 20;
+
+/* All addressing modes have the same cost on the V850 series. */
+#define ADDRESS_COST(ADDR) 1
+
+/* Nonzero if access to memory by bytes or half words is no faster
+ than accessing full words. */
+#define SLOW_BYTE_ACCESS 1
+
+/* Define this if zero-extension is slow (more than one real instruction). */
+#define SLOW_ZERO_EXTEND
+
+/* According expr.c, a value of around 6 should minimize code size, and
+ for the V850 series, that's our primary concern. */
+#define MOVE_RATIO 6
+
+/* Indirect calls are expensive, never turn a direct call
+ into an indirect call. */
+#define NO_FUNCTION_CSE
+
+/* A list of names for sections other than the standard two, which are
+ `in_text' and `in_data'. You need not define this macro on a
+ system with no other sections (that GCC needs to use). */
+#undef EXTRA_SECTIONS
+#define EXTRA_SECTIONS in_tdata, in_sdata, in_zdata, in_const, in_ctors, in_dtors
+
+/* One or more functions to be defined in `varasm.c'. These
+ functions should do jobs analogous to those of `text_section' and
+ `data_section', for your additional sections. Do not define this
+ macro if you do not define `EXTRA_SECTIONS'. */
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
+CONST_SECTION_FUNCTION \
+CTORS_SECTION_FUNCTION \
+DTORS_SECTION_FUNCTION \
+ \
+void \
+sdata_section () \
+{ \
+ if (in_section != in_sdata) \
+ { \
+ fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \
+ in_section = in_sdata; \
+ } \
+} \
+ \
+void \
+tdata_section () \
+{ \
+ if (in_section != in_tdata) \
+ { \
+ fprintf (asm_out_file, "%s\n", TDATA_SECTION_ASM_OP); \
+ in_section = in_tdata; \
+ } \
+} \
+ \
+void \
+zdata_section () \
+{ \
+ if (in_section != in_zdata) \
+ { \
+ fprintf (asm_out_file, "%s\n", ZDATA_SECTION_ASM_OP); \
+ in_section = in_zdata; \
+ } \
+}
+
+#define TEXT_SECTION_ASM_OP "\t.section .text"
+#define DATA_SECTION_ASM_OP "\t.section .data"
+#define BSS_SECTION_ASM_OP "\t.section .bss"
+#define SDATA_SECTION_ASM_OP "\t.section .sdata,\"aw\""
+#define SBSS_SECTION_ASM_OP "\t.section .sbss,\"aw\""
+#define ZDATA_SECTION_ASM_OP "\t.section .zdata,\"aw\""
+#define ZBSS_SECTION_ASM_OP "\t.section .zbss,\"aw\""
+#define TDATA_SECTION_ASM_OP "\t.section .tdata,\"aw\""
+
+/* A C statement or statements to switch to the appropriate section
+ for output of EXP. You can assume that EXP is either a `VAR_DECL'
+ node or a constant of some sort. RELOC indicates whether the
+ initial value of EXP requires link-time relocations. Select the
+ section by calling `text_section' or one of the alternatives for
+ other sections.
+
+ Do not define this macro if you put all read-only variables and
+ constants in the read-only data section (usually the text section). */
+#undef SELECT_SECTION
+#define SELECT_SECTION(EXP, RELOC) \
+do { \
+ if (TREE_CODE (EXP) == VAR_DECL) \
+ { \
+ if (!TREE_READONLY (EXP) || TREE_SIDE_EFFECTS (EXP) \
+ || !DECL_INITIAL (EXP) \
+ || (DECL_INITIAL (EXP) != error_mark_node \
+ && !TREE_CONSTANT (DECL_INITIAL (EXP)))) \
+ data_section (); \
+ else \
+ const_section (); \
+ } \
+ else if (TREE_CODE (EXP) == STRING_CST) \
+ { \
+ if (! flag_writable_strings) \
+ const_section (); \
+ else \
+ data_section (); \
+ } \
+ \
+ else \
+ const_section (); \
+ \
+} while (0)
+
+/* A C statement or statements to switch to the appropriate section
+ for output of RTX in mode MODE. You can assume that RTX is some
+ kind of constant in RTL. The argument MODE is redundant except in
+ the case of a `const_int' rtx. Select the section by calling
+ `text_section' or one of the alternatives for other sections.
+
+ Do not define this macro if you put all constants in the read-only
+ data section. */
+/* #define SELECT_RTX_SECTION(MODE, RTX) */
+
+/* Output at beginning/end of assembler file. */
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) asm_file_start(FILE)
+
+#define ASM_COMMENT_START "#"
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#define ASM_APP_ON "#APP\n"
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#define ASM_APP_OFF "#NO_APP\n"
+
+/* This is how to output an assembler line defining a `double' constant.
+ It is .double or .float, depending. */
+
+#define ASM_OUTPUT_DOUBLE(FILE, VALUE) \
+do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
+ fprintf (FILE, "\t.double %s\n", dstr); \
+ } while (0)
+
+
+/* This is how to output an assembler line defining a `float' constant. */
+#define ASM_OUTPUT_FLOAT(FILE, VALUE) \
+do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
+ fprintf (FILE, "\t.float %s\n", dstr); \
+ } while (0)
+
+/* This is how to output an assembler line defining an `int' constant. */
+
+#define ASM_OUTPUT_INT(FILE, VALUE) \
+( fprintf (FILE, "\t.long "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* Likewise for `char' and `short' constants. */
+
+#define ASM_OUTPUT_SHORT(FILE, VALUE) \
+( fprintf (FILE, "\t.hword "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+#define ASM_OUTPUT_CHAR(FILE, VALUE) \
+( fprintf (FILE, "\t.byte "), \
+ output_addr_const (FILE, (VALUE)), \
+ fprintf (FILE, "\n"))
+
+/* This is how to output an assembler line for a numeric constant byte. */
+#define ASM_OUTPUT_BYTE(FILE, VALUE) \
+ fprintf (FILE, "\t.byte 0x%x\n", (VALUE))
+
+/* Define the parentheses used to group arithmetic operations
+ in assembler code. */
+
+#define ASM_OPEN_PAREN "("
+#define ASM_CLOSE_PAREN ")"
+
+/* This says how to output the assembler to define a global
+ uninitialized but not common symbol.
+ Try to use asm_output_bss to implement this macro. */
+
+#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED) \
+ asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED))
+
+/* This is how to output the definition of a user-level label named NAME,
+ such as the label on a static function or variable NAME. */
+
+#define ASM_OUTPUT_LABEL(FILE, NAME) \
+ do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+
+/* This is how to output a command to make the user-level label named NAME
+ defined for reference from other files. */
+
+#define ASM_GLOBALIZE_LABEL(FILE, NAME) \
+ do { fputs ("\t.global ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
+
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
+
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE, NAME) \
+ do { \
+ char* real_name; \
+ STRIP_NAME_ENCODING (real_name, (NAME)); \
+ fprintf (FILE, "_%s", real_name); \
+ } while (0)
+
+/* Store in OUTPUT a string (made with alloca) containing
+ an assembler-name for a local static variable named NAME.
+ LABELNO is an integer which is different for each call. */
+
+#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
+( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
+ sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO)))
+
+/* This is how we tell the assembler that two symbols have the same value. */
+
+#define ASM_OUTPUT_DEF(FILE,NAME1,NAME2) \
+ do { assemble_name(FILE, NAME1); \
+ fputs(" = ", FILE); \
+ assemble_name(FILE, NAME2); \
+ fputc('\n', FILE); } while (0)
+
+
+/* How to refer to registers in assembler output.
+ This sequence is indexed by compiler's hard-register-number (see above). */
+
+#define REGISTER_NAMES \
+{ "r0", "r1", "r2", "sp", "gp", "r5", "r6" , "r7", \
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
+ "r24", "r25", "r26", "r27", "r28", "r29", "ep", "r31", \
+ ".fp", ".ap"}
+
+#define ADDITIONAL_REGISTER_NAMES \
+{ { "zero", 0 }, \
+ { "hp", 2 }, \
+ { "r3", 3 }, \
+ { "r4", 4 }, \
+ { "tp", 5 }, \
+ { "fp", 29 }, \
+ { "r30", 30 }, \
+ { "lp", 31} }
+
+/* Print an instruction operand X on file FILE.
+ look in v850.c for details */
+
+#define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE,X,CODE)
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+ ((CODE) == '.')
+
+/* Print a memory operand whose address is X, on file FILE.
+ This uses a function in output-vax.c. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+
+#define ASM_OUTPUT_REG_PUSH(FILE,REGNO)
+#define ASM_OUTPUT_REG_POP(FILE,REGNO)
+
+/* 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)
+
+/* 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)
+
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG) != 0) \
+ fprintf (FILE, "\t.align %d\n", (LOG))
+
+/* We don't have to worry about dbx compatability for the v850. */
+#define DEFAULT_GDB_EXTENSIONS 1
+
+/* Use stabs debugging info by default. */
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+#define DBX_REGISTER_NUMBER(REGNO) REGNO
+
+/* Define to use software floating point emulator for REAL_ARITHMETIC and
+ decimal <-> binary conversion. */
+#define REAL_ARITHMETIC
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction. */
+#define CASE_VECTOR_MODE Pmode
+
+/* 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 WORD_REGISTER_OPERATIONS
+
+/* Byte and short loads sign extend the value to a word. */
+#define LOAD_EXTEND_OP(MODE) SIGN_EXTEND
+
+/* Specify the tree operation to be used to convert reals to integers. */
+#define IMPLICIT_FIX_EXPR FIX_ROUND_EXPR
+
+/* This flag, if defined, says the same insns that convert to a signed fixnum
+ also convert validly to an unsigned one. */
+#define FIXUNS_TRUNC_LIKE_FIX_TRUNC
+
+/* This is the kind of divide that is easiest to do in the general case. */
+#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX 4
+
+/* Define if shifts truncate the shift count
+ which implies one can omit a sign-extension or zero-extension
+ of a shift count. */
+#define SHIFT_COUNT_TRUNCATED 1
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
+
+#define STORE_FLAG_VALUE 1
+
+/* Specify the machine mode that pointers have.
+ After generation of rtl, the compiler makes no further distinction
+ between pointers and any other objects of this machine mode. */
+#define Pmode SImode
+
+/* A function address in a call instruction
+ is a byte address (for indexing purposes)
+ so give the MEM rtx a byte's mode. */
+#define FUNCTION_MODE QImode
+
+/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
+ is a valid machine specific attribute for DECL.
+ The attributes in ATTRIBUTES have previously been assigned to DECL. */
+#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
+v850_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
+
+/* Tell compiler we have {ZDA,TDA,SDA} small data regions */
+#define HAVE_ZDA 1
+#define HAVE_SDA 1
+#define HAVE_TDA 1
+
+/* Tell compiler we want to support GHS pragmas */
+#define HANDLE_GHS_PRAGMA
+
+/* The assembler op to to start the file. */
+
+#define FILE_ASM_OP "\t.file\n"
+
+/* Enable the register move pass to improve code. */
+#define ENABLE_REGMOVE_PASS
+
+
+/* Implement ZDA, TDA, and SDA */
+
+#define EP_REGNUM 30 /* ep register number */
+
+#define ENCODE_SECTION_INFO(DECL) \
+do { \
+ if ((TREE_STATIC (DECL) || DECL_EXTERNAL (DECL)) \
+ && TREE_CODE (DECL) == VAR_DECL) \
+ v850_encode_data_area (DECL); \
+} while (0)
+
+#define ZDA_NAME_FLAG_CHAR '@'
+#define TDA_NAME_FLAG_CHAR '%'
+#define SDA_NAME_FLAG_CHAR '&'
+
+#define ZDA_NAME_P(NAME) (*(NAME) == ZDA_NAME_FLAG_CHAR)
+#define TDA_NAME_P(NAME) (*(NAME) == TDA_NAME_FLAG_CHAR)
+#define SDA_NAME_P(NAME) (*(NAME) == SDA_NAME_FLAG_CHAR)
+
+#define ENCODED_NAME_P(SYMBOL_NAME) \
+ (ZDA_NAME_P (SYMBOL_NAME) \
+ || TDA_NAME_P (SYMBOL_NAME) \
+ || SDA_NAME_P (SYMBOL_NAME))
+
+#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
+ (VAR) = (SYMBOL_NAME) + (ENCODED_NAME_P (SYMBOL_NAME) || *(SYMBOL_NAME) == '*')
+
+/* Define this if you have defined special-purpose predicates in the
+ file `MACHINE.c'. This macro is called within an initializer of an
+ array of structures. The first field in the structure is the name
+ of a predicate and the second field is an array of rtl codes. For
+ each predicate, list all rtl codes that can be in expressions
+ matched by the predicate. The list should have a trailing comma. */
+
+#define PREDICATE_CODES \
+{ "ep_memory_operand", { MEM }}, \
+{ "reg_or_0_operand", { REG, SUBREG, CONST_INT, CONST_DOUBLE }}, \
+{ "reg_or_int5_operand", { REG, SUBREG, CONST_INT }}, \
+{ "call_address_operand", { REG, SYMBOL_REF }}, \
+{ "movsi_source_operand", { LABEL_REF, SYMBOL_REF, CONST_INT, \
+ CONST_DOUBLE, CONST, HIGH, MEM, \
+ REG, SUBREG }}, \
+{ "special_symbolref_operand", { SYMBOL_REF }}, \
+{ "power_of_two_operand", { CONST_INT }}, \
+{ "not_power_of_two_operand", { CONST_INT }},
+
+extern void override_options ();
+extern void asm_file_start ();
+extern int function_arg_partial_nregs ();
+extern int const_costs ();
+extern void print_operand ();
+extern void print_operand_address ();
+extern char *output_move_double ();
+extern char *output_move_single ();
+extern int ep_operand ();
+extern int reg_or_0_operand ();
+extern int reg_or_int5_operand ();
+extern int call_address_operand ();
+extern int movsi_source_operand ();
+extern int power_of_two_operand ();
+extern int not_power_of_two_operand ();
+extern void v850_reorg ();
+extern int compute_register_save_size ();
+extern int compute_frame_size ();
+extern void expand_prologue ();
+extern void expand_epilogue ();
+extern void notice_update_cc ();
+extern int v850_valid_machine_decl_attribute ();
+extern int v850_interrupt_function_p ();
+/* END CYGNUS LOCAL */
diff --git a/gcc/config/v850/v850.md b/gcc/config/v850/v850.md
new file mode 100644
index 0000000..30ebf87
--- /dev/null
+++ b/gcc/config/v850/v850.md
@@ -0,0 +1,1852 @@
+;; CYGNUS LOCAL entire file/law
+;; GCC machine description for NEC V850
+;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+
+;; Contributed by Jeff Law (law@cygnus.com).
+
+;; This file is part of GNU CC.
+
+;; GNU CC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU CC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU CC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; The original PO technology requires these to be ordered by speed,
+;; so that assigner will pick the fastest.
+
+;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
+
+;; The V851 manual states that the instruction address space is 16M;
+;; the various branch/call instructions only have a 22bit offset (4M range).
+;;
+;; One day we'll probably need to handle calls to targets more than 4M
+;; away.
+
+;; The size of instructions in bytes.
+
+(define_attr "length" ""
+ (const_int 200))
+
+;; Types of instructions (for scheduling purposes).
+
+(define_attr "type" "load,mult,other"
+ (const_string "other"))
+
+;; Condition code settings.
+;; none - insn does not affect cc
+;; none_0hit - insn does not affect cc but it does modify operand 0
+;; This attribute is used to keep track of when operand 0 changes.
+;; See the description of NOTICE_UPDATE_CC for more info.
+;; set_znv - sets z,n,v to useable values; c is unknown.
+;; set_zn - sets z,n to usable values; v,c is unknown.
+;; compare - compare instruction
+;; clobber - value of cc is unknown
+(define_attr "cc" "none,none_0hit,set_zn,set_znv,compare,clobber"
+ (const_string "clobber"))
+
+;; Function units for the V850. As best as I can tell, there's
+;; a traditional memory load/use stall as well as a stall if
+;; the result of a multiply is used too early.
+;;
+(define_function_unit "memory" 1 0 (eq_attr "type" "load") 2 0)
+(define_function_unit "mult" 1 0 (eq_attr "type" "mult") 2 0)
+
+
+;; ----------------------------------------------------------------------
+;; MOVE INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+;; movqi
+
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+ "
+{
+ /* One of the ops has to be in a register or 0 */
+ if (!register_operand (operand0, QImode)
+ && !reg_or_0_operand (operand1, QImode))
+ operands[1] = copy_to_mode_reg (QImode, operand1);
+}")
+
+(define_insn "*movqi_internal"
+ [(set (match_operand:QI 0 "general_operand" "=r,r,r,Q,r,m,m")
+ (match_operand:QI 1 "general_operand" "Jr,n,Q,Ir,m,r,I"))]
+ "register_operand (operands[0], QImode)
+ || reg_or_0_operand (operands[1], QImode)"
+ "* return output_move_single (operands);"
+ [(set_attr "length" "2,4,2,2,4,4,4")
+ (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")
+ (set_attr "type" "other,other,load,other,load,other,other")])
+
+;; movhi
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "
+{
+ /* One of the ops has to be in a register or 0 */
+ if (!register_operand (operand0, HImode)
+ && !reg_or_0_operand (operand1, HImode))
+ operands[1] = copy_to_mode_reg (HImode, operand1);
+}")
+
+(define_insn "*movhi_internal"
+ [(set (match_operand:HI 0 "general_operand" "=r,r,r,Q,r,m,m")
+ (match_operand:HI 1 "general_operand" "Jr,n,Q,Ir,m,r,I"))]
+ "register_operand (operands[0], HImode)
+ || reg_or_0_operand (operands[1], HImode)"
+ "* return output_move_single (operands);"
+ [(set_attr "length" "2,4,2,2,4,4,4")
+ (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")
+ (set_attr "type" "other,other,load,other,load,other,other")])
+
+;; movsi and helpers
+
+(define_insn "*movsi_high"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (match_operand 1 "" "")))]
+ ""
+ "movhi hi(%1),%.,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")
+ (set_attr "type" "other")])
+
+(define_insn "*movsi_lo"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "i")))]
+ ""
+ "movea lo(%2),%1,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")
+ (set_attr "type" "other")])
+
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" ""))]
+ ""
+ "
+{
+ /* One of the ops has to be in a register or 0 */
+ if (!register_operand (operand0, SImode)
+ && !reg_or_0_operand (operand1, SImode))
+ operands[1] = copy_to_mode_reg (SImode, operand1);
+
+ /* Some constants, as well as symbolic operands
+ must be done with HIGH & LO_SUM patterns. */
+ if (CONSTANT_P (operands[1])
+ && GET_CODE (operands[1]) != HIGH
+ && !special_symbolref_operand (operands[1], VOIDmode)
+ && !(GET_CODE (operands[1]) == CONST_INT
+ && (CONST_OK_FOR_J (INTVAL (operands[1]))
+ || CONST_OK_FOR_K (INTVAL (operands[1]))
+ || CONST_OK_FOR_L (INTVAL (operands[1])))))
+ {
+ rtx high;
+ rtx temp;
+
+ if (reload_in_progress || reload_completed)
+ temp = operands[0];
+ else
+ temp = gen_reg_rtx (SImode);
+
+ emit_insn (gen_rtx (SET, SImode, temp,
+ gen_rtx (HIGH, SImode, operand1)));
+ emit_insn (gen_rtx (SET, SImode, operand0,
+ gen_rtx (LO_SUM, SImode, temp, operand1)));
+ DONE;
+ }
+}")
+
+(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"))]
+ "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")
+ (set_attr "cc" "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")])
+
+(define_expand "movdi"
+ [(set (match_operand:DI 0 "general_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ ""
+ "
+{
+ /* One of the ops has to be in a register or 0 */
+ if (!register_operand (operand0, DImode)
+ && !reg_or_0_operand (operand1, DImode))
+ operands[1] = copy_to_mode_reg (DImode, operand1);
+}")
+
+(define_insn "*movdi_internal"
+ [(set (match_operand:DI 0 "general_operand" "=r,r,r,r,r,m,m,r")
+ (match_operand:DI 1 "general_operand" "Jr,K,L,i,m,r,IG,iF"))]
+ "register_operand (operands[0], DImode)
+ || reg_or_0_operand (operands[1], DImode)"
+ "* return output_move_double (operands);"
+ [(set_attr "length" "4,8,8,16,8,8,8,16")
+ (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")
+ (set_attr "type" "other,other,other,other,load,other,other,other")])
+
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "general_operand" ""))]
+ ""
+ "
+{
+ /* One of the ops has to be in a register or 0 */
+ if (!register_operand (operand0, SFmode)
+ && !reg_or_0_operand (operand1, SFmode))
+ operands[1] = copy_to_mode_reg (SFmode, operand1);
+}")
+
+(define_insn "*movsf_internal"
+ [(set (match_operand:SF 0 "general_operand" "=r,r,r,r,r,Q,r,m,m,r")
+ (match_operand:SF 1 "general_operand" "Jr,K,L,n,Q,Ir,m,r,IG,iF"))]
+ "register_operand (operands[0], SFmode)
+ || reg_or_0_operand (operands[1], SFmode)"
+ "* return output_move_single (operands);"
+ [(set_attr "length" "2,4,4,8,2,2,4,4,4,8")
+ (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,other,load,other,load,other,other,other")])
+
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ ""
+ "
+{
+ /* One of the ops has to be in a register or 0 */
+ if (!register_operand (operand0, DFmode)
+ && !reg_or_0_operand (operand1, DFmode))
+ operands[1] = copy_to_mode_reg (DFmode, operand1);
+}")
+
+(define_insn "*movdf_internal"
+ [(set (match_operand:DF 0 "general_operand" "=r,r,r,r,r,m,m,r")
+ (match_operand:DF 1 "general_operand" "Jr,K,L,i,m,r,IG,iF"))]
+ "register_operand (operands[0], DFmode)
+ || reg_or_0_operand (operands[1], DFmode)"
+ "* return output_move_double (operands);"
+ [(set_attr "length" "4,8,8,16,8,8,8,16")
+ (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")
+ (set_attr "type" "other,other,other,other,load,other,other,other")])
+
+
+;; ----------------------------------------------------------------------
+;; TEST INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_insn "*v850_tst1"
+ [(set (cc0) (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
+ (const_int 1)
+ (match_operand:QI 1 "const_int_operand" "n")))]
+ ""
+ "tst1 %1,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+(define_insn "tstsi"
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))]
+ ""
+ "cmp %.,%0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_znv")])
+
+(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")))]
+ ""
+ "@
+ cmp %1,%0
+ cmp %1,%0"
+ [(set_attr "length" "2,2")
+ (set_attr "cc" "compare")])
+
+;; ----------------------------------------------------------------------
+;; ADD INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_insn "addsi3"
+ [(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")))]
+ ""
+ "@
+ add %2,%0
+ addi %2,%1,%0
+ mov %1,%0\;add %2,%0"
+ [(set_attr "length" "2,4,6")
+ (set_attr "cc" "set_zn")])
+
+;; ----------------------------------------------------------------------
+;; SUBTRACT INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (minus:SI (match_operand:SI 1 "register_operand" "0,r")
+ (match_operand:SI 2 "register_operand" "r,0")))]
+ ""
+ "@
+ sub %2,%0
+ subr %1,%0"
+ [(set_attr "length" "2,2")
+ (set_attr "cc" "set_zn")])
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (neg:SI (match_operand:SI 1 "register_operand" "0")))]
+ ""
+ "subr %.,%0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
+
+;; ----------------------------------------------------------------------
+;; MULTIPLY INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_expand "mulhisi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (mult:SI
+ (sign_extend:SI (match_operand:HI 1 "register_operand" ""))
+ (sign_extend:SI (match_operand:HI 2 "nonmemory_operand" ""))))]
+ ""
+ "")
+
+(define_insn "*mulhisi3_internal1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI
+ (sign_extend:SI (match_operand:HI 1 "register_operand" "%0"))
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
+ ""
+ "mulh %2,%0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "none_0hit")
+ (set_attr "type" "mult")])
+
+(define_insn "*mulhisi3_internal2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (mult:SI
+ (sign_extend:SI (match_operand:HI 1 "register_operand" "%0,r"))
+ (sign_extend:SI (match_operand 2 "const_int_operand" "J,K"))))]
+ ""
+ "@
+ mulh %2,%0
+ mulhi %2,%1,%0"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "none_0hit,none_0hit")
+ (set_attr "type" "mult")])
+
+
+;; ----------------------------------------------------------------------
+;; AND INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_insn "*v850_clr1_1"
+ [(set (match_operand:QI 0 "memory_operand" "=m")
+ (subreg:QI
+ (and:SI (subreg:SI (match_dup 0) 0)
+ (match_operand:QI 1 "not_power_of_two_operand" "")) 0))]
+ ""
+ "*
+{
+ rtx xoperands[2];
+ xoperands[0] = operands[0];
+ xoperands[1] = GEN_INT (~INTVAL (operands[1]) & 0xff);
+ output_asm_insn (\"clr1 %M1,%0\", xoperands);
+ return \"\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*v850_clr1_2"
+ [(set (match_operand:HI 0 "memory_operand" "=m")
+ (subreg:HI
+ (and:SI (subreg:SI (match_dup 0) 0)
+ (match_operand:HI 1 "not_power_of_two_operand" "")) 0))]
+ ""
+ "*
+{
+ int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffff);
+
+ rtx xoperands[2];
+ xoperands[0] = gen_rtx (MEM, QImode,
+ plus_constant (XEXP (operands[0], 0), log2 / 8));
+ xoperands[1] = GEN_INT (log2 % 8);
+ output_asm_insn (\"clr1 %1,%0\", xoperands);
+ return \"\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*v850_clr1_3"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (and:SI (match_dup 0)
+ (match_operand:SI 1 "not_power_of_two_operand" "")))]
+ ""
+ "*
+{
+ int log2 = exact_log2 (~INTVAL (operands[1]) & 0xffffffff);
+
+ rtx xoperands[2];
+ xoperands[0] = gen_rtx (MEM, QImode,
+ plus_constant (XEXP (operands[0], 0), log2 / 8));
+ xoperands[1] = GEN_INT (log2 % 8);
+ output_asm_insn (\"clr1 %1,%0\", xoperands);
+ return \"\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ (and:SI (match_operand:SI 1 "register_operand" "%0,0,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,I,M")))]
+ ""
+ "@
+ and %2,%0
+ and %.,%0
+ andi %2,%1,%0"
+ [(set_attr "length" "2,2,4")
+ (set_attr "cc" "set_znv")])
+
+;; ----------------------------------------------------------------------
+;; OR INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_insn "*v850_set1_1"
+ [(set (match_operand:QI 0 "memory_operand" "=m")
+ (subreg:QI (ior:SI (subreg:SI (match_dup 0) 0)
+ (match_operand 1 "power_of_two_operand" "")) 0))]
+ ""
+ "set1 %M1,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*v850_set1_2"
+ [(set (match_operand:HI 0 "memory_operand" "=m")
+ (subreg:HI (ior:SI (subreg:SI (match_dup 0) 0)
+ (match_operand 1 "power_of_two_operand" "")) 0))]
+ ""
+ "*
+{
+ int log2 = exact_log2 (INTVAL (operands[1]));
+
+ if (log2 < 8)
+ return \"set1 %M1,%0\";
+ else
+ {
+ rtx xoperands[2];
+ xoperands[0] = gen_rtx (MEM, QImode,
+ plus_constant (XEXP (operands[0], 0), log2 / 8));
+ xoperands[1] = GEN_INT (log2 % 8);
+ output_asm_insn (\"set1 %1,%0\", xoperands);
+ }
+ return \"\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*v850_set1_3"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (ior:SI (match_dup 0)
+ (match_operand 1 "power_of_two_operand" "")))]
+ ""
+ "*
+{
+ int log2 = exact_log2 (INTVAL (operands[1]));
+
+ if (log2 < 8)
+ return \"set1 %M1,%0\";
+ else
+ {
+ rtx xoperands[2];
+ xoperands[0] = gen_rtx (MEM, QImode,
+ plus_constant (XEXP (operands[0], 0), log2 / 8));
+ xoperands[1] = GEN_INT (log2 % 8);
+ output_asm_insn (\"set1 %1,%0\", xoperands);
+ }
+ return \"\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,I,M")))]
+ ""
+ "@
+ or %2,%0
+ or %.,%0
+ ori %2,%1,%0"
+ [(set_attr "length" "2,2,4")
+ (set_attr "cc" "set_znv")])
+
+;; ----------------------------------------------------------------------
+;; XOR INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_insn "*v850_not1_1"
+ [(set (match_operand:QI 0 "memory_operand" "=m")
+ (subreg:QI (xor:SI (subreg:SI (match_dup 0) 0)
+ (match_operand 1 "power_of_two_operand" "")) 0))]
+ ""
+ "not1 %M1,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*v850_not1_2"
+ [(set (match_operand:HI 0 "memory_operand" "=m")
+ (subreg:HI (xor:SI (subreg:SI (match_dup 0) 0)
+ (match_operand 1 "power_of_two_operand" "")) 0))]
+ ""
+ "*
+{
+ int log2 = exact_log2 (INTVAL (operands[1]));
+
+ if (log2 < 8)
+ return \"not1 %M1,%0\";
+ else
+ {
+ rtx xoperands[2];
+ xoperands[0] = gen_rtx (MEM, QImode,
+ plus_constant (XEXP (operands[0], 0), log2 / 8));
+ xoperands[1] = GEN_INT (log2 % 8);
+ output_asm_insn (\"not1 %1,%0\", xoperands);
+ }
+ return \"\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+(define_insn "*v850_not1_3"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (xor:SI (match_dup 0)
+ (match_operand 1 "power_of_two_operand" "")))]
+ ""
+ "*
+{
+ int log2 = exact_log2 (INTVAL (operands[1]));
+
+ if (log2 < 8)
+ return \"not1 %M1,%0\";
+ else
+ {
+ rtx xoperands[2];
+ xoperands[0] = gen_rtx (MEM, QImode,
+ plus_constant (XEXP (operands[0], 0), log2 / 8));
+ xoperands[1] = GEN_INT (log2 % 8);
+ output_asm_insn (\"not1 %1,%0\", xoperands);
+ }
+ return \"\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r")
+ (match_operand:SI 2 "nonmemory_operand" "r,I,M")))]
+ ""
+ "@
+ xor %2,%0
+ xor %.,%0
+ xori %2,%1,%0"
+ [(set_attr "length" "2,2,4")
+ (set_attr "cc" "set_znv")])
+
+;; ----------------------------------------------------------------------
+;; NOT INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "not %1,%0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_znv")])
+
+;; -----------------------------------------------------------------
+;; BIT FIELDS
+;; -----------------------------------------------------------------
+;; Is it worth defining insv and extv for the V850 series?!?
+
+;; -----------------------------------------------------------------
+;; Scc INSTRUCTIONS
+;; -----------------------------------------------------------------
+
+(define_insn "sle"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (le:SI (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+ return 0;
+
+ return \"setf le,%0\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")])
+
+(define_insn "sleu"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (leu:SI (cc0) (const_int 0)))]
+ ""
+ "setf nh,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")])
+
+(define_insn "sge"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ge:SI (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+ return 0;
+
+ return \"setf ge,%0\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")])
+
+(define_insn "sgeu"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (geu:SI (cc0) (const_int 0)))]
+ ""
+ "setf nl,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")])
+
+(define_insn "slt"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lt:SI (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+ return 0;
+
+ return \"setf lt,%0\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")])
+
+(define_insn "sltu"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ltu:SI (cc0) (const_int 0)))]
+ ""
+ "setf l,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")])
+
+(define_insn "sgt"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (gt:SI (cc0) (const_int 0)))]
+ ""
+ "*
+{
+ if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
+ return 0;
+
+ return \"setf gt,%0\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")])
+
+(define_insn "sgtu"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (gtu:SI (cc0) (const_int 0)))]
+ ""
+ "setf h,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")])
+
+(define_insn "seq"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (eq:SI (cc0) (const_int 0)))]
+ ""
+ "setf z,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")])
+
+(define_insn "sne"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ne:SI (cc0) (const_int 0)))]
+ ""
+ "setf nz,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "none_0hit")])
+
+
+;; ----------------------------------------------------------------------
+;; JUMP INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+;; Conditional jump instructions
+
+(define_expand "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_expand "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "")
+
+(define_insn "*branch_normal"
+ [(set (pc)
+ (if_then_else (match_operator 1 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
+ && (GET_CODE (operands[1]) == GT
+ || GET_CODE (operands[1]) == GE
+ || GET_CODE (operands[1]) == LE
+ || GET_CODE (operands[1]) == LT))
+ return 0;
+
+ if (get_attr_length (insn) == 2)
+ return \"%b1 %l0\";
+ else
+ return \"%B1 .+6\;jr %l0\";
+}"
+ [(set (attr "length")
+ (if_then_else (lt (abs (minus (match_dup 0) (pc)))
+ (const_int 256))
+ (const_int 2)
+ (const_int 6)))
+ (set_attr "cc" "none")])
+
+(define_insn "*branch_invert"
+ [(set (pc)
+ (if_then_else (match_operator 1 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
+ && (GET_CODE (operands[1]) == GT
+ || GET_CODE (operands[1]) == GE
+ || GET_CODE (operands[1]) == LE
+ || GET_CODE (operands[1]) == LT))
+ return 0;
+ if (get_attr_length (insn) == 2)
+ return \"%B1 %l0\";
+ else
+ return \"%b1 .+6\;jr %l0\";
+}"
+ [(set (attr "length")
+ (if_then_else (lt (abs (minus (match_dup 0) (pc)))
+ (const_int 256))
+ (const_int 2)
+ (const_int 6)))
+ (set_attr "cc" "none")])
+
+;; Unconditional and other jump instructions.
+
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "*
+{
+ if (get_attr_length (insn) == 2)
+ return \"br %0\";
+ else
+ return \"jr %0\";
+}"
+ [(set (attr "length")
+ (if_then_else (lt (abs (minus (match_dup 0) (pc)))
+ (const_int 256))
+ (const_int 2)
+ (const_int 4)))
+ (set_attr "cc" "none")])
+
+(define_insn "indirect_jump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
+ ""
+ "jmp %0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "none")])
+
+(define_insn "tablejump"
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "jmp %0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "none")])
+
+;; Call subroutine with no return value.
+
+(define_expand "call"
+ [(call (match_operand:QI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" ""))]
+ ""
+ "
+{
+ if (! call_address_operand (XEXP (operands[0], 0))
+ || TARGET_LONG_CALLS)
+ XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
+ emit_call_insn (gen_call_internal (XEXP (operands[0], 0), operands[1]));
+ DONE;
+}")
+
+(define_insn "call_internal"
+ [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r"))
+ (match_operand:SI 1 "general_operand" "g,g"))
+ (clobber (reg:SI 31))]
+ ""
+ "@
+ jarl %0,r31
+ jarl .+4,r31\\n\\tadd 4,r31\\n\\tjmp %0"
+ [(set_attr "length" "4,8")])
+
+;; Call subroutine, returning value in operand 0
+;; (which must be a hard register).
+
+(define_expand "call_value"
+ [(set (match_operand 0 "" "")
+ (call (match_operand:QI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ ""
+ "
+{
+ if (! call_address_operand (XEXP (operands[1], 0))
+ || TARGET_LONG_CALLS)
+ XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
+ emit_call_insn (gen_call_value_internal (operands[0],
+ XEXP (operands[1], 0),
+ operands[2]));
+ DONE;
+}")
+
+(define_insn "call_value_internal"
+ [(set (match_operand 0 "" "=r,r")
+ (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r"))
+ (match_operand:SI 2 "general_operand" "g,g")))
+ (clobber (reg:SI 31))]
+ ""
+ "@
+ jarl %1,r31
+ jarl .+4,r31\\n\\tadd 4,r31\\n\\tjmp %1"
+ [(set_attr "length" "4,8")])
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop"
+ [(set_attr "length" "2")
+ (set_attr "cc" "none")])
+
+;; ----------------------------------------------------------------------
+;; EXTEND INSTRUCTIONS
+;; ----------------------------------------------------------------------
+
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI
+ (match_operand:HI 1 "register_operand" "r")))]
+ ""
+ "andi 65535,%1,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "set_znv")])
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI
+ (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "andi 255,%1,%0"
+ [(set_attr "length" "4")
+ (set_attr "cc" "set_znv")])
+
+;;- sign extension instructions
+
+(define_expand "extendhisi2"
+ [(set (match_dup 2)
+ (ashift:SI (match_operand:HI 1 "register_operand" "")
+ (const_int 16)))
+ (set (match_operand:SI 0 "register_operand" "")
+ (ashiftrt:SI (match_dup 2)
+ (const_int 16)))]
+ ""
+ "
+{
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_reg_rtx (SImode);
+}")
+
+(define_expand "extendqisi2"
+ [(set (match_dup 2)
+ (ashift:SI (match_operand:QI 1 "register_operand" "")
+ (const_int 24)))
+ (set (match_operand:SI 0 "register_operand" "")
+ (ashiftrt:SI (match_dup 2)
+ (const_int 24)))]
+ ""
+ "
+{
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_reg_rtx (SImode);
+}")
+
+;; ----------------------------------------------------------------------
+;; SHIFTS
+;; ----------------------------------------------------------------------
+
+(define_insn "ashlsi3"
+ [(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")))]
+ ""
+ "@
+ shl %2,%0
+ shl %2,%0"
+ [(set_attr "length" "4,2")
+ (set_attr "cc" "set_znv")])
+
+(define_insn "lshrsi3"
+ [(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")))]
+ ""
+ "@
+ shr %2,%0
+ shr %2,%0"
+ [(set_attr "length" "4,2")
+ (set_attr "cc" "set_znv")])
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ashiftrt:SI
+ (match_operand:SI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "r,N")))]
+ ""
+ "@
+ sar %2,%0
+ sar %2,%0"
+ [(set_attr "length" "4,2")
+ (set_attr "cc" "set_znv")])
+
+;; ----------------------------------------------------------------------
+;; PROLOGUE/EPILOGUE
+;; ----------------------------------------------------------------------
+(define_expand "prologue"
+ [(const_int 0)]
+ ""
+ "expand_prologue (); DONE;")
+
+(define_expand "epilogue"
+ [(return)]
+ ""
+ "
+{
+ /* Try to use the trivial return first. Else use the
+ full epilogue. */
+ if (0)
+ emit_jump_insn (gen_return ());
+ else
+ expand_epilogue ();
+ DONE;
+}")
+
+(define_insn "return"
+ [(return)]
+ "reload_completed && compute_frame_size (get_frame_size (), (long *)0) == 0"
+ "jmp [r31]"
+ [(set_attr "length" "2")
+ (set_attr "cc" "none")])
+
+(define_insn "return_internal"
+ [(return)
+ (use (reg:SI 31))]
+ ""
+ "jmp [r31]"
+ [(set_attr "length" "2")
+ (set_attr "cc" "none")])
+
+
+
+;; ----------------------------------------------------------------------
+;; HELPER INSTRUCTIONS for saving the prologue and epilog registers
+;; ----------------------------------------------------------------------
+
+;; Save r2, r20-r29, r31, and create 16 byte register call area
+(define_insn "save_r2_r31"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -64)))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 2))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 20))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 21))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 22))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -32))) (reg:SI 23))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -36))) (reg:SI 24))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -40))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -44))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -48))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -52))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -56))) (reg:SI 29))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -60))) (reg:SI 31))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r2_r31,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r20-r29, r31, and create 16 byte register call area
+(define_insn "save_r20_r31"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -60)))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 20))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 21))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 22))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 23))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -32))) (reg:SI 24))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -36))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -40))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -44))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -48))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -52))) (reg:SI 29))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -56))) (reg:SI 31))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r20_r31,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r21-r29, r31, and create 16 byte register call area
+(define_insn "save_r21_r31"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -56)))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 21))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 22))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 23))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 24))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -32))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -36))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -40))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -44))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -48))) (reg:SI 29))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -52))) (reg:SI 31))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r21_r31,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r22-r29, r31, and create 16 byte register call area
+(define_insn "save_r22_r31"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -52)))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 22))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 23))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 24))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -32))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -36))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -40))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -44))) (reg:SI 29))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -48))) (reg:SI 31))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r22_r31,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r23-r29, r31, and create 16 byte register call area
+(define_insn "save_r23_r31"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -48)))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 23))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 24))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -32))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -36))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -40))) (reg:SI 29))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -44))) (reg:SI 31))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r23_r31,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r24-r29, r31, and create 16 byte register call area
+(define_insn "save_r24_r31"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -44)))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 24))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -32))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -36))) (reg:SI 29))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -40))) (reg:SI 31))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r24_r31,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r25-r29, r31, and create 16 byte register call area
+(define_insn "save_r25_r31"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -40)))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -32))) (reg:SI 29))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -36))) (reg:SI 31))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r25_r31,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r26-r29, r31, and create 16 byte register call area
+(define_insn "save_r26_r31"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -36)))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 29))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -32))) (reg:SI 31))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r26_r31,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r27-r29, r31, and create 16 byte register call area
+(define_insn "save_r27_r31"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -32)))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 29))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 31))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r27_r31,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r28-r29, r31, and create 16 byte register call area
+(define_insn "save_r28_r31"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -28)))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 29))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 31))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r28_r31,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r29, r31, and create 16 byte register call area
+(define_insn "save_r29_r31"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -24)))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 29))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 31))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r29_r31,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r31, and create 16 byte register call area
+(define_insn "save_r31"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -20)))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 31))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r31,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r2, r20-r29
+(define_insn "save_r2_r29"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -44)))
+ (set (mem:SI (reg:SI 3)) (reg:SI 2))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 20))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 21))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 22))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 23))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 24))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -32))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -36))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -40))) (reg:SI 29))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r2_r29,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r20-r29
+(define_insn "save_r20_r29"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -40)))
+ (set (mem:SI (reg:SI 3)) (reg:SI 20))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 21))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 22))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 23))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 24))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -32))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -36))) (reg:SI 29))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r20_r29,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r21-r29
+(define_insn "save_r21_r29"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -36)))
+ (set (mem:SI (reg:SI 3)) (reg:SI 21))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 22))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 23))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 24))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -32))) (reg:SI 29))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r21_r29,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r22-r29
+(define_insn "save_r22_r29"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -32)))
+ (set (mem:SI (reg:SI 3)) (reg:SI 22))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 23))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 24))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -28))) (reg:SI 29))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r22_r29,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r23-r29
+(define_insn "save_r23_r29"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -28)))
+ (set (mem:SI (reg:SI 3)) (reg:SI 23))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 24))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -24))) (reg:SI 29))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r23_r29,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r24-r29
+(define_insn "save_r24_r29"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -24)))
+ (set (mem:SI (reg:SI 3)) (reg:SI 24))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -20))) (reg:SI 29))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r24_r29,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r25-r29
+(define_insn "save_r25_r29"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -20)))
+ (set (mem:SI (reg:SI 3)) (reg:SI 25))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 29))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r25_r29,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r26-r29
+(define_insn "save_r26_r29"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -16)))
+ (set (mem:SI (reg:SI 3)) (reg:SI 26))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 29))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r26_r29,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r27-r29
+(define_insn "save_r27_r29"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -12)))
+ (set (mem:SI (reg:SI 3)) (reg:SI 27))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 29))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r27_r29,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r28-r29
+(define_insn "save_r28_r29"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -8)))
+ (set (mem:SI (reg:SI 3)) (reg:SI 28))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 29))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r28_r29,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Save r29
+(define_insn "save_r29"
+ [(set (reg:SI 3) (plus:SI (reg:SI 3) (const_int -4)))
+ (set (mem:SI (reg:SI 3)) (reg:SI 29))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r29,r10"
+ [(set_attr "length" "4")
+ (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 5))
+ (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1))]
+ ""
+ "add -16,sp\;st.w r10,12[sp]\;jarl __save_interrupt,r10"
+ [(set_attr "length" "12")
+ (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
+;; all of memory. This blocks insns from being moved across this point.
+;; This is needed because the rest of the compiler is not reading to handle
+;; insns this compilcated
+
+(define_insn "save_all_interrupt"
+ [(unspec_volatile [(const_int 0)] 0)]
+ ""
+ "jarl __save_all_interrupt,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r2, r20-r29, r31, eliminate 16 byte register call area, and return to user
+(define_insn "restore_r2_r31"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 64)))
+ (set (reg:SI 2) (mem:SI (plus:SI (reg:SI 3) (const_int 60))))
+ (set (reg:SI 20) (mem:SI (plus:SI (reg:SI 3) (const_int 56))))
+ (set (reg:SI 21) (mem:SI (plus:SI (reg:SI 3) (const_int 52))))
+ (set (reg:SI 22) (mem:SI (plus:SI (reg:SI 3) (const_int 48))))
+ (set (reg:SI 23) (mem:SI (plus:SI (reg:SI 3) (const_int 44))))
+ (set (reg:SI 24) (mem:SI (plus:SI (reg:SI 3) (const_int 40))))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 36))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 32))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 31) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r2_r31"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r20-r29, r31, eliminate 16 byte register call area, and return to user
+(define_insn "restore_r20_r31"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 60)))
+ (set (reg:SI 20) (mem:SI (plus:SI (reg:SI 3) (const_int 56))))
+ (set (reg:SI 21) (mem:SI (plus:SI (reg:SI 3) (const_int 52))))
+ (set (reg:SI 22) (mem:SI (plus:SI (reg:SI 3) (const_int 48))))
+ (set (reg:SI 23) (mem:SI (plus:SI (reg:SI 3) (const_int 44))))
+ (set (reg:SI 24) (mem:SI (plus:SI (reg:SI 3) (const_int 40))))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 36))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 32))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 31) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r20_r31"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r21-r29, r31, eliminate 16 byte register call area, and return to user
+(define_insn "restore_r21_r31"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 56)))
+ (set (reg:SI 21) (mem:SI (plus:SI (reg:SI 3) (const_int 52))))
+ (set (reg:SI 22) (mem:SI (plus:SI (reg:SI 3) (const_int 48))))
+ (set (reg:SI 23) (mem:SI (plus:SI (reg:SI 3) (const_int 44))))
+ (set (reg:SI 24) (mem:SI (plus:SI (reg:SI 3) (const_int 40))))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 36))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 32))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 31) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r21_r31"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r22-r29, r31, eliminate 16 byte register call area, and return to user
+(define_insn "restore_r22_r31"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 52)))
+ (set (reg:SI 22) (mem:SI (plus:SI (reg:SI 3) (const_int 48))))
+ (set (reg:SI 23) (mem:SI (plus:SI (reg:SI 3) (const_int 44))))
+ (set (reg:SI 24) (mem:SI (plus:SI (reg:SI 3) (const_int 40))))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 36))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 32))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 31) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r22_r31"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r23-r29, r31, eliminate 16 byte register call area, and return to user
+(define_insn "restore_r23_r31"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 48)))
+ (set (reg:SI 23) (mem:SI (plus:SI (reg:SI 3) (const_int 44))))
+ (set (reg:SI 24) (mem:SI (plus:SI (reg:SI 3) (const_int 40))))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 36))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 32))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 31) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r23_r31"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r24-r29, r31, eliminate 16 byte register call area, and return to user
+(define_insn "restore_r24_r31"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 44)))
+ (set (reg:SI 24) (mem:SI (plus:SI (reg:SI 3) (const_int 40))))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 36))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 32))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 31) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r24_r31"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r25-r29, r31, eliminate 16 byte register call area, and return to user
+(define_insn "restore_r25_r31"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 40)))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 36))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 32))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 31) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r25_r31"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r26-r29, r31, eliminate 16 byte register call area, and return to user
+(define_insn "restore_r26_r31"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 36)))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 32))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 31) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r26_r31"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r27-r29, r31, eliminate 16 byte register call area, and return to user
+(define_insn "restore_r27_r31"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 32)))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 31) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r27_r31"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r28-r29, r31, eliminate 16 byte register call area, and return to user
+(define_insn "restore_r28_r31"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 28)))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 31) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r28_r31"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r29, r31, eliminate 16 byte register call area, and return to user
+(define_insn "restore_r29_r31"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 24)))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 31) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r29_r31"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r31, eliminate 16 byte register call area, and return to user
+(define_insn "restore_r31"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 20)))
+ (set (reg:SI 31) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r31"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r2, r20-r29, and return to user
+(define_insn "restore_r2_r29"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 48)))
+ (set (reg:SI 2) (mem:SI (plus:SI (reg:SI 3) (const_int 44))))
+ (set (reg:SI 20) (mem:SI (plus:SI (reg:SI 3) (const_int 40))))
+ (set (reg:SI 21) (mem:SI (plus:SI (reg:SI 3) (const_int 36))))
+ (set (reg:SI 22) (mem:SI (plus:SI (reg:SI 3) (const_int 32))))
+ (set (reg:SI 23) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 24) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r2_r29"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r20-r29, and return to user
+(define_insn "restore_r20_r29"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 44)))
+ (set (reg:SI 20) (mem:SI (plus:SI (reg:SI 3) (const_int 40))))
+ (set (reg:SI 21) (mem:SI (plus:SI (reg:SI 3) (const_int 36))))
+ (set (reg:SI 22) (mem:SI (plus:SI (reg:SI 3) (const_int 32))))
+ (set (reg:SI 23) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 24) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r20_r29"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r21-r29, and return to user
+(define_insn "restore_r21_r29"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 40)))
+ (set (reg:SI 21) (mem:SI (plus:SI (reg:SI 3) (const_int 36))))
+ (set (reg:SI 22) (mem:SI (plus:SI (reg:SI 3) (const_int 32))))
+ (set (reg:SI 23) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 24) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r21_r29"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r22-r29, and return to user
+(define_insn "restore_r22_r29"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 36)))
+ (set (reg:SI 22) (mem:SI (plus:SI (reg:SI 3) (const_int 32))))
+ (set (reg:SI 23) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 24) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r22_r29"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r23-r29, and return to user
+(define_insn "restore_r23_r29"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 32)))
+ (set (reg:SI 23) (mem:SI (plus:SI (reg:SI 3) (const_int 28))))
+ (set (reg:SI 24) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r23_r29"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r24-r29, and return to user
+(define_insn "restore_r24_r29"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 28)))
+ (set (reg:SI 24) (mem:SI (plus:SI (reg:SI 3) (const_int 24))))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r24_r29"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r25-r29, and return to user
+(define_insn "restore_r25_r29"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 24)))
+ (set (reg:SI 25) (mem:SI (plus:SI (reg:SI 3) (const_int 20))))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r25_r29"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r26-r29, and return to user
+(define_insn "restore_r26_r29"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 20)))
+ (set (reg:SI 26) (mem:SI (plus:SI (reg:SI 3) (const_int 16))))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r26_r29"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r27-r29, and return to user
+(define_insn "restore_r27_r29"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 16)))
+ (set (reg:SI 27) (mem:SI (plus:SI (reg:SI 3) (const_int 12))))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r27_r29"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r28-r29, and return to user
+(define_insn "restore_r28_r29"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 12)))
+ (set (reg:SI 28) (mem:SI (plus:SI (reg:SI 3) (const_int 8))))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r28_r29"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r29, and return to user
+(define_insn "restore_r29"
+ [(return)
+ (set (reg:SI 3) (plus:SI (reg:SI 3) (const_int 8)))
+ (set (reg:SI 29) (mem:SI (plus:SI (reg:SI 3) (const_int 4))))]
+ "TARGET_PROLOG_FUNCTION"
+ "jr __return_r29"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+
+;; Restore r1, r5, 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 5) (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")])
+
+;; 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 reading to handle
+;; insns this compilcated
+
+(define_insn "restore_all_interrupt"
+ [(unspec_volatile [(const_int 0)] 1)]
+ ""
+ "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))
+ (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))
+ (clobber (reg:SI 10))]
+ "TARGET_PROLOG_FUNCTION"
+ "jarl __save_r6_r9,r10"
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
+;; END CYGNUS LOCAL
diff --git a/gcc/config/v850/xm-v850.h b/gcc/config/v850/xm-v850.h
new file mode 100644
index 0000000..2d67cf8
--- /dev/null
+++ b/gcc/config/v850/xm-v850.h
@@ -0,0 +1,51 @@
+/* CYGNUS LOCAL entire file v850/law */
+/* Configuration for NEC V850.
+ Copyright (C) 1996 Free Software Foundation, Inc.
+ Contributed by Cygnus Support.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* #defines that need visibility everywhere. */
+#define FALSE 0
+#define TRUE 1
+
+/* This describes the machine the compiler is hosted on. */
+#define HOST_BITS_PER_CHAR 8
+#define HOST_BITS_PER_SHORT 16
+#define HOST_BITS_PER_INT 32
+#define HOST_BITS_PER_LONG 32
+#define HOST_BITS_PER_LONGLONG 64
+
+/* Arguments to use with `exit'. */
+#define SUCCESS_EXIT_CODE 0
+#define FATAL_EXIT_CODE 33
+
+#ifdef __v850__
+#ifndef __STDC__
+extern char *malloc (), *realloc (), *calloc ();
+#else
+extern void *malloc (), *realloc (), *calloc ();
+#endif
+extern void free ();
+#endif
+
+/* target machine dependencies.
+ tm.h is a symbolic link to the actual target specific file. */
+
+#include "tm.h"
+/* END CYGNUS LOCAL */