OSDN Git Service

Fri Sep 5 10:08:44 1997 Jeffrey A Law (law@cygnus.com)
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 5 Sep 1997 17:41:24 +0000 (17:41 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 5 Sep 1997 17:41:24 +0000 (17:41 +0000)
        * 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@15103 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/v850/lib1funcs.asm [new file with mode: 0644]
gcc/config/v850/t-v850 [new file with mode: 0644]
gcc/config/v850/v850.c [new file with mode: 0644]
gcc/config/v850/v850.h [new file with mode: 0644]
gcc/config/v850/v850.md [new file with mode: 0644]
gcc/config/v850/xm-v850.h [new file with mode: 0644]

diff --git a/gcc/config/v850/lib1funcs.asm b/gcc/config/v850/lib1funcs.asm
new file mode 100644 (file)
index 0000000..d441590
--- /dev/null
@@ -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 (file)
index 0000000..5203441
--- /dev/null
@@ -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 (file)
index 0000000..6435d40
--- /dev/null
@@ -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;
+
+\f
+/* 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);
+           }
+       }
+    }
+}
+
+\f
+/* Output assembly code for the start of the file.  */
+
+void
+asm_file_start (file)
+     FILE *file;
+{
+  output_file_directive (file, main_input_filename);
+}
+\f
+
+/* 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;
+}
+
+\f
+/* 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;
+}
+
+\f
+/* 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);
+}
+
+\f
+/* 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;
+    }
+}
+
+\f
+/* 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;
+
+    }
+}
+
+\f
+/* 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;
+    }
+}
+
+\f
+/* 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 "";
+}
+
+\f
+/* 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";
+}
+
+\f
+/* 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;
+}
+
+\f
+/* 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);
+}
+
+\f
+/* 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;
+                   }
+               }
+           }
+       }
+    }
+}
+
+\f
+/* # 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);
+}
+
+\f
+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);
+}
+\f
+
+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;
+}
+
+\f
+/* 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;
+    }
+}
+
+\f
+/* 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;
+}
+
+\f
+/* 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;
+}
+
+\f
+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 (file)
index 0000000..2a05aef
--- /dev/null
@@ -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);                  \
+}
+
+\f
+/* 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
+\f
+/* 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)
+
+\f
+/* 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)
+
+\f
+/* 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
+
+\f
+/* 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.  */
+
+\f
+/* 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)
+\f
+/* 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)
+
+\f
+/* 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)
+
+\f
+/* 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 (file)
index 0000000..30ebf87
--- /dev/null
@@ -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"))
+\f
+;; 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)
+
+\f
+;; ----------------------------------------------------------------------
+;; 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")])
+
+\f
+;; ----------------------------------------------------------------------
+;; 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")])
+\f
+;; ----------------------------------------------------------------------
+;; 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")])
+
+\f
+;; ----------------------------------------------------------------------
+;; 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")])
+\f
+;; ----------------------------------------------------------------------
+;; 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")])
+\f
+;; -----------------------------------------------------------------
+;; 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")])
+
+\f
+;; ----------------------------------------------------------------------
+;; 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")])
+\f
+;; ----------------------------------------------------------------------
+;; 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);
+}")
+\f
+;; ----------------------------------------------------------------------
+;; 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")])
+
+
+\f
+;; ----------------------------------------------------------------------
+;; 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 (file)
index 0000000..2d67cf8
--- /dev/null
@@ -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 */